Overview

Namespaces

  • Evenement
  • None
  • PHP
  • Psr
    • Http
      • Message
  • Ratchet
    • Http
    • RFC6455
      • Handshake
      • Messaging
    • Server
    • Session
      • Serialize
      • Storage
        • Proxy
    • Wamp
    • WebSocket
  • React
    • EventLoop
      • Tick
      • Timer
    • Socket
    • Stream
  • Symfony
    • Component
      • HttpFoundation
        • Session
          • Attribute
          • Flash
          • Storage
            • Handler
            • Proxy
      • Routing
        • Annotation
        • Exception
        • Generator
          • Dumper
        • Loader
          • DependencyInjection
        • Matcher
          • Dumper
        • Tests
          • Annotation
          • Fixtures
            • AnnotatedClasses
            • OtherAnnotatedClasses
          • Generator
            • Dumper
          • Loader
          • Matcher
            • Dumper

Classes

  • EchoServer
  • FlashPolicy
  • IoConnection
  • IoServer
  • IpBlackList
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: namespace Ratchet\Server;
  3: use Ratchet\MessageComponentInterface;
  4: use Ratchet\ConnectionInterface;
  5: 
  6: /**
  7:  * An app to go on a server stack to pass a policy file to a Flash socket
  8:  * Useful if you're using Flash as a WebSocket polyfill on IE
  9:  * Be sure to run your server instance on port 843
 10:  * By default this lets accepts everything, make sure you tighten the rules up for production
 11:  * @final
 12:  * @link http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html
 13:  * @link http://learn.adobe.com/wiki/download/attachments/64389123/CrossDomain_PolicyFile_Specification.pdf?version=1
 14:  * @link view-source:http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd
 15:  */
 16: class FlashPolicy implements MessageComponentInterface {
 17: 
 18:     /**
 19:      * Contains the root policy node
 20:      * @var string
 21:      */
 22:     protected $_policy = '<?xml version="1.0"?><!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"><cross-domain-policy></cross-domain-policy>';
 23: 
 24:     /**
 25:      * Stores an array of allowed domains and their ports
 26:      * @var array
 27:      */
 28:     protected $_access = array();
 29: 
 30:     /**
 31:      * @var string
 32:      */
 33:     protected $_siteControl = '';
 34: 
 35:     /**
 36:      * @var string
 37:      */
 38:     protected $_cache = '';
 39: 
 40:     /**
 41:      * @var string
 42:      */
 43:     protected $_cacheValid = false;
 44: 
 45:     /**
 46:      * Add a domain to an allowed access list.
 47:      *
 48:      * @param string $domain Specifies a requesting domain to be granted access. Both named domains and IP
 49:      * addresses are acceptable values. Subdomains are considered different domains. A wildcard (*) can
 50:      * be used to match all domains when used alone, or multiple domains (subdomains) when used as a
 51:      * prefix for an explicit, second-level domain name separated with a dot (.)
 52:      * @param string $ports A comma-separated list of ports or range of ports that a socket connection
 53:      * is allowed to connect to. A range of ports is specified through a dash (-) between two port numbers.
 54:      * Ranges can be used with individual ports when separated with a comma. A single wildcard (*) can
 55:      * be used to allow all ports.
 56:      * @param bool $secure
 57:      * @throws \UnexpectedValueException
 58:      * @return FlashPolicy
 59:      */
 60:     public function addAllowedAccess($domain, $ports = '*', $secure = false) {
 61:         if (!$this->validateDomain($domain)) {
 62:            throw new \UnexpectedValueException('Invalid domain');
 63:         }
 64: 
 65:         if (!$this->validatePorts($ports)) {
 66:            throw new \UnexpectedValueException('Invalid Port');
 67:         }
 68: 
 69:         $this->_access[]   = array($domain, $ports, (boolean)$secure);
 70:         $this->_cacheValid = false;
 71: 
 72:         return $this;
 73:     }
 74:     
 75:     /**
 76:      * Removes all domains from the allowed access list.
 77:      * 
 78:      * @return \Ratchet\Server\FlashPolicy
 79:      */
 80:     public function clearAllowedAccess() {
 81:         $this->_access      = array();
 82:         $this->_cacheValid = false;
 83: 
 84:         return $this;
 85:     }
 86: 
 87:     /**
 88:      * site-control defines the meta-policy for the current domain. A meta-policy specifies acceptable
 89:      * domain policy files other than the master policy file located in the target domain's root and named
 90:      * crossdomain.xml.
 91:      *
 92:      * @param string $permittedCrossDomainPolicies
 93:      * @throws \UnexpectedValueException
 94:      * @return FlashPolicy
 95:      */
 96:     public function setSiteControl($permittedCrossDomainPolicies = 'all') {
 97:         if (!$this->validateSiteControl($permittedCrossDomainPolicies)) {
 98:             throw new \UnexpectedValueException('Invalid site control set');
 99:         }
100: 
101:         $this->_siteControl = $permittedCrossDomainPolicies;
102:         $this->_cacheValid  = false;
103: 
104:         return $this;
105:     }
106: 
107:     /**
108:      * {@inheritdoc}
109:      */
110:     public function onOpen(ConnectionInterface $conn) {
111:     }
112: 
113:     /**
114:      * {@inheritdoc}
115:      */
116:     public function onMessage(ConnectionInterface $from, $msg) {
117:         if (!$this->_cacheValid) {
118:             $this->_cache      = $this->renderPolicy()->asXML();
119:             $this->_cacheValid = true;
120:         }
121: 
122:         $from->send($this->_cache . "\0");
123:         $from->close();
124:     }
125: 
126:     /**
127:      * {@inheritdoc}
128:      */
129:     public function onClose(ConnectionInterface $conn) {
130:     }
131: 
132:     /**
133:      * {@inheritdoc}
134:      */
135:     public function onError(ConnectionInterface $conn, \Exception $e) {
136:         $conn->close();
137:     }
138: 
139:     /**
140:      * Builds the crossdomain file based on the template policy
141:      *
142:      * @throws \UnexpectedValueException
143:      * @return \SimpleXMLElement
144:      */
145:     public function renderPolicy() {
146:         $policy = new \SimpleXMLElement($this->_policy);
147: 
148:         $siteControl = $policy->addChild('site-control');
149: 
150:         if ($this->_siteControl == '') {
151:             $this->setSiteControl();
152:         }
153: 
154:         $siteControl->addAttribute('permitted-cross-domain-policies', $this->_siteControl);
155: 
156:         if (empty($this->_access)) {
157:             throw new \UnexpectedValueException('You must add a domain through addAllowedAccess()');
158:         }
159: 
160:         foreach ($this->_access as $access) {
161:             $tmp = $policy->addChild('allow-access-from');
162:             $tmp->addAttribute('domain', $access[0]);
163:             $tmp->addAttribute('to-ports', $access[1]);
164:             $tmp->addAttribute('secure', ($access[2] === true) ? 'true' : 'false');
165:         }
166: 
167:         return $policy;
168:     }
169: 
170:     /**
171:      * Make sure the proper site control was passed
172:      *
173:      * @param string $permittedCrossDomainPolicies
174:      * @return bool
175:      */
176:     public function validateSiteControl($permittedCrossDomainPolicies) {
177:         //'by-content-type' and 'by-ftp-filename' are not available for sockets
178:         return (bool)in_array($permittedCrossDomainPolicies, array('none', 'master-only', 'all'));
179:     }
180: 
181:     /**
182:      * Validate for proper domains (wildcards allowed)
183:      *
184:      * @param string $domain
185:      * @return bool
186:      */
187:     public function validateDomain($domain) {
188:         return (bool)preg_match("/^((http(s)?:\/\/)?([a-z0-9-_]+\.|\*\.)*([a-z0-9-_\.]+)|\*)$/i", $domain);
189:     }
190: 
191:     /**
192:      * Make sure valid ports were passed
193:      *
194:      * @param string $port
195:      * @return bool
196:      */
197:     public function validatePorts($port) {
198:         return (bool)preg_match('/^(\*|(\d+[,-]?)*\d+)$/', $port);
199:     }
200: }
201: 
Ratchet API documentation generated by ApiGen 2.8.0