3 <title>FlashPolicyFileServer</title>
4 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
8 font: 14px/1.5 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
15 text-decoration: underline;
27 border-collapse: collapse;
29 table#source td:first-child {
30 padding: 30px 40px 30px 40px;
33 table#source td:first-child,
34 table#source td:first-child pre {
37 table#source td:last-child {
38 padding: 30px 0 30px 40px;
39 border-left: 1px solid #E5E5EE;
43 border-bottom: 1px solid #E5E5EE;
45 table#source tr.filename {
47 border-top: 1px solid #E5E5EE;
49 table#source tr.filename td:first-child {
50 text-transform: capitalize;
52 table#source tr.filename td:last-child {
55 table#source tr.filename h2 {
60 table#source tr.code h1,
61 table#source tr.code h2,
62 table#source tr.code h3 {
64 font-family: "Lucida Grande", "Helvetica Nueue", Arial, sans-serif;
67 table#source tr.code h2 {
70 table#source tr.code h3 {
73 table#source tr.code ul {
74 margin: 15px 0 15px 35px;
77 table#source tr.code ul li {
81 table#source tr.code ul li p {
85 table#source tr.code td:first-child pre {
93 code .string { color: #219161; }
94 code .regexp { color: #219161; }
95 code .keyword { color: #954121; }
96 code .number { color: #19469D; }
97 code .comment { color: #bbb; }
98 code .this { color: #19469D; }</style>
102 $('tr.filename').toggle(function(){
103 $(this).nextUntil('.filename').fadeIn();
105 $(this).nextUntil('.filename').fadeOut();
111 <table id="source"><tbody><tr><td><h1>FlashPolicyFileServer</h1></td><td></td></tr><tr class="filename"><td><h2 id="lib/server.js"><a href="#">server</a></h2></td><td>lib/server.js</td></tr><tr class="code">
113 <p>Module dependencies and cached references.
117 <pre><code><span class="keyword">var</span> <span class="variable">slice</span> = <span class="class">Array</span>.<span class="variable">prototype</span>.<span class="variable">slice</span>
118 , <span class="variable">net</span> = <span class="variable">require</span>(<span class="string">'net'</span>);</code></pre>
123 <p>The server that does the Policy File severing</p>
127 <ul><li><code>log</code> false or a function that can output log information, defaults to console.log?</li></ul>
131 <ul><li><p><strong>param</strong>: <em>Object</em> options Options to customize the servers functionality.</p></li><li><p><strong>param</strong>: <em>Array</em> origins The origins that are allowed on this server, defaults to <code>*:*</code>.</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
134 <pre><code><span class="keyword">function</span> <span class="class">Server</span>(<span class="variable">options</span>, <span class="variable">origins</span>){
135 <span class="keyword">var</span> <span class="variable">me</span> = <span class="this">this</span>;
137 <span class="this">this</span>.<span class="variable">origins</span> = <span class="variable">origins</span> || [<span class="string">'*:*'</span>];
138 <span class="this">this</span>.<span class="variable">port</span> = <span class="number integer">843</span>;
139 <span class="this">this</span>.<span class="variable">log</span> = <span class="variable">console</span>.<span class="variable">log</span>;
141 <span class="comment">// merge `this` with the options</span>
142 <span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">options</span>).<span class="variable">forEach</span>(<span class="keyword">function</span>(<span class="variable">key</span>){
143 <span class="variable">me</span>[<span class="variable">key</span>] &<span class="variable">amp</span>;&<span class="variable">amp</span>; (<span class="variable">me</span>[<span class="variable">key</span>] = <span class="variable">options</span>[<span class="variable">key</span>])
146 <span class="comment">// create the net server</span>
147 <span class="this">this</span>.<span class="variable">socket</span> = <span class="variable">net</span>.<span class="variable">createServer</span>(<span class="keyword">function</span> <span class="variable">createServer</span>(<span class="variable">socket</span>){
148 <span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'error'</span>, <span class="keyword">function</span> <span class="variable">socketError</span>(){ <span class="variable">me</span>.<span class="variable">responder</span>.<span class="variable">call</span>(<span class="variable">me</span>, <span class="variable">socket</span>) });
149 <span class="variable">me</span>.<span class="variable">responder</span>.<span class="variable">call</span>(<span class="variable">me</span>, <span class="variable">socket</span>);
152 <span class="comment">// Listen for errors as the port might be blocked because we do not have root priv.</span>
153 <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'error'</span>, <span class="keyword">function</span> <span class="variable">serverError</span>(<span class="variable">err</span>){
154 <span class="comment">// Special and common case error handling</span>
155 <span class="keyword">if</span> (<span class="variable">err</span>.<span class="variable">errno</span> == <span class="number integer">13</span>){
156 <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(
157 <span class="string">'Unable to listen to port `'</span> + <span class="variable">me</span>.<span class="variable">port</span> + <span class="string">'` as your Node.js instance does not have root privileges. '</span> +
159 <span class="variable">me</span>.<span class="variable">server</span>
160 ? <span class="string">'The Flash Policy file will now be served inline over the supplied HTTP server, Flash Policy files request will suffer.'</span>
161 : <span class="string">'No fallback server supplied.'</span>
165 <span class="variable">me</span>.<span class="variable">socket</span>.<span class="variable">removeAllListeners</span>();
166 <span class="keyword">delete</span> <span class="variable">me</span>.<span class="variable">socket</span>;
168 <span class="variable">me</span>.<span class="variable">emit</span>(<span class="string">'connect_failed'</span>, <span class="variable">err</span>);
169 } <span class="keyword">else</span> {
170 <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'FlashPolicyFileServer received a error event:\n'</span> + (<span class="variable">err</span>.<span class="variable">message</span> ? <span class="variable">err</span>.<span class="variable">message</span> : <span class="variable">err</span>));
174 <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'timeout'</span>, <span class="keyword">function</span> <span class="variable">serverTimeout</span>(){});
175 <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'close'</span>, <span class="keyword">function</span> <span class="variable">serverClosed</span>(<span class="variable">err</span>){
176 <span class="variable">err</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'Server closing due to an error: \n'</span> + (<span class="variable">err</span>.<span class="variable">message</span> ? <span class="variable">err</span>.<span class="variable">message</span> : <span class="variable">err</span>));
178 <span class="keyword">if</span> (<span class="variable">me</span>.<span class="variable">server</span>){
179 <span class="comment">// not online anymore</span>
180 <span class="keyword">delete</span> <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">online</span>;
182 <span class="comment">// Remove the inline policy listener if we close down</span>
183 <span class="comment">// but only when the server was `online` (see listen prototype)</span>
184 <span class="keyword">if</span>( <span class="variable">me</span>.<span class="variable">server</span>[<span class="string">'@'</span>] &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">online</span>){
185 <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">removeListener</span>(<span class="string">'connection'</span>, <span class="variable">me</span>.<span class="variable">server</span>[<span class="string">'@'</span>]);
188 <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'Shutting down FlashPolicyFileServer'</span>);
191 <span class="comment">// Compile the initial `buffer`</span>
192 <span class="this">this</span>.<span class="variable">compile</span>();
198 <p>Start listening for requests</p>
202 <ul><li><p><strong>param</strong>: <em>Number</em> port The port number it should be listening to.</p></li><li><p><strong>param</strong>: <em>Server</em> server A HTTP server instance, this will be used to listen for inline requests</p></li><li><p><strong>param</strong>: <em>Function</em> cb The callback needs to be called once server is ready</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
205 <pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">listen</span> = <span class="keyword">function</span> <span class="variable">listen</span>(<span class="variable">port</span>, <span class="variable">server</span>, <span class="variable">cb</span>){
206 <span class="keyword">var</span> <span class="variable">me</span> = <span class="this">this</span>
207 , <span class="variable">args</span> = <span class="variable">slice</span>.<span class="variable">call</span>(<span class="variable">arguments</span>, <span class="number integer">0</span>)
208 , <span class="variable">callback</span>;
210 <span class="comment">// assign the correct vars, for flexible arguments</span>
211 <span class="variable">args</span>.<span class="variable">forEach</span>(<span class="keyword">function</span> <span class="variable">args</span>(<span class="variable">arg</span>){
212 <span class="keyword">var</span> <span class="variable">type</span> = <span class="keyword">typeof</span> <span class="variable">arg</span>;
214 <span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'number'</span>) <span class="variable">me</span>.<span class="variable">port</span> = <span class="variable">arg</span>;
215 <span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'function'</span>) <span class="variable">callback</span> = <span class="variable">arg</span>;
216 <span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'object'</span>) <span class="variable">me</span>.<span class="variable">server</span> = <span class="variable">arg</span>;
219 <span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">server</span>){
221 <span class="comment">// no one in their right mind would ever create a `@` prototype, so Im just gonna store</span>
222 <span class="comment">// my function on the server, so I can remove it later again once the server(s) closes</span>
223 <span class="this">this</span>.<span class="variable">server</span>[<span class="string">'@'</span>] = <span class="keyword">function</span> <span class="variable">connection</span>(<span class="variable">socket</span>){
224 <span class="variable">socket</span>.<span class="variable">once</span>(<span class="string">'data'</span>, <span class="keyword">function</span> <span class="variable">requestData</span>(<span class="variable">data</span>){
225 <span class="comment">// if it's a Flash policy request, and we can write to the </span>
226 <span class="keyword">if</span> (
227 <span class="variable">data</span>
228 &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">data</span>[<span class="number integer">0</span>] === <span class="number integer">60</span>
229 &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">data</span>.<span class="variable">toString</span>() === <span class="string">'<policy-file-request/>\0'</span>
230 &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">socket</span>
231 &<span class="variable">amp</span>;&<span class="variable">amp</span>; (<span class="variable">socket</span>.<span class="variable">readyState</span> === <span class="string">'open'</span> || <span class="variable">socket</span>.<span class="variable">readyState</span> === <span class="string">'writeOnly'</span>)
233 <span class="comment">// send the buffer</span>
234 <span class="variable">socket</span>.<span class="variable">end</span>(<span class="variable">me</span>.<span class="variable">buffer</span>);
238 <span class="comment">// attach it</span>
239 <span class="this">this</span>.<span class="variable">server</span>.<span class="variable">on</span>(<span class="string">'connection'</span>, <span class="this">this</span>.<span class="variable">server</span>[<span class="string">'@'</span>]);
242 <span class="comment">// We add a callback method, so we can set a flag for when the server is `enabled` or `online`.</span>
243 <span class="comment">// this flag is needed because if a error occurs and the we cannot boot up the server the</span>
244 <span class="comment">// fallback functionality should not be removed during the `close` event</span>
245 <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">listen</span>(<span class="this">this</span>.<span class="variable">port</span>, <span class="keyword">function</span> <span class="variable">serverListening</span>(){
246 <span class="variable">me</span>.<span class="variable">socket</span>.<span class="variable">online</span> = <span class="variable">true</span>;
248 <span class="keyword">if</span> (<span class="variable">callback</span>) <span class="variable">callback</span>(), <span class="variable">callback</span> = <span class="variable">undefined</span>;
252 <span class="keyword">return</span> <span class="this">this</span>;
258 <p>Adds a new origin to the Flash Policy File.</p>
262 <ul><li><p><strong>param</strong>: <em>Arguments</em> The origins that need to be added.</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
265 <pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">add</span> = <span class="keyword">function</span> <span class="variable">add</span>(){
266 <span class="keyword">var</span> <span class="variable">args</span> = <span class="variable">slice</span>.<span class="variable">call</span>(<span class="variable">arguments</span>, <span class="number integer">0</span>)
267 , <span class="variable">i</span> = <span class="variable">args</span>.<span class="variable">length</span>;
269 <span class="comment">// flag duplicates</span>
270 <span class="keyword">while</span> (<span class="variable">i</span>--){
271 <span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">indexOf</span>(<span class="variable">args</span>[<span class="variable">i</span>]) &<span class="variable">gt</span>;= <span class="number integer">0</span>){
272 <span class="variable">args</span>[<span class="variable">i</span>] = <span class="keyword">null</span>;
276 <span class="comment">// Add all the arguments to the array</span>
277 <span class="comment">// but first we want to remove all `falsy` values from the args</span>
278 <span class="class">Array</span>.<span class="variable">prototype</span>.<span class="variable">push</span>.<span class="variable">apply</span>(
279 <span class="this">this</span>.<span class="variable">origins</span>
280 , <span class="variable">args</span>.<span class="variable">filter</span>(<span class="keyword">function</span>(<span class="variable">value</span>){ <span class="keyword">return</span> !!<span class="variable">value</span> })
283 <span class="this">this</span>.<span class="variable">compile</span>();
284 <span class="keyword">return</span> <span class="this">this</span>;
290 <p>Removes a origin from the Flash Policy File.</p>
294 <ul><li><p><strong>param</strong>: <em>String</em> origin The origin that needs to be removed from the server</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
297 <pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">remove</span> = <span class="keyword">function</span> <span class="variable">remove</span>(<span class="variable">origin</span>){
298 <span class="keyword">var</span> <span class="variable">position</span> = <span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">indexOf</span>(<span class="variable">origin</span>);
300 <span class="comment">// only remove and recompile if we have a match</span>
301 <span class="keyword">if</span> (<span class="variable">position</span> &<span class="variable">gt</span>; <span class="number integer">0</span>){
302 <span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">splice</span>(<span class="variable">position</span>,<span class="number integer">1</span>);
303 <span class="this">this</span>.<span class="variable">compile</span>();
306 <span class="keyword">return</span> <span class="this">this</span>;
312 <p>Closes and cleans up the server</p>
314 <ul><li><p><strong>api</strong>: <em>public</em></p></li></ul>
317 <pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">close</span> = <span class="keyword">function</span> <span class="variable">close</span>(){
318 <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">removeAllListeners</span>();
319 <span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">close</span>();
321 <span class="keyword">return</span> <span class="this">this</span>;
327 <p>Proxy the event listener requests to the created Net server
331 <pre><code><span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">process</span>.<span class="class">EventEmitter</span>.<span class="variable">prototype</span>).<span class="variable">forEach</span>(<span class="keyword">function</span> <span class="variable">proxy</span>(<span class="variable">key</span>){
332 <span class="class">Server</span>.<span class="variable">prototype</span>[<span class="variable">key</span>] = <span class="class">Server</span>.<span class="variable">prototype</span>[<span class="variable">key</span>] || <span class="keyword">function</span> (){
333 <span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">socket</span>) <span class="this">this</span>.<span class="variable">socket</span>[<span class="variable">key</span>].<span class="variable">apply</span>(<span class="this">this</span>.<span class="variable">socket</span>, <span class="variable">arguments</span>);
334 <span class="keyword">return</span> <span class="this">this</span>;
341 <p>Creates a new server instance.</p>
345 <ul><li><p><strong>param</strong>: <em>Object</em> options A options object to override the default config</p></li><li><p><strong>param</strong>: <em>Array</em> origins The origins that should be allowed by the server</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
348 <pre><code><span class="variable">exports</span>.<span class="variable">createServer</span> = <span class="keyword">function</span> <span class="variable">createServer</span>(<span class="variable">options</span>, <span class="variable">origins</span>){
349 <span class="variable">origins</span> = <span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">origins</span>) ? <span class="variable">origins</span> : (<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">options</span>) ? <span class="variable">options</span> : <span class="variable">false</span>);
350 <span class="variable">options</span> = !<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">options</span>) &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">options</span> ? <span class="variable">options</span> : {};
352 <span class="keyword">return</span> <span class="keyword">new</span> <span class="class">Server</span>(<span class="variable">options</span>, <span class="variable">origins</span>);
358 <p>Provide a hook to the original server, so it can be extended if needed.
362 <pre><code><span class="variable">exports</span>.<span class="class">Server</span> = <span class="class">Server</span>;</code></pre>
371 <pre><code><span class="variable">exports</span>.<span class="variable">version</span> = <span class="string">'0.0.2'</span>;
375 </html></tbody></table>