├── .gitignore ├── ChangeLog ├── LICENCE ├── README.md ├── build.xml ├── composer.json ├── examples ├── AMF3Client.php ├── callbackserver.php ├── client.php └── server.php ├── integrations └── drupal │ └── module │ └── sabreamf │ ├── CHANGELOG.txt │ ├── COPYING.txt │ ├── HELP.txt │ ├── INSTALL.txt │ ├── README.txt │ ├── SabreAMF │ └── README.txt │ ├── TODO.txt │ ├── examples │ ├── README.txt │ ├── TODO.txt │ └── drupalclient │ │ ├── AC_RunActiveContent.js │ │ ├── example.fla │ │ ├── example.swf │ │ ├── index.html │ │ └── ro │ │ └── gion │ │ └── drupal │ │ └── remoting │ │ └── DrupalService.as │ ├── media │ ├── images │ │ ├── gateway.png │ │ └── sabreamf.png │ └── styles │ │ ├── reset.css │ │ └── sabreamf.css │ ├── sabreamf.info │ ├── sabreamf.module │ └── tests │ └── ping_client.php └── lib └── SabreAMF ├── AMF0 ├── Const.php ├── Deserializer.php └── Serializer.php ├── AMF3 ├── AbstractMessage.php ├── AcknowledgeMessage.php ├── CommandMessage.php ├── Const.php ├── Deserializer.php ├── ErrorMessage.php ├── RemotingMessage.php ├── Serializer.php └── Wrapper.php ├── ArrayCollection.php ├── ByteArray.php ├── CallbackServer.php ├── ClassMapper.php ├── ClassNotFoundException.php ├── Client.php ├── Const.php ├── Deserializer.php ├── DetailException.php ├── Externalized.php ├── ITypedObject.php ├── InputStream.php ├── InvalidAMFException.php ├── Message.php ├── OutputStream.php ├── RecordSet.php ├── Serializer.php ├── Server.php ├── TypedObject.php ├── UndefinedMethodException.php └── tests ├── README ├── alltests.php ├── amf3.php └── amf3 └── int.php /.gitignore: -------------------------------------------------------------------------------- 1 | # composer 2 | vendor 3 | composer.lock 4 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | SabreAMF 1.4 - 2013-??-?? 2 | * Added: Now a composer package. 3 | 4 | SabreAMF 1.3 - 2009-06-27 5 | * Fixed: Issue 6: Invalid command operation 12 6 | * Fixed: AMF3 deserialization improvements on 64bit machines and various 7 | other bugs (thanks Asbjorn) 8 | * Fixed: Issue 11: AMF0 array reference bugs fixed 9 | * Fixed: AMF0 classmapping bugs 10 | * Fixed: Bug in recordset object notation 11 | * New: If invalid AMF is received, we send back a more specific 12 | exception (thanks Asbjorn) 13 | * New: Drupal integration module (separate download) (thanks Ionut) 14 | 15 | Older: 16 | * Changelogs to follow, if anyone is interested 17 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2006-2009 Rooftop Solutions. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the SabreAMF nor the names of its contributors 13 | may be used to endorse or promote products derived from this software 14 | without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sabre/amf 2 | ========= 3 | 4 | sabre/amf is a AMF server/client for PHP. AMF stands for Action Message Format, 5 | and is the format Flash/ActionScript uses for communicating with servers 6 | (a.k.a. remoting). 7 | 8 | This project is largely unmaintained since 2009, as both flash and this method 9 | of communication has fallen out of favor. It's kept around because it should 10 | still work. 11 | 12 | Some information about this can be found [on my blog][1] 13 | 14 | Copyright (C) 2006-2013 Rooftop Solutions. All rights reserved. 15 | 16 | Documentation, bug reports, downloads 17 | 18 | [http://code.google.com/p/sabreamf/][2] 19 | 20 | SabreAMF is distributed under a BSD licence. Please check the LICENCE file for more information. 21 | 22 | Credits 23 | ------- 24 | 25 | Main Author: 26 | * [Evert Pot][3] 27 | 28 | Bugfixes, suggestions, improvements: 29 | * [Karl von Randow][4] 30 | * [Renaun Erickson][5] 31 | * [Asbjørn Sloth Tønnesen][6] 32 | * [Matt Humphrey][7] 33 | 34 | [See all contributors](https://github.com/evert/SabreAMF/graphs/contributors) 35 | 36 | Drupal integration: 37 | * Ionut Stoica 38 | 39 | Thanks to: 40 | * Kevin Langdon, author of ServiceCapture for making the first big steps in decoding the AMF3 spec and helping out when i got stuck 41 | * The AMFPHP team for their excellent piece of software. 42 | * The OSFlash community for opening up the Flash Platform. 43 | * PyAMF project 44 | 45 | [1]: http://evertpot.com/throwing-in-the-towel-with-sabreamf-and-dropbox-php-lib/ 46 | [2]: http://code.google.com/p/sabreamf/ 47 | [3]: http://evertpot.com/ 48 | [4]: http://xk72.com/blog 49 | [5]: http://renaun.com/blog 50 | [6]: http://lila.io 51 | [7]: http://m4tt.io 52 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sabre/amf", 3 | "description" : "SabreAMF is a Flash Remoting server and client for PHP", 4 | "keywords" : [ "Flash", "ActionScript", "Remoting", "AMF", "AMF0", "AMF3" ], 5 | "homepage" : "http://code.google.com/p/sabreamf/", 6 | "license" : "BSD-3-Clause", 7 | "require" : { 8 | "php" : ">=5.2.1" 9 | }, 10 | "require-dev" : { 11 | "phing/phing" : "*", 12 | "phpunit/phpunit" : "*" 13 | }, 14 | "authors" : [ 15 | { 16 | "name" : "Evert Pot", 17 | "email" : "evert@rooftopsolutions.nl", 18 | "homepage" : "http://evertpot.com/", 19 | "role" : "Developer" 20 | } 21 | ], 22 | "support" : { 23 | "source" : "https://github.com/fruux/sabre-vobject" 24 | }, 25 | "autoload" : { 26 | "psr-0" : { 27 | "SabreAMF" : "lib/" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/AMF3Client.php: -------------------------------------------------------------------------------- 1 | sendRequest('myService.myMethod',new SabreAMF_AMF3_Wrapper(array('myParameter'))); //Send a request to myService.myMethod and send as only parameter 'myParameter' 10 | 11 | var_dump($result); //Dump the results 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/callbackserver.php: -------------------------------------------------------------------------------- 1 | onInvokeService = 'myCallBack'; 20 | 21 | $server->exec(); 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/client.php: -------------------------------------------------------------------------------- 1 | sendRequest('myService.myMethod',array('myParameter')); //Send a request to myService.myMethod and send as only parameter 'myParameter' 10 | 11 | var_dump($result); //Dump the results 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/server.php: -------------------------------------------------------------------------------- 1 | getRequests() as $request) { // Loop through requests 12 | 13 | $server->setResponse( // Send a new response 14 | $request['response'], // Connect the request to the response 15 | SabreAMF_Const::R_RESULT, // Either R_RESULT or R_STATUS 16 | $request['data'] // Any data structure, in this case we are echoing back the original data 17 | ); 18 | 19 | } 20 | 21 | $server->sendResponse(); //Send the responses back to the client 22 | 23 | 24 | -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | - first release -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/COPYING.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/HELP.txt: -------------------------------------------------------------------------------- 1 | - contact stoica.ionut@gmail.com if you have any ideeas/help/samples or any needs for which i can find time to answer. -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/INSTALL.txt: -------------------------------------------------------------------------------- 1 | Read the following: 2 | 3 | First, explore all the txt files from all the directories in this package. 4 | This module requires SabreAMF framework from: http://code.google.com/p/sabreamf 5 | and drupal services module from: http://drupal.org/project/Services. 6 | 7 | Installation method: 8 | Just extract it in your modules path and enable it from the drupal modules 9 | management panel(smth like http://localhost/drupal/admin/build/modules). 10 | Scroll that list and check mark SabreAMF. -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/README.txt: -------------------------------------------------------------------------------- 1 | This module is a complement/alternative to AMFPHP module. 2 | Most of the scripts here pay tribute to that module,. 3 | SabreAMF module has its base and source of inspiriation in drupal AMFPHP's module code. 4 | 5 | Notes (case sensitive): 6 | 7 | SabreAMF is the framework 8 | sabreamf is the drupal module -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/SabreAMF/README.txt: -------------------------------------------------------------------------------- 1 | SabreAMF framework goes here (either the content of current SabreAMF archive or a svn checkout) 2 | 3 | For the naysayer(like me): 4 | 5 | - put here what is inside SabreAMF (all the content where dirs like AMF0, AMF3 and the files next to them reside) -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/TODO.txt: -------------------------------------------------------------------------------- 1 | - attempt automatic classmapping between drupal nodes and actionscript classes 2 | - fix nid problem -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/examples/README.txt: -------------------------------------------------------------------------------- 1 | This module provides a one frame fla file for testing service invocation. 2 | 3 | There is an as3 wrapper class that helps you invoke in an easy manner, the drupal remote object methods(aka services). 4 | It can be used with flex too (tested in flex3) 5 | 6 | Code in the fla's first frame: 7 | 8 | import flash.events.NetStatusEvent; 9 | import flash.net.NetConnection; 10 | import flash.net.ObjectEncoding; 11 | import flash.net.Responder; 12 | 13 | // you are welcomed to adapt this as3 proxy class(aka class with unknown/dynamic methods) as you feeld it is needed 14 | import ro.gion.drupal.remoting.DrupalService; 15 | 16 | // first argument, the gateway url, second argument, the service name(module name) 17 | // the code bellow creates an in instance of a remote object(proxy to your drupal service) 18 | // you can have as many instances as you want, each of them poiting to different or the same service 19 | var gw:DrupalService = new DrupalService( 20 | 'http://localhost/drupal/services/sabreamf', 21 | 'sabreamf' 22 | ); 23 | 24 | // reponder callbacks, these are invoked when result is received from the server 25 | // communication between flash and the server side php/drupal is done in an async manner 26 | // you have to deal with "transitorial"(bad english) states yourself 27 | function sabreamf_pingme_Result(re:Object) { 28 | trace('sabreamf_pingme_Result result ' + re); 29 | } 30 | 31 | // responder callback when called when smth bad happened(server died, the internet connection died, etc.) 32 | function sabreamf_pingme_Fault(fe:Object) { 33 | trace('sabreamf_pingme_Fault fault ' + fe); 34 | } 35 | 36 | // hooks are called without the module prefix (to ease your pain, in the DrupalService constructor above 37 | // you already told the proxy what to use 38 | // for the 4 calls bellow you should receive 4 results or faults 39 | gw.pingme([21, 24], sabreamf_pingme_Result, sabreamf_pingme_Fault); 40 | gw.pingme([22, 24], sabreamf_pingme_Result, sabreamf_pingme_Fault); 41 | gw.pingme([23, 24], sabreamf_pingme_Result, sabreamf_pingme_Fault); 42 | gw.pingme([24, 24], sabreamf_pingme_Result, sabreamf_pingme_Fault); -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/examples/TODO.txt: -------------------------------------------------------------------------------- 1 | - create more samples 2 | - create flex samples 3 | - create a sample console demoing usual drupal exposed services (menu, node, search, system, views, etc.), "a-la" drupal service browser -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/examples/drupalclient/AC_RunActiveContent.js: -------------------------------------------------------------------------------- 1 | //v1.7 2 | // Flash Player Version Detection 3 | // Detect Client Browser type 4 | // Copyright 2005-2007 Adobe Systems Incorporated. All rights reserved. 5 | var isIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false; 6 | var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false; 7 | var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false; 8 | 9 | function ControlVersion() 10 | { 11 | var version; 12 | var axo; 13 | var e; 14 | 15 | // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry 16 | 17 | try { 18 | // version will be set for 7.X or greater players 19 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); 20 | version = axo.GetVariable("$version"); 21 | } catch (e) { 22 | } 23 | 24 | if (!version) 25 | { 26 | try { 27 | // version will be set for 6.X players only 28 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"); 29 | 30 | // installed player is some revision of 6.0 31 | // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29, 32 | // so we have to be careful. 33 | 34 | // default to the first public version 35 | version = "WIN 6,0,21,0"; 36 | 37 | // throws if AllowScripAccess does not exist (introduced in 6.0r47) 38 | axo.AllowScriptAccess = "always"; 39 | 40 | // safe to call for 6.0r47 or greater 41 | version = axo.GetVariable("$version"); 42 | 43 | } catch (e) { 44 | } 45 | } 46 | 47 | if (!version) 48 | { 49 | try { 50 | // version will be set for 4.X or 5.X player 51 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); 52 | version = axo.GetVariable("$version"); 53 | } catch (e) { 54 | } 55 | } 56 | 57 | if (!version) 58 | { 59 | try { 60 | // version will be set for 3.X player 61 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); 62 | version = "WIN 3,0,18,0"; 63 | } catch (e) { 64 | } 65 | } 66 | 67 | if (!version) 68 | { 69 | try { 70 | // version will be set for 2.X player 71 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); 72 | version = "WIN 2,0,0,11"; 73 | } catch (e) { 74 | version = -1; 75 | } 76 | } 77 | 78 | return version; 79 | } 80 | 81 | // JavaScript helper required to detect Flash Player PlugIn version information 82 | function GetSwfVer(){ 83 | // NS/Opera version >= 3 check for Flash plugin in plugin array 84 | var flashVer = -1; 85 | 86 | if (navigator.plugins != null && navigator.plugins.length > 0) { 87 | if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) { 88 | var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : ""; 89 | var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description; 90 | var descArray = flashDescription.split(" "); 91 | var tempArrayMajor = descArray[2].split("."); 92 | var versionMajor = tempArrayMajor[0]; 93 | var versionMinor = tempArrayMajor[1]; 94 | var versionRevision = descArray[3]; 95 | if (versionRevision == "") { 96 | versionRevision = descArray[4]; 97 | } 98 | if (versionRevision[0] == "d") { 99 | versionRevision = versionRevision.substring(1); 100 | } else if (versionRevision[0] == "r") { 101 | versionRevision = versionRevision.substring(1); 102 | if (versionRevision.indexOf("d") > 0) { 103 | versionRevision = versionRevision.substring(0, versionRevision.indexOf("d")); 104 | } 105 | } 106 | var flashVer = versionMajor + "." + versionMinor + "." + versionRevision; 107 | } 108 | } 109 | // MSN/WebTV 2.6 supports Flash 4 110 | else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4; 111 | // WebTV 2.5 supports Flash 3 112 | else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3; 113 | // older WebTV supports Flash 2 114 | else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2; 115 | else if ( isIE && isWin && !isOpera ) { 116 | flashVer = ControlVersion(); 117 | } 118 | return flashVer; 119 | } 120 | 121 | // When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available 122 | function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision) 123 | { 124 | versionStr = GetSwfVer(); 125 | if (versionStr == -1 ) { 126 | return false; 127 | } else if (versionStr != 0) { 128 | if(isIE && isWin && !isOpera) { 129 | // Given "WIN 2,0,0,11" 130 | tempArray = versionStr.split(" "); // ["WIN", "2,0,0,11"] 131 | tempString = tempArray[1]; // "2,0,0,11" 132 | versionArray = tempString.split(","); // ['2', '0', '0', '11'] 133 | } else { 134 | versionArray = versionStr.split("."); 135 | } 136 | var versionMajor = versionArray[0]; 137 | var versionMinor = versionArray[1]; 138 | var versionRevision = versionArray[2]; 139 | 140 | // is the major.revision >= requested major.revision AND the minor version >= requested minor 141 | if (versionMajor > parseFloat(reqMajorVer)) { 142 | return true; 143 | } else if (versionMajor == parseFloat(reqMajorVer)) { 144 | if (versionMinor > parseFloat(reqMinorVer)) 145 | return true; 146 | else if (versionMinor == parseFloat(reqMinorVer)) { 147 | if (versionRevision >= parseFloat(reqRevision)) 148 | return true; 149 | } 150 | } 151 | return false; 152 | } 153 | } 154 | 155 | function AC_AddExtension(src, ext) 156 | { 157 | if (src.indexOf('?') != -1) 158 | return src.replace(/\?/, ext+'?'); 159 | else 160 | return src + ext; 161 | } 162 | 163 | function AC_Generateobj(objAttrs, params, embedAttrs) 164 | { 165 | var str = ''; 166 | if (isIE && isWin && !isOpera) 167 | { 168 | str += ' '; 177 | } 178 | str += ''; 179 | } 180 | else 181 | { 182 | str += ' 2 | 3 | 4 | example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 40 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/examples/drupalclient/ro/gion/drupal/remoting/DrupalService.as: -------------------------------------------------------------------------------- 1 | /** 2 | * This code is distributed under a non restrictive license 3 | * - so do whatever you want with it 4 | */ 5 | 6 | package ro.gion.drupal.remoting { 7 | 8 | import flash.events.*; 9 | import flash.net.NetConnection; 10 | import flash.net.ObjectEncoding; 11 | import flash.net.Responder; 12 | 13 | import flash.utils.*; 14 | 15 | public dynamic class DrupalService extends Proxy { 16 | 17 | private static const STATUS_DISCONNECTED = 'DrupalService.STATUS_DISCONNECTED'; 18 | private static const STATUS_CONNECTING = 'DrupalService.STATUS_CONNECTING'; 19 | private static const STATUS_CONNECTED = 'DrupalService.STATUS_CONNECTED'; 20 | 21 | private var nc:NetConnection; 22 | private var gatewayUrl:String; 23 | private var serviceName:String; 24 | 25 | private var apiKey:String = null; 26 | private var sessionId:String = null; 27 | 28 | private var status:String = DrupalService.STATUS_DISCONNECTED; 29 | private var connectionObject:Object = null; 30 | private var user:Object = null; 31 | 32 | private var nextCalls:Array = new Array(); 33 | 34 | public function DrupalService(gatewayUrl:String, serviceName:String, apiKey:String=null, sessionId:String=null) { 35 | 36 | this.gatewayUrl = gatewayUrl; 37 | this.serviceName = serviceName; 38 | this.apiKey = apiKey; 39 | this.sessionId = sessionId; 40 | 41 | nc = new NetConnection(); 42 | nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusEvent_Handler); 43 | nc.addEventListener(IOErrorEvent.IO_ERROR, ioErrorEvent_Handler); 44 | nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorEvent_Handler); 45 | nc.objectEncoding = ObjectEncoding.AMF3; 46 | nc.connect(this.gatewayUrl); 47 | } 48 | 49 | public function systemConnect() { 50 | __trace('calling system.connect'); 51 | status = STATUS_CONNECTING; 52 | var command:String = 'system.connect'; 53 | var responder:Responder = new Responder(systemConnectResult_Handler, systemConnectFault_Handler); 54 | var args:Array = new Array(command, responder); 55 | if(apiKey != null) { 56 | args.push(apiKey); 57 | } 58 | nc.call.apply(nc, args); 59 | } 60 | 61 | private function systemConnectResult_Handler(result:Object):void { 62 | __trace('connected through : ' + gatewayUrl); 63 | __trace('received sessionId: ' + result.sessid); 64 | __trace('received userId : ' + result.user.userid); 65 | 66 | sessionId = result.sessid; 67 | user = result.user; 68 | status = STATUS_CONNECTED; 69 | 70 | var cb:Object = null; 71 | while(cb = nextCalls.shift()) { 72 | __trace('calling pending: ' + cb.name); 73 | cb.callback.apply(cb.name, cb.args); 74 | } 75 | } 76 | 77 | private function systemConnectFault_Handler(result:Object):void { 78 | __trace('systemConnectFault ' + result); 79 | status = STATUS_DISCONNECTED; 80 | } 81 | 82 | private function netStatusEvent_Handler(event:NetStatusEvent):void { 83 | __trace('netStatusEvent_Handler ' + event.info.code); 84 | switch(event.info.code) { 85 | case 'NetConnection.Call.Failed': 86 | break; 87 | case 'NetConnection.Connect.Success': 88 | __trace(event.info.code); 89 | break; 90 | default: 91 | break; 92 | } 93 | } 94 | 95 | private function __trace(el:*) { 96 | if((el is Number) || (el is String) || (el is Boolean) || (el is Date)) { 97 | trace(serviceName + ' - ' + el); 98 | return; 99 | } 100 | for(var i in el) { 101 | trace(serviceName + ' - ' + i + ':' + el); 102 | if(el[i] is Object) { 103 | __trace(el[i]); 104 | } 105 | } 106 | } 107 | 108 | 109 | private function genericResult_Handler(result:*):void { 110 | __trace('got unhandled result'); 111 | __trace(result); 112 | } 113 | 114 | private function genericFault_Handler(fault:*):void { 115 | __trace('got unhandled fault'); 116 | __trace(fault); 117 | } 118 | 119 | private function ioErrorEvent_Handler(event:IOErrorEvent):void { 120 | __trace(event); 121 | } 122 | 123 | private function securityErrorEvent_Handler(event:SecurityErrorEvent):void { 124 | __trace(event); 125 | } 126 | 127 | flash_proxy override function callProperty(method: *, ...args): * { 128 | 129 | var clazz : Class = getDefinitionByName(getQualifiedClassName(this)) as Class; 130 | clazz.prototype[method] = function() { 131 | arguments[1] = arguments[1] != null ? arguments[1] : genericResult_Handler; 132 | arguments[2] = arguments[2] != null ? arguments[2] : genericFault_Handler; 133 | var command:String = serviceName+'.'+serviceName+'_'+method; 134 | var responder:Responder = new Responder(arguments[1], arguments[2]); 135 | __trace(responder); 136 | arguments[0].unshift(command, responder); 137 | nc.call.apply(nc, arguments[0]); 138 | return true; 139 | } 140 | 141 | switch(status) { 142 | case STATUS_CONNECTED: 143 | return clazz.prototype[method].apply(method, args); 144 | break; 145 | case STATUS_CONNECTING: 146 | nextCalls.push({name: method, args: args, callback: clazz.prototype[method]}); 147 | break; 148 | case STATUS_DISCONNECTED: 149 | systemConnect(); 150 | nextCalls.push({name: method, args: args, callback: clazz.prototype[method]}); 151 | break; 152 | default:break; 153 | } 154 | } 155 | } 156 | 157 | } -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/media/images/gateway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evert/SabreAMF/e20dddba4f49c06c9bb5c8a052e6f4dfe4ffd1e3/integrations/drupal/module/sabreamf/media/images/gateway.png -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/media/images/sabreamf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evert/SabreAMF/e20dddba4f49c06c9bb5c8a052e6f4dfe4ffd1e3/integrations/drupal/module/sabreamf/media/images/sabreamf.png -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/media/styles/reset.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Yahoo! Inc. All rights reserved. 3 | Code licensed under the BSD License: 4 | http://developer.yahoo.net/yui/license.txt 5 | version: 2.5.2 6 | */ 7 | html{color:#000;background:#FFF;} 8 | body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;} 9 | table{border-collapse:collapse;border-spacing:0;} 10 | fieldset,img{border:0;} 11 | address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:normal;} 12 | li{list-style:none;} 13 | caption,th{text-align:left;} 14 | h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;} 15 | q:before,q:after{content:'';} 16 | abbr,acronym {border:0;font-variant:normal;} 17 | /* to preserve line-height and selector appearance */ 18 | sup {vertical-align:text-top;} 19 | sub {vertical-align:text-bottom;} 20 | input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;} 21 | /*to enable resizing for IE*/ 22 | input,textarea,select{*font-size:100%;} 23 | /*because legend doesn't inherit in IE */ 24 | legend{color:#000;} 25 | -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/media/styles/sabreamf.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | html { background-color: #000000; color:#ffffff; font-family:Verdana; font-size: 11px; color:#ffdd11 } 3 | 4 | #logo { 5 | margin: 0 auto; 6 | margin-top: 25%; 7 | background-image: url(../images/sabreamf.png); 8 | background-repeat:no-repeat; 9 | width:261px; 10 | height:46px; 11 | font-weight:bold; 12 | } 13 | 14 | #logo span { display: none; } -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/sabreamf.info: -------------------------------------------------------------------------------- 1 | ; $Id: sabreamf.info,v 1.0 2009/02/17 20:35:00 stoica.ionut Exp $ 2 | name = SabreAMF 3 | description = Provides an SabreAMF server. 4 | package = Services - servers 5 | dependencies[] = services 6 | core = 6.x 7 | -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/sabreamf.module: -------------------------------------------------------------------------------- 1 | t('SabreAMF'), 11 | 'value' => t('1.2'), 12 | ); 13 | 14 | if (!file_exists(realpath(dirname(__FILE__) . '/SabreAMF/Server.php'))) { 15 | $requirements['sabreamf']['value'] = t('SabreAMF framework was not found'); 16 | $requirements['sabreamf']['description'] = t('You must dowload SabreAMF framework and install it into modules/sabreamf/SabreAMF.'); 17 | $requirements['sabreamf']['severity'] = REQUIREMENT_ERROR; 18 | } 19 | 20 | return $requirements; 21 | } 22 | 23 | /* 24 | * Implementation of hook_server_info() 25 | */ 26 | function sabreamf_server_info() { 27 | return array( 28 | '#name' => 'SabreAMF', 29 | '#path' => 'sabreamf', 30 | ); 31 | } 32 | 33 | /* 34 | * Implementation of hook_server() 35 | */ 36 | function sabreamf_server() { 37 | 38 | $path = $_SERVER['DOCUMENT_ROOT'] . base_path() . drupal_get_path('module', 'sabreamf'); 39 | 40 | if(!(isset($_SERVER['CONTENT_TYPE']) && ($_SERVER['CONTENT_TYPE'] == 'application/x-amf'))) { 41 | $media_url = base_path().drupal_get_path('module', 'sabreamf').'/media'; 42 | $html = ' 43 | '; 44 | $html .= 'SabreAMF gateway ready'; 45 | $html .= ''; 46 | $html .= ''; 47 | $html .= ''; 48 | echo $html; 49 | } else { 50 | set_include_path(get_include_path().PATH_SEPARATOR.$path); 51 | require_once $path . '/SabreAMF/CallbackServer.php'; 52 | $server = new SabreAMF_CallbackServer(); 53 | $server->onInvokeService = '_sabreamf_server_callback'; 54 | $server->exec(); 55 | } 56 | } 57 | 58 | function _sabreamf_server_callback($serviceName, $methodName, $arguments) { 59 | $method = $serviceName.'.'.$methodName; 60 | // this is only a convenience method so that you can test sabreamf drupal module 61 | // using a php script (running from browser or from the console(ie: command line in windows)) 62 | // this "if" block bellow can be removed with no issue 63 | if($methodName == 'sabreamf_pingme') { 64 | return array($method, $arguments); 65 | } 66 | return sabreamf_method_call($method, array($method, $arguments)); 67 | } 68 | 69 | /* 70 | * Implementation of hook_method_call() 71 | */ 72 | function sabreamf_method_call($method_name, $args) { 73 | return services_method_call($method_name, $args); 74 | } 75 | 76 | /* 77 | * Implementation of hook_server_error() 78 | */ 79 | function sabreamf_server_error($message) { 80 | watchdog('sabreamf server', $message, NULL, WATCHDOG_ERROR); 81 | } 82 | 83 | /* 84 | function trace_dump_sabreamf() { 85 | $args = func_get_args(); 86 | $fp = fopen(dirname(__FILE__).'/log.txt', 'a+'); 87 | fwrite($fp, print_r($args, true)."\n"); 88 | fclose($fp); 89 | } 90 | */ -------------------------------------------------------------------------------- /integrations/drupal/module/sabreamf/tests/ping_client.php: -------------------------------------------------------------------------------- 1 | int_value = 10; 18 | $object->float_value = 1.123456; 19 | $object->datetime_value = date_create(date('Y-m-d')); 20 | $object->string_value = 'this is a string'; 21 | $object->boolean_value = TRUE; 22 | $object->array_value = array('a', 'b', 'c'); 23 | $parameter = array( 24 | 'int_value' => 10, 25 | 'float_value' => 1.123456, 26 | 'datetime_value' => date_create(date('Y-m-d')), 27 | 'string_value' => 'weee', 28 | 'boolean_value' => TRUE, 29 | 'array_value' => array('a', 'b', 'c'), 30 | 'object_value' => $object 31 | ); 32 | 33 | try { 34 | $sabreamf_result = $sabreamf->sendRequest('sabreamf_server.sabreamf_pingme',new SabreAMF_AMF3_Wrapper(array($parameter))); 35 | var_dump($sabreamf_result); 36 | } catch (Exception $ex) { 37 | echo "\n ERROR - $gateway_url - may not point to a valid gateway.\n\n "; 38 | echo $ex->getMessage()."\n"; 39 | } 40 | -------------------------------------------------------------------------------- /lib/SabreAMF/AMF0/Const.php: -------------------------------------------------------------------------------- 1 | refList = array(); 52 | 53 | if (is_null($settype)) { 54 | $settype = $this->stream->readByte(); 55 | } 56 | 57 | switch ($settype) { 58 | 59 | case SabreAMF_AMF0_Const::DT_NUMBER : return $this->stream->readDouble(); 60 | case SabreAMF_AMF0_Const::DT_BOOL : return $this->stream->readByte()==true; 61 | case SabreAMF_AMF0_Const::DT_STRING : return $this->readString(); 62 | case SabreAMF_AMF0_Const::DT_OBJECT : return $this->readObject(); 63 | case SabreAMF_AMF0_Const::DT_NULL : return null; 64 | case SabreAMF_AMF0_Const::DT_UNDEFINED : return null; 65 | case SabreAMF_AMF0_Const::DT_REFERENCE : return $this->readReference(); 66 | case SabreAMF_AMF0_Const::DT_MIXEDARRAY : return $this->readMixedArray(); 67 | case SabreAMF_AMF0_Const::DT_ARRAY : return $this->readArray(); 68 | case SabreAMF_AMF0_Const::DT_DATE : return $this->readDate(); 69 | case SabreAMF_AMF0_Const::DT_LONGSTRING : return $this->readLongString(); 70 | case SabreAMF_AMF0_Const::DT_UNSUPPORTED : return null; 71 | case SabreAMF_AMF0_Const::DT_XML : return $this->readLongString(); 72 | case SabreAMF_AMF0_Const::DT_TYPEDOBJECT : return $this->readTypedObject(); 73 | case SabreAMF_AMF0_Const::DT_AMF3 : return $this->readAMF3Data(); 74 | default : throw new Exception('Unsupported type: 0x' . strtoupper(str_pad(dechex($settype),2,0,STR_PAD_LEFT))); return false; 75 | 76 | } 77 | 78 | } 79 | 80 | /** 81 | * readObject 82 | * 83 | * @return object 84 | */ 85 | public function readObject() { 86 | 87 | $object = array(); 88 | $this->refList[] =& $object; 89 | while (true) { 90 | $key = $this->readString(); 91 | $vartype = $this->stream->readByte(); 92 | if ($vartype==SabreAMF_AMF0_Const::DT_OBJECTTERM) break; 93 | $object[$key] = $this->readAmfData($vartype); 94 | } 95 | if (defined('SABREAMF_OBJECT_AS_ARRAY')) { 96 | $object = (object)$object; 97 | } 98 | return $object; 99 | 100 | } 101 | 102 | /** 103 | * readReference 104 | * 105 | * @return object 106 | */ 107 | public function readReference() { 108 | 109 | $refId = $this->stream->readInt(); 110 | if (isset($this->refList[$refId])) { 111 | return $this->refList[$refId]; 112 | } else { 113 | throw new Exception('Invalid reference offset: ' . $refId); 114 | return false; 115 | } 116 | 117 | } 118 | 119 | 120 | /** 121 | * readArray 122 | * 123 | * @return array 124 | */ 125 | public function readArray() { 126 | 127 | $length = $this->stream->readLong(); 128 | $arr = array(); 129 | $this->refList[]=&$arr; 130 | while($length--) $arr[] = $this->readAMFData(); 131 | return $arr; 132 | 133 | } 134 | 135 | /** 136 | * readMixedArray 137 | * 138 | * @return array 139 | */ 140 | public function readMixedArray() { 141 | 142 | $highestIndex = $this->stream->readLong(); 143 | return $this->readObject(); 144 | 145 | } 146 | 147 | /** 148 | * readString 149 | * 150 | * @return string 151 | */ 152 | public function readString() { 153 | 154 | $strLen = $this->stream->readInt(); 155 | return $this->stream->readBuffer($strLen); 156 | 157 | } 158 | 159 | /** 160 | * readLongString 161 | * 162 | * @return string 163 | */ 164 | public function readLongString() { 165 | 166 | $strLen = $this->stream->readLong(); 167 | return $this->stream->readBuffer($strLen); 168 | 169 | } 170 | 171 | /** 172 | * 173 | * readDate 174 | * 175 | * @return int 176 | */ 177 | public function readDate() { 178 | 179 | // Unix timestamp in seconds. We strip the millisecond part 180 | $timestamp = floor($this->stream->readDouble() / 1000); 181 | 182 | // we are ignoring the timezone 183 | $timezoneOffset = $this->stream->readInt(); 184 | //if ($timezoneOffset > 720) $timezoneOffset = ((65536 - $timezoneOffset)); 185 | //$timezoneOffset=($timezoneOffset * 60) - date('Z'); 186 | 187 | $dateTime = new DateTime('@' . $timestamp); 188 | 189 | return $dateTime; 190 | 191 | } 192 | 193 | /** 194 | * readTypedObject 195 | * 196 | * @return object 197 | */ 198 | public function readTypedObject() { 199 | 200 | $classname = $this->readString(); 201 | 202 | $isMapped = false; 203 | 204 | if ($localClassname = $this->getLocalClassName($classname)) { 205 | $rObject = new $localClassname(); 206 | $isMapped = true; 207 | } else { 208 | $rObject = new SabreAMF_TypedObject($classname,null); 209 | } 210 | $this->refList[] =& $rObject; 211 | 212 | $props = array(); 213 | while (true) { 214 | $key = $this->readString(); 215 | $vartype = $this->stream->readByte(); 216 | if ($vartype==SabreAMF_AMF0_Const::DT_OBJECTTERM) break; 217 | $props[$key] = $this->readAmfData($vartype); 218 | } 219 | 220 | if ($isMapped) { 221 | foreach($props as $k=>$v) 222 | $rObject->$k = $v; 223 | } else { 224 | $rObject->setAMFData($props); 225 | } 226 | 227 | return $rObject; 228 | 229 | } 230 | 231 | /** 232 | * readAMF3Data 233 | * 234 | * @return SabreAMF_AMF3_Wrapper 235 | */ 236 | public function readAMF3Data() { 237 | 238 | $amf3Deserializer = new SabreAMF_AMF3_Deserializer($this->stream, $this->savedRefs); 239 | $data = $amf3Deserializer->readAMFData(); 240 | $this->savedRefs = $amf3Deserializer->getReferences(); 241 | return new SabreAMF_AMF3_Wrapper($data); 242 | 243 | } 244 | 245 | 246 | } 247 | 248 | 249 | -------------------------------------------------------------------------------- /lib/SabreAMF/AMF0/Serializer.php: -------------------------------------------------------------------------------- 1 | 65536) $type = SabreAMF_AMF0_Const::DT_LONGSTRING; 44 | 45 | // Normal string 46 | if (!$type && is_string($data)) $type = SabreAMF_AMF0_Const::DT_STRING; 47 | 48 | // Checking if its an array 49 | if (!$type && is_array($data)) { 50 | if ( $this->isPureArray( $data ) ) { 51 | $type = SabreAMF_AMF0_Const::DT_ARRAY; 52 | } else { 53 | $type = SabreAMF_AMF0_Const::DT_MIXEDARRAY; 54 | } 55 | } 56 | 57 | // Its an object 58 | if (!$type && is_object($data)) { 59 | 60 | // If its an AMF3 wrapper.. we treat it as such 61 | if ($data instanceof SabreAMF_AMF3_Wrapper) $type = SabreAMF_AMF0_Const::DT_AMF3; 62 | 63 | else if ($data instanceof DateTime) $type = SabreAMF_AMF0_Const::DT_DATE; 64 | 65 | // We'll see if its registered in the classmapper 66 | else if ($this->getRemoteClassName(get_class($data))) $type = SabreAMF_AMF0_Const::DT_TYPEDOBJECT; 67 | 68 | // Otherwise.. check if it its an TypedObject 69 | else if ($data instanceof SabreAMF_ITypedObject) $type = SabreAMF_AMF0_Const::DT_TYPEDOBJECT; 70 | 71 | // If everything else fails, its a general object 72 | else $type = SabreAMF_AMF0_Const::DT_OBJECT; 73 | } 74 | 75 | // If everything failed, throw an exception 76 | if ($type===false) { 77 | throw new Exception('Unhandled data-type: ' . gettype($data)); 78 | return null; 79 | } 80 | } else $type = $forcetype; 81 | 82 | $this->stream->writeByte($type); 83 | 84 | switch ($type) { 85 | 86 | case SabreAMF_AMF0_Const::DT_NUMBER : return $this->stream->writeDouble($data); 87 | case SabreAMF_AMF0_Const::DT_BOOL : return $this->stream->writeByte($data==true); 88 | case SabreAMF_AMF0_Const::DT_STRING : return $this->writeString($data); 89 | case SabreAMF_AMF0_Const::DT_OBJECT : return $this->writeObject($data); 90 | case SabreAMF_AMF0_Const::DT_NULL : return true; 91 | case SabreAMF_AMF0_Const::DT_MIXEDARRAY : return $this->writeMixedArray($data); 92 | case SabreAMF_AMF0_Const::DT_ARRAY : return $this->writeArray($data); 93 | case SabreAMF_AMF0_Const::DT_DATE : return $this->writeDate($data); 94 | case SabreAMF_AMF0_Const::DT_LONGSTRING : return $this->writeLongString($data); 95 | case SabreAMF_AMF0_Const::DT_TYPEDOBJECT : return $this->writeTypedObject($data); 96 | case SabreAMF_AMF0_Const::DT_AMF3 : return $this->writeAMF3Data($data); 97 | default : throw new Exception('Unsupported type: ' . gettype($data)); return false; 98 | 99 | } 100 | 101 | } 102 | 103 | /** 104 | * writeMixedArray 105 | * 106 | * @param array $data 107 | * @return void 108 | */ 109 | public function writeMixedArray($data) { 110 | 111 | $this->stream->writeLong(0); 112 | foreach($data as $key=>$value) { 113 | $this->writeString($key); 114 | $this->writeAMFData($value); 115 | } 116 | $this->writeString(''); 117 | $this->stream->writeByte(SabreAMF_AMF0_Const::DT_OBJECTTERM); 118 | 119 | } 120 | 121 | /** 122 | * writeArray 123 | * 124 | * @param array $data 125 | * @return void 126 | */ 127 | public function writeArray($data) { 128 | 129 | if (!count($data)) { 130 | $this->stream->writeLong(0); 131 | } else { 132 | end($data); 133 | $last = key($data); 134 | $this->stream->writeLong($last+1); 135 | for($i=0;$i<=$last;$i++) { 136 | if (isset($data[$i])) { 137 | $this->writeAMFData($data[$i]); 138 | } else { 139 | $this->stream->writeByte(SabreAMF_AMF0_Const::DT_UNDEFINED); 140 | } 141 | } 142 | } 143 | 144 | } 145 | 146 | /** 147 | * writeObject 148 | * 149 | * @param object $data 150 | * @return void 151 | */ 152 | public function writeObject($data) { 153 | 154 | foreach($data as $key=>$value) { 155 | $this->writeString($key); 156 | $this->writeAmfData($value); 157 | } 158 | $this->writeString(''); 159 | $this->stream->writeByte(SabreAMF_AMF0_Const::DT_OBJECTTERM); 160 | return true; 161 | 162 | } 163 | 164 | /** 165 | * writeString 166 | * 167 | * @param string $string 168 | * @return void 169 | */ 170 | public function writeString($string) { 171 | 172 | $this->stream->writeInt(strlen($string)); 173 | $this->stream->writeBuffer($string); 174 | 175 | } 176 | 177 | /** 178 | * writeLongString 179 | * 180 | * @param string $string 181 | * @return void 182 | */ 183 | public function writeLongString($string) { 184 | 185 | $this->stream->writeLong(strlen($string)); 186 | $this->stream->writeBuffer($string); 187 | 188 | } 189 | /** 190 | * writeTypedObject 191 | * 192 | * @param object $data 193 | * @return void 194 | */ 195 | public function writeTypedObject($data) { 196 | 197 | if ($data instanceof SabreAMF_ITypedObject) { 198 | $classname = $data->getAMFClassName(); 199 | $data = $data->getAMFData(); 200 | } else $classname = $this->getRemoteClassName(get_class($data)); 201 | 202 | $this->writeString($classname); 203 | return $this->writeObject($data); 204 | 205 | } 206 | 207 | 208 | /** 209 | * writeAMF3Data 210 | * 211 | * @param mixed $data 212 | * @return void 213 | */ 214 | public function writeAMF3Data(SabreAMF_AMF3_Wrapper $data) { 215 | 216 | $serializer = new SabreAMF_AMF3_Serializer($this->stream); 217 | return $serializer->writeAMFData($data->getData()); 218 | 219 | } 220 | 221 | /** 222 | * Writes a date object 223 | * 224 | * @param DateTime $data 225 | * @return void 226 | */ 227 | public function writeDate(DateTime $data) { 228 | 229 | $this->stream->writeDouble($data->format('U')*1000); 230 | 231 | // empty timezone 232 | $this->stream->writeInt(0); 233 | } 234 | 235 | } 236 | 237 | 238 | -------------------------------------------------------------------------------- /lib/SabreAMF/AMF3/AbstractMessage.php: -------------------------------------------------------------------------------- 1 | messageId = $this->generateRandomId(); 31 | $this->clientId = $this->generateRandomId(); 32 | $this->destination = null; 33 | $this->body = null; 34 | $this->timeToLive = 0; 35 | $this->timestamp = time() . '00'; 36 | $this->headers = new STDClass(); 37 | 38 | if ($message) { 39 | $this->correlationId = $message->messageId; 40 | } 41 | 42 | } 43 | 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /lib/SabreAMF/AMF3/CommandMessage.php: -------------------------------------------------------------------------------- 1 | storedStrings, $this->storedObjects, $this->storedClasses); 62 | } 63 | 64 | /** 65 | * readAMFData 66 | * 67 | * @param mixed $settype 68 | * @return mixed 69 | */ 70 | public function readAMFData($settype = null) { 71 | 72 | if ($this->refsLoaded == false && empty($this->savedreferences) == false) { 73 | $this->storedStrings = $this->savedreferences[0]; 74 | $this->storedObjects = $this->savedreferences[1]; 75 | $this->storedClasses = $this->savedreferences[2]; 76 | 77 | $this->refsLoaded = true; 78 | } 79 | 80 | if (is_null($settype)) { 81 | $settype = $this->stream->readByte(); 82 | } 83 | 84 | switch ($settype) { 85 | 86 | case SabreAMF_AMF3_Const::DT_UNDEFINED : return null; 87 | case SabreAMF_AMF3_Const::DT_NULL : return null; 88 | case SabreAMF_AMF3_Const::DT_BOOL_FALSE : return false; 89 | case SabreAMF_AMF3_Const::DT_BOOL_TRUE : return true; 90 | case SabreAMF_AMF3_Const::DT_INTEGER : return $this->readInt(); 91 | case SabreAMF_AMF3_Const::DT_NUMBER : return $this->stream->readDouble(); 92 | case SabreAMF_AMF3_Const::DT_STRING : return $this->readString(); 93 | case SabreAMF_AMF3_Const::DT_XML : return $this->readString(); 94 | case SabreAMF_AMF3_Const::DT_DATE : return $this->readDate(); 95 | case SabreAMF_AMF3_Const::DT_ARRAY : return $this->readArray(); 96 | case SabreAMF_AMF3_Const::DT_OBJECT : return $this->readObject(); 97 | case SabreAMF_AMF3_Const::DT_XMLSTRING : return $this->readXMLString(); 98 | case SabreAMF_AMF3_Const::DT_BYTEARRAY : return $this->readByteArray(); 99 | default : throw new Exception('Unsupported type: 0x' . strtoupper(str_pad(dechex($settype),2,0,STR_PAD_LEFT))); return false; 100 | 101 | 102 | } 103 | 104 | } 105 | 106 | 107 | /** 108 | * readObject 109 | * 110 | * @return object 111 | */ 112 | public function readObject() { 113 | 114 | $objInfo = $this->readU29(); 115 | $storedObject = ($objInfo & 0x01)==0; 116 | $objInfo = $objInfo >> 1; 117 | 118 | if ($storedObject) { 119 | 120 | $objectReference = $objInfo; 121 | if (!isset($this->storedObjects[$objectReference])) { 122 | 123 | throw new Exception('Object reference #' . $objectReference . ' not found'); 124 | 125 | } else { 126 | 127 | $rObject = $this->storedObjects[$objectReference]; 128 | 129 | } 130 | 131 | } else { 132 | 133 | $storedClass = ($objInfo & 0x01)==0; 134 | $objInfo= $objInfo >> 1; 135 | 136 | // If this is a stored class.. we have the info 137 | if ($storedClass) { 138 | 139 | $classReference = $objInfo; 140 | if (!isset($this->storedClasses[$classReference])) { 141 | 142 | throw new Exception('Class reference #' . $classReference . ' not found'); 143 | 144 | } else { 145 | 146 | $encodingType = $this->storedClasses[$classReference]['encodingType']; 147 | $propertyNames = $this->storedClasses[$classReference]['propertyNames']; 148 | $className = $this->storedClasses[$classReference]['className']; 149 | 150 | } 151 | 152 | } else { 153 | 154 | $className = $this->readString(); 155 | $encodingType = $objInfo & 0x03; 156 | $propertyNames = array(); 157 | $objInfo = $objInfo >> 2; 158 | 159 | } 160 | 161 | //ClassMapping magic 162 | if ($className) { 163 | 164 | if ($localClassName = $this->getLocalClassName($className)) { 165 | 166 | $rObject = new $localClassName(); 167 | 168 | } else { 169 | 170 | $rObject = new SabreAMF_TypedObject($className,array()); 171 | 172 | } 173 | } else { 174 | 175 | $rObject = new STDClass(); 176 | 177 | } 178 | 179 | $this->storedObjects[] =& $rObject; 180 | 181 | if ($encodingType & SabreAMF_AMF3_Const::ET_EXTERNALIZED) { 182 | 183 | if (!$storedClass) { 184 | $this->storedClasses[] = array('className' => $className,'encodingType'=>$encodingType,'propertyNames'=>$propertyNames); 185 | } 186 | if ($rObject instanceof SabreAMF_Externalized) { 187 | $rObject->readExternal($this->readAMFData()); 188 | } elseif ($rObject instanceof SabreAMF_TypedObject) { 189 | $rObject->setAMFData(array('externalizedData'=>$this->readAMFData())); 190 | } else { 191 | $rObject->externalizedData = $this->readAMFData(); 192 | } 193 | //$properties['externalizedData'] = $this->readAMFData(); 194 | 195 | } else { 196 | 197 | if ($encodingType & SabreAMF_AMF3_Const::ET_SERIAL) { 198 | 199 | if (!$storedClass) { 200 | $this->storedClasses[] = array('className' => $className,'encodingType'=>$encodingType,'propertyNames'=>$propertyNames); 201 | } 202 | $properties = array(); 203 | do { 204 | $propertyName = $this->readString(); 205 | if ($propertyName!="") { 206 | $propertyNames[] = $propertyName; 207 | $properties[$propertyName] = $this->readAMFData(); 208 | } 209 | } while ($propertyName!=""); 210 | 211 | 212 | } else { 213 | if (!$storedClass) { 214 | $propertyCount = $objInfo; 215 | for($i=0;$i<$propertyCount;$i++) { 216 | 217 | $propertyNames[] = $this->readString(); 218 | 219 | } 220 | $this->storedClasses[] = array('className' => $className,'encodingType'=>$encodingType,'propertyNames'=>$propertyNames); 221 | 222 | } 223 | 224 | $properties = array(); 225 | foreach($propertyNames as $propertyName) { 226 | 227 | $properties[$propertyName] = $this->readAMFData(); 228 | 229 | } 230 | 231 | } 232 | 233 | if ($rObject instanceof SabreAMF_TypedObject) { 234 | $rObject->setAMFData($properties); 235 | } else { 236 | foreach($properties as $k=>$v) if ($k) $rObject->$k = $v; 237 | } 238 | 239 | } 240 | 241 | } 242 | return $rObject; 243 | 244 | } 245 | 246 | /** 247 | * readArray 248 | * 249 | * @return array 250 | */ 251 | public function readArray() { 252 | 253 | $arrId = $this->readU29(); 254 | if (($arrId & 0x01)==0) { 255 | $arrId = $arrId >> 1; 256 | if ($arrId>=count($this->storedObjects)) { 257 | throw new Exception('Undefined array reference: ' . $arrId); 258 | return false; 259 | } 260 | return $this->storedObjects[$arrId]; 261 | } 262 | $arrId = $arrId >> 1; 263 | 264 | $data = array(); 265 | $this->storedObjects[]=&$data; 266 | 267 | $key = $this->readString(); 268 | 269 | while($key!="") { 270 | $data[$key] = $this->readAMFData(); 271 | $key = $this->readString(); 272 | } 273 | 274 | for($i=0;$i<$arrId;$i++) { 275 | $data[] = $this->readAMFData(); 276 | } 277 | 278 | return $data; 279 | 280 | } 281 | 282 | 283 | /** 284 | * readString 285 | * 286 | * @return string 287 | */ 288 | public function readString() { 289 | 290 | $strref = $this->readU29(); 291 | 292 | if (($strref & 0x01) == 0) { 293 | $strref = $strref >> 1; 294 | if ($strref>=count($this->storedStrings)) { 295 | throw new Exception('Undefined string reference: ' . $strref); 296 | return false; 297 | } 298 | return $this->storedStrings[$strref]; 299 | } else { 300 | $strlen = $strref >> 1; 301 | $str = $this->stream->readBuffer($strlen); 302 | if ($str != "") $this->storedStrings[] = $str; 303 | return $str; 304 | } 305 | 306 | } 307 | 308 | 309 | /** 310 | * readString 311 | * 312 | * @return string 313 | */ 314 | public function readXMLString() { 315 | 316 | $strref = $this->readU29(); 317 | 318 | $strlen = $strref >> 1; 319 | $str = $this->stream->readBuffer($strlen); 320 | return simplexml_load_string($str); 321 | 322 | } 323 | 324 | /** 325 | * readString 326 | * 327 | * @return string 328 | */ 329 | public function readByteArray() { 330 | 331 | $strref = $this->readU29(); 332 | 333 | $strlen = $strref >> 1; 334 | $str = $this->stream->readBuffer($strlen); 335 | return new SabreAMF_ByteArray($str); 336 | 337 | } 338 | 339 | /** 340 | * readU29 341 | * 342 | * @return int 343 | */ 344 | public function readU29() { 345 | 346 | $count = 1; 347 | $u29 = 0; 348 | 349 | $byte = $this->stream->readByte(); 350 | 351 | while((($byte & 0x80) != 0) && $count < 4) { 352 | $u29 <<= 7; 353 | $u29 |= ($byte & 0x7f); 354 | $byte = $this->stream->readByte(); 355 | $count++; 356 | } 357 | 358 | if ($count < 4) { 359 | $u29 <<= 7; 360 | $u29 |= $byte; 361 | } else { 362 | // Use all 8 bits from the 4th byte 363 | $u29 <<= 8; 364 | $u29 |= $byte; 365 | } 366 | 367 | return $u29; 368 | 369 | } 370 | 371 | /** 372 | * readInt 373 | * 374 | * @return int 375 | */ 376 | public function readInt() { 377 | 378 | $int = $this->readU29(); 379 | // if int and has the sign bit set 380 | // Check if the integer is an int 381 | // and is signed 382 | if (($int & 0x18000000) == 0x18000000) { 383 | $int ^= 0x1fffffff; 384 | $int *= -1; 385 | $int -= 1; 386 | } else if (($int & 0x10000000) == 0x10000000) { 387 | // remove the signed flag 388 | $int &= 0x0fffffff; 389 | } 390 | 391 | return $int; 392 | 393 | } 394 | 395 | /** 396 | * readDate 397 | * 398 | * @return int 399 | */ 400 | public function readDate() { 401 | $dateref = $this->readU29(); 402 | if (($dateref & 0x01) == 0) { 403 | $dateref = $dateref >> 1; 404 | if ($dateref>=count($this->storedObjects)) { 405 | throw new Exception('Undefined date reference: ' . $dateref); 406 | return false; 407 | } 408 | return $this->storedObjects[$dateref]; 409 | } 410 | 411 | $timestamp = floor($this->stream->readDouble() / 1000); 412 | 413 | $dateTime = new DateTime('@' . $timestamp); 414 | 415 | $this->storedObjects[] = $dateTime; 416 | return $dateTime; 417 | } 418 | 419 | 420 | } 421 | 422 | 423 | -------------------------------------------------------------------------------- /lib/SabreAMF/AMF3/ErrorMessage.php: -------------------------------------------------------------------------------- 1 | messageId = $this->generateRandomId(); 42 | $this->clientId = $this->generateRandomId(); 43 | $this->destination = null; 44 | $this->body = null; 45 | $this->timeToLive = 0; 46 | $this->timestamp = time() . '00'; 47 | $this->headers = new STDClass(); 48 | 49 | } 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /lib/SabreAMF/AMF3/Serializer.php: -------------------------------------------------------------------------------- 1 | 0xFFFFFFF || $data < -268435456) { 39 | $type = SabreAMF_AMF3_Const::DT_NUMBER; 40 | } else { 41 | $type = SabreAMF_AMF3_Const::DT_INTEGER; 42 | } 43 | } 44 | if (!$type && is_float($data)) $type = SabreAMF_AMF3_Const::DT_NUMBER; 45 | if (!$type && is_int($data)) $type = SabreAMF_AMF3_Const::DT_INTEGER; 46 | if (!$type && is_string($data)) $type = SabreAMF_AMF3_Const::DT_STRING; 47 | if (!$type && is_array($data)) $type = SabreAMF_AMF3_Const::DT_ARRAY; 48 | if (!$type && is_object($data)) { 49 | 50 | if ($data instanceof SabreAMF_ByteArray) 51 | $type = SabreAMF_AMF3_Const::DT_BYTEARRAY; 52 | elseif ($data instanceof DateTime) 53 | $type = SabreAMF_AMF3_Const::DT_DATE; 54 | else 55 | $type = SabreAMF_AMF3_Const::DT_OBJECT; 56 | 57 | 58 | } 59 | if ($type===false) { 60 | throw new Exception('Unhandled data-type: ' . gettype($data)); 61 | return null; 62 | } 63 | if ($type == SabreAMF_AMF3_Const::DT_INTEGER && ($data > 268435455 || $data < -268435456)) { 64 | $type = SabreAMF_AMF3_Const::DT_NUMBER; 65 | } 66 | } else $type = $forcetype; 67 | 68 | $this->stream->writeByte($type); 69 | 70 | switch ($type) { 71 | 72 | case SabreAMF_AMF3_Const::DT_NULL : break; 73 | case SabreAMF_AMF3_Const::DT_BOOL_FALSE : break; 74 | case SabreAMF_AMF3_Const::DT_BOOL_TRUE : break; 75 | case SabreAMF_AMF3_Const::DT_INTEGER : $this->writeInt($data); break; 76 | case SabreAMF_AMF3_Const::DT_NUMBER : $this->stream->writeDouble($data); break; 77 | case SabreAMF_AMF3_Const::DT_STRING : $this->writeString($data); break; 78 | case SabreAMF_AMF3_Const::DT_DATE : $this->writeDate($data); break; 79 | case SabreAMF_AMF3_Const::DT_ARRAY : $this->writeArray($data); break; 80 | case SabreAMF_AMF3_Const::DT_OBJECT : $this->writeObject($data); break; 81 | case SabreAMF_AMF3_Const::DT_BYTEARRAY : $this->writeByteArray($data); break; 82 | default : throw new Exception('Unsupported type: ' . gettype($data)); return null; 83 | 84 | } 85 | 86 | } 87 | 88 | /** 89 | * writeObject 90 | * 91 | * @param mixed $data 92 | * @return void 93 | */ 94 | public function writeObject($data) { 95 | 96 | $encodingType = SabreAMF_AMF3_Const::ET_PROPLIST; 97 | if ($data instanceof SabreAMF_ITypedObject) { 98 | 99 | $classname = $data->getAMFClassName(); 100 | $data = $data->getAMFData(); 101 | 102 | } else if (!$classname = $this->getRemoteClassName(get_class($data))) { 103 | 104 | 105 | $classname = ''; 106 | 107 | } else { 108 | 109 | if ($data instanceof SabreAMF_Externalized) { 110 | 111 | $encodingType = SabreAMF_AMF3_Const::ET_EXTERNALIZED; 112 | 113 | } 114 | 115 | } 116 | 117 | 118 | $objectInfo = 0x03; 119 | $objectInfo |= $encodingType << 2; 120 | 121 | switch($encodingType) { 122 | 123 | case SabreAMF_AMF3_Const::ET_PROPLIST : 124 | 125 | $propertyCount=0; 126 | foreach($data as $k=>$v) { 127 | $propertyCount++; 128 | } 129 | 130 | $objectInfo |= ($propertyCount << 4); 131 | 132 | 133 | $this->writeInt($objectInfo); 134 | $this->writeString($classname); 135 | foreach($data as $k=>$v) { 136 | 137 | $this->writeString($k); 138 | 139 | } 140 | foreach($data as $k=>$v) { 141 | 142 | $this->writeAMFData($v); 143 | 144 | } 145 | break; 146 | 147 | case SabreAMF_AMF3_Const::ET_EXTERNALIZED : 148 | 149 | $this->writeInt($objectInfo); 150 | $this->writeString($classname); 151 | $this->writeAMFData($data->writeExternal()); 152 | break; 153 | } 154 | 155 | } 156 | 157 | /** 158 | * writeInt 159 | * 160 | * @param int $int 161 | * @return void 162 | */ 163 | public function writeInt($int) { 164 | 165 | // Note that this is simply a sanity check of the conversion algorithm; 166 | // when live this sanity check should be disabled (overflow check handled in this.writeAMFData). 167 | /*if ( ( ( $int & 0x70000000 ) != 0 ) && ( ( $int & 0x80000000 ) == 0 ) ) 168 | throw new Exception ( 'Integer overflow during Int32 to AMF3 conversion' );*/ 169 | 170 | if ( ( $int & 0xffffff80 ) == 0 ) 171 | { 172 | $this->stream->writeByte ( $int & 0x7f ); 173 | 174 | return; 175 | } 176 | 177 | if ( ( $int & 0xffffc000 ) == 0 ) 178 | { 179 | $this->stream->writeByte ( ( $int >> 7 ) | 0x80 ); 180 | $this->stream->writeByte ( $int & 0x7f ); 181 | 182 | return; 183 | } 184 | 185 | if ( ( $int & 0xffe00000 ) == 0 ) 186 | { 187 | $this->stream->writeByte ( ( $int >> 14 ) | 0x80 ); 188 | $this->stream->writeByte ( ( $int >> 7 ) | 0x80 ); 189 | $this->stream->writeByte ( $int & 0x7f ); 190 | 191 | return; 192 | } 193 | 194 | $this->stream->writeByte ( ( $int >> 22 ) | 0x80 ); 195 | $this->stream->writeByte ( ( $int >> 15 ) | 0x80 ); 196 | $this->stream->writeByte ( ( $int >> 8 ) | 0x80 ); 197 | $this->stream->writeByte ( $int & 0xff ); 198 | 199 | return; 200 | } 201 | 202 | public function writeByteArray(SabreAMF_ByteArray $data) { 203 | 204 | $this->writeString($data->getData()); 205 | 206 | } 207 | 208 | /** 209 | * writeString 210 | * 211 | * @param string $str 212 | * @return void 213 | */ 214 | public function writeString($str) { 215 | 216 | $strref = strlen($str) << 1 | 0x01; 217 | $this->writeInt($strref); 218 | $this->stream->writeBuffer($str); 219 | 220 | } 221 | 222 | /** 223 | * writeArray 224 | * 225 | * @param array $arr 226 | * @return void 227 | */ 228 | public function writeArray(array $arr) { 229 | 230 | //Check if this is an associative array or not. 231 | if ( $this->isPureArray( $arr ) ) { 232 | // Writing the length for the numeric keys in the array 233 | $arrLen = count($arr); 234 | $arrId = ($arrLen << 1) | 0x01; 235 | 236 | $this->writeInt($arrId); 237 | $this->writeString(''); 238 | 239 | foreach($arr as $v) { 240 | $this->writeAMFData($v); 241 | } 242 | 243 | } else { 244 | $this->writeInt(1); 245 | foreach($arr as $key=>$value) { 246 | $this->writeString($key); 247 | $this->writeAMFData($value); 248 | } 249 | $this->writeString(''); 250 | 251 | } 252 | 253 | } 254 | 255 | /** 256 | * Writes a date object 257 | * 258 | * @param DateTime $data 259 | * @return void 260 | */ 261 | public function writeDate(DateTime $data) { 262 | 263 | // We're always sending actual date objects, never references 264 | $this->writeInt(0x01); 265 | $this->stream->writeDouble($data->format('U')*1000); 266 | 267 | } 268 | 269 | } 270 | -------------------------------------------------------------------------------- /lib/SabreAMF/AMF3/Wrapper.php: -------------------------------------------------------------------------------- 1 | setData($data); 33 | 34 | } 35 | 36 | 37 | /** 38 | * getData 39 | * 40 | * @return mixed 41 | */ 42 | public function getData() { 43 | 44 | return $this->data; 45 | 46 | } 47 | 48 | /** 49 | * setData 50 | * 51 | * @param mixed $data 52 | * @return void 53 | */ 54 | public function setData($data) { 55 | 56 | $this->data = $data; 57 | 58 | } 59 | 60 | 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /lib/SabreAMF/ArrayCollection.php: -------------------------------------------------------------------------------- 1 | data = new ArrayObject($data); 36 | 37 | } 38 | 39 | /** 40 | * This is used by SabreAMF when this object is unserialized (from AMF3) 41 | * 42 | * @param array $data 43 | * @return void 44 | */ 45 | function readExternal($data) { 46 | 47 | $this->data = new ArrayObject($data); 48 | 49 | } 50 | 51 | /** 52 | * This is used by SabreAMF when this object is serialized 53 | * 54 | * @return array 55 | */ 56 | function writeExternal() { 57 | 58 | return iterator_to_array($this->data); 59 | 60 | } 61 | 62 | /** 63 | * implemented from IteratorAggregate 64 | * 65 | * @return ArrayObject 66 | */ 67 | function getIterator() { 68 | 69 | return $this->data; 70 | 71 | } 72 | 73 | /** 74 | * implemented from ArrayAccess 75 | * 76 | * @param mixed $offset 77 | * @return bool 78 | */ 79 | function offsetExists($offset) { 80 | 81 | return isset($this->data[$offset]); 82 | 83 | } 84 | 85 | /** 86 | * Implemented from ArrayAccess 87 | * 88 | * @param mixed $offset 89 | * @return mixed 90 | */ 91 | function offsetGet($offset) { 92 | 93 | return $this->data[$offset]; 94 | 95 | } 96 | 97 | /** 98 | * Implemented from ArrayAccess 99 | * 100 | * @param mixed $offset 101 | * @param mixed $value 102 | * @return void 103 | */ 104 | function offsetSet($offset,$value) { 105 | 106 | if (!is_null($offset)) { 107 | $this->data[$offset] = $value; 108 | } else { 109 | $this->data[] = $value; 110 | } 111 | 112 | } 113 | 114 | /** 115 | * Implemented from ArrayAccess 116 | * 117 | * @param mixed $offset 118 | * @return void 119 | */ 120 | function offsetUnset($offset) { 121 | 122 | unset($this->data[$offset]); 123 | 124 | } 125 | 126 | /** 127 | * Implemented from Countable 128 | * 129 | * @return int 130 | */ 131 | function count() { 132 | 133 | return count($this->data); 134 | 135 | } 136 | 137 | } 138 | 139 | 140 | -------------------------------------------------------------------------------- /lib/SabreAMF/ByteArray.php: -------------------------------------------------------------------------------- 1 | data = $data; 30 | 31 | } 32 | 33 | /** 34 | * getData 35 | * 36 | * @return string 37 | */ 38 | function getData() { 39 | 40 | return $this->data; 41 | 42 | } 43 | 44 | /** 45 | * setData 46 | * 47 | * @param string $data 48 | * @return void 49 | */ 50 | function setData($data) { 51 | 52 | $this->data = $data; 53 | 54 | } 55 | 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /lib/SabreAMF/CallbackServer.php: -------------------------------------------------------------------------------- 1 | operation) { 46 | 47 | case SabreAMF_AMF3_CommandMessage::CLIENT_PING_OPERATION : 48 | $response = new SabreAMF_AMF3_AcknowledgeMessage($request); 49 | break; 50 | case SabreAMF_AMF3_CommandMessage::LOGIN_OPERATION : 51 | $authData = base64_decode($request->body); 52 | if ($authData) { 53 | $authData = explode(':',$authData,2); 54 | if (count($authData)==2) { 55 | $this->authenticate($authData[0],$authData[1]); 56 | } 57 | } 58 | $response = new SabreAMF_AMF3_AcknowledgeMessage($request); 59 | $response->body = true; 60 | break; 61 | case SabreAMF_AMF3_CommandMessage::DISCONNECT_OPERATION : 62 | $response = new SabreAMF_AMF3_AcknowledgeMessage($request); 63 | break; 64 | default : 65 | throw new Exception('Unsupported CommandMessage operation: ' . $request->operation); 66 | 67 | } 68 | return $response; 69 | 70 | } 71 | 72 | /** 73 | * authenticate 74 | * 75 | * @param string $username 76 | * @param string $password 77 | * @return void 78 | */ 79 | protected function authenticate($username,$password) { 80 | 81 | if (is_callable($this->onAuthenticate)) { 82 | call_user_func($this->onAuthenticate,$username,$password); 83 | } 84 | 85 | } 86 | 87 | /** 88 | * invokeService 89 | * 90 | * @param string $service 91 | * @param string $method 92 | * @param array $data 93 | * @return mixed 94 | */ 95 | protected function invokeService($service,$method,$data) { 96 | 97 | if (is_callable($this->onInvokeService)) { 98 | return call_user_func_array($this->onInvokeService,array($service,$method,$data)); 99 | } else { 100 | throw new Exception('onInvokeService is not defined or not callable'); 101 | } 102 | 103 | } 104 | 105 | 106 | /** 107 | * exec 108 | * 109 | * @return void 110 | */ 111 | public function exec() { 112 | 113 | // First we'll be looping through the headers to see if there's anything we reconize 114 | 115 | foreach($this->getRequestHeaders() as $header) { 116 | 117 | switch($header['name']) { 118 | 119 | // We found a credentials headers, calling the authenticate method 120 | case 'Credentials' : 121 | $this->authenticate($header['data']['userid'],$header['data']['password']); 122 | break; 123 | 124 | } 125 | 126 | } 127 | 128 | foreach($this->getRequests() as $request) { 129 | 130 | // Default AMFVersion 131 | $AMFVersion = 0; 132 | 133 | $response = null; 134 | 135 | try { 136 | 137 | if (is_array($request['data']) && isset($request['data'][0]) && $request['data'][0] instanceof SabreAMF_AMF3_AbstractMessage) { 138 | $request['data'] = $request['data'][0]; 139 | } 140 | 141 | // See if we are dealing with the AMF3 messaging system 142 | if (is_object($request['data']) && $request['data'] instanceof SabreAMF_AMF3_AbstractMessage) { 143 | 144 | $AMFVersion = 3; 145 | 146 | // See if we are dealing with a CommandMessage 147 | if ($request['data'] instanceof SabreAMF_AMF3_CommandMessage) { 148 | 149 | // Handle the command message 150 | $response = $this->handleCommandMessage($request['data']); 151 | } 152 | 153 | // Is this maybe a RemotingMessage ? 154 | if ($request['data'] instanceof SabreAMF_AMF3_RemotingMessage) { 155 | 156 | // Yes 157 | $response = new SabreAMF_AMF3_AcknowledgeMessage($request['data']); 158 | $response->body = $this->invokeService($request['data']->source,$request['data']->operation,$request['data']->body); 159 | 160 | } 161 | 162 | } else { 163 | 164 | // We are dealing with AMF0 165 | $service = substr($request['target'],0,strrpos($request['target'],'.')); 166 | $method = substr(strrchr($request['target'],'.'),1); 167 | 168 | $response = $this->invokeService($service,$method,$request['data']); 169 | 170 | } 171 | 172 | $status = SabreAMF_Const::R_RESULT; 173 | 174 | } catch (Exception $e) { 175 | 176 | // We got an exception somewhere, ignore anything that has happened and send back 177 | // exception information 178 | 179 | if ($e instanceof SabreAMF_DetailException) { 180 | $detail = $e->getDetail(); 181 | } else { 182 | $detail = ''; 183 | } 184 | 185 | switch($AMFVersion) { 186 | case SabreAMF_Const::AMF0 : 187 | $response = array( 188 | 'description' => $e->getMessage(), 189 | 'detail' => $detail, 190 | 'line' => $e->getLine(), 191 | 'code' => $e->getCode()?$e->getCode():get_class($e), 192 | ); 193 | break; 194 | case SabreAMF_Const::AMF3 : 195 | $response = new SabreAMF_AMF3_ErrorMessage($request['data']); 196 | $response->faultString = $e->getMessage(); 197 | $response->faultCode = $e->getCode(); 198 | $response->faultDetail = $detail; 199 | break; 200 | 201 | } 202 | $status = SabreAMF_Const::R_STATUS; 203 | } 204 | 205 | $this->setResponse($request['response'],$status,$response); 206 | 207 | } 208 | $this->sendResponse(); 209 | 210 | } 211 | 212 | } 213 | 214 | 215 | -------------------------------------------------------------------------------- /lib/SabreAMF/ClassMapper.php: -------------------------------------------------------------------------------- 1 | 'SabreAMF_AMF3_RemotingMessage', 19 | 'flex.messaging.messages.CommandMessage' => 'SabreAMF_AMF3_CommandMessage', 20 | 'flex.messaging.messages.AcknowledgeMessage' => 'SabreAMF_AMF3_AcknowledgeMessage', 21 | 'flex.messaging.messages.ErrorMessage' => 'SabreAMF_AMF3_ErrorMessage', 22 | 'flex.messaging.io.ArrayCollection' => 'SabreAMF_ArrayCollection' 23 | ); 24 | 25 | /** 26 | * Assign this callback to intercept calls to getLocalClass 27 | * 28 | * @var callback 29 | */ 30 | static public $onGetLocalClass; 31 | 32 | /** 33 | * Assign this callback to intercept calls to getRemoteClass 34 | * 35 | * @var callback 36 | */ 37 | static public $onGetRemoteClass; 38 | 39 | /** 40 | * The Constructor 41 | * 42 | * We make the constructor private so the class cannot be initialized 43 | * 44 | * @return void 45 | */ 46 | private function __construct() { } 47 | 48 | /** 49 | * Register a new class to be mapped 50 | * 51 | * @param string $remoteClass 52 | * @param string $localClass 53 | * @return void 54 | */ 55 | static public function registerClass($remoteClass,$localClass) { 56 | 57 | self::$maps[$remoteClass] = $localClass; 58 | 59 | } 60 | 61 | /** 62 | * Get the local classname for a remote class 63 | * 64 | * This method will return FALSE when the class is not found 65 | * 66 | * @param string $remoteClass 67 | * @return mixed 68 | */ 69 | static public function getLocalClass($remoteClass) { 70 | 71 | $localClass = false; 72 | $cb = false; 73 | $localClass=(isset(self::$maps[$remoteClass]))?self::$maps[$remoteClass]:false; 74 | if (!$localClass && is_callable(self::$onGetLocalClass)) { 75 | $cb = true; 76 | $localClass = call_user_func(self::$onGetLocalClass,$remoteClass); 77 | } 78 | if (!$localClass) return false; 79 | if (!is_string($localClass) && $cb) { 80 | throw new Exception('Classname received from onGetLocalClass should be a string or return false. ' . gettype($localClass) . ' was returned'); 81 | } 82 | if (!class_exists($localClass)) { 83 | throw new Exception('Class ' . $localClass . ' is not defined'); 84 | } 85 | return $localClass; 86 | 87 | } 88 | 89 | /** 90 | * Get the remote classname for a local class 91 | * 92 | * This method will return FALSE when the class is not found 93 | * 94 | * @param string $localClass 95 | * @return mixed 96 | */ 97 | static public function getRemoteClass($localClass) { 98 | 99 | $remoteClass = false; 100 | $cb = false; 101 | $remoteClass = array_search($localClass,self::$maps); 102 | if (!$remoteClass && is_callable(self::$onGetRemoteClass)) { 103 | $cb = true; 104 | $remoteClass = call_user_func(self::$onGetRemoteClass,$localClass); 105 | } 106 | if (!$remoteClass) return false; 107 | if (!is_string($remoteClass) && $cb) { 108 | throw new Exception('Classname received from onGetRemoteClass should be a string or return false. ' . gettype($remoteClass) . ' was returned'); 109 | } 110 | return $remoteClass; 111 | 112 | } 113 | 114 | } 115 | 116 | 117 | -------------------------------------------------------------------------------- /lib/SabreAMF/ClassNotFoundException.php: -------------------------------------------------------------------------------- 1 | message = "Could not locate class " . $classname; 28 | $this->code = "Server.Processing"; 29 | 30 | // Call parent class constructor 31 | parent::__construct( $this->message ); 32 | } 33 | 34 | public function getDetail() { 35 | 36 | return "Please check that the given servicename is correct and that the class exists."; 37 | 38 | } 39 | 40 | } 41 | 42 | ?> 43 | -------------------------------------------------------------------------------- /lib/SabreAMF/Client.php: -------------------------------------------------------------------------------- 1 | endPoint = $endPoint; 84 | 85 | $this->amfRequest = new SabreAMF_Message(); 86 | $this->amfOutputStream = new SabreAMF_OutputStream(); 87 | 88 | } 89 | 90 | /** 91 | * Add a HTTP header to the cURL request 92 | * 93 | * @param string $header 94 | * @return $this 95 | */ 96 | public function addHTTPHeader($header) 97 | { 98 | $this->httpHeaders[] = $header; 99 | 100 | return $this; 101 | } 102 | 103 | 104 | /** 105 | * sendRequest 106 | * 107 | * sendRequest sends the request to the server. It expects the servicepath and methodname, and the parameters of the methodcall 108 | * 109 | * @param string $servicePath The servicepath (e.g.: myservice.mymethod) 110 | * @param array $data The parameters you want to send 111 | * @return mixed 112 | */ 113 | public function sendRequest($servicePath,$data) { 114 | 115 | // We're using the FLEX Messaging framework 116 | if($this->encoding & SabreAMF_Const::FLEXMSG) { 117 | 118 | 119 | // Setting up the message 120 | $message = new SabreAMF_AMF3_RemotingMessage(); 121 | $message->body = $data; 122 | 123 | // We need to split serviceName.methodName into separate variables 124 | $service = explode('.',$servicePath); 125 | $method = array_pop($service); 126 | $service = implode('.',$service); 127 | $message->operation = $method; 128 | $message->source = $service; 129 | 130 | $data = $message; 131 | } 132 | 133 | $this->amfRequest->addBody(array( 134 | 135 | // If we're using the flex messaging framework, target is specified as the string 'null' 136 | 'target' => $this->encoding & SabreAMF_Const::FLEXMSG?'null':$servicePath, 137 | 'response' => '/1', 138 | 'data' => $data 139 | )); 140 | 141 | $this->amfRequest->serialize($this->amfOutputStream); 142 | 143 | $headers = array_merge(array( 144 | 'Content-type: ' . SabreAMF_Const::MIMETYPE 145 | ), $this->httpHeaders); 146 | 147 | // The curl request 148 | $ch = curl_init($this->endPoint); 149 | curl_setopt($ch,CURLOPT_POST,1); 150 | curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1); 151 | curl_setopt($ch,CURLOPT_TIMEOUT,20); 152 | curl_setopt($ch,CURLOPT_HTTPHEADER,$headers); 153 | curl_setopt($ch,CURLOPT_POSTFIELDS,$this->amfOutputStream->getRawData()); 154 | if ($this->httpProxy) { 155 | curl_setopt($ch,CURLOPT_PROXY,$this->httpProxy); 156 | } 157 | $result = curl_exec($ch); 158 | 159 | if (curl_errno($ch)) { 160 | throw new Exception('CURL error: ' . curl_error($ch)); 161 | false; 162 | } else { 163 | curl_close($ch); 164 | } 165 | 166 | $this->amfInputStream = new SabreAMF_InputStream($result); 167 | $this->amfResponse = new SabreAMF_Message(); 168 | $this->amfResponse->deserialize($this->amfInputStream); 169 | 170 | $this->parseHeaders(); 171 | 172 | foreach($this->amfResponse->getBodies() as $body) { 173 | 174 | if (strpos($body['target'],'/1')===0) return $body['data'] ; 175 | 176 | } 177 | 178 | } 179 | 180 | /** 181 | * addHeader 182 | * 183 | * Add a header to the client request 184 | * 185 | * @param string $name 186 | * @param bool $required 187 | * @param mixed $data 188 | * @return void 189 | */ 190 | public function addHeader($name,$required,$data) { 191 | 192 | $this->amfRequest->addHeader(array('name'=>$name,'required'=>$required==true,'data'=>$data)); 193 | 194 | } 195 | 196 | /** 197 | * setCredentials 198 | * 199 | * @param string $username 200 | * @param string $password 201 | * @return void 202 | */ 203 | public function setCredentials($username,$password) { 204 | 205 | $this->addHeader('Credentials',false,(object)array('userid'=>$username,'password'=>$password)); 206 | 207 | } 208 | 209 | /** 210 | * setHttpProxy 211 | * 212 | * @param mixed $httpProxy 213 | * @return void 214 | */ 215 | public function setHttpProxy($httpProxy) { 216 | $this->httpProxy = $httpProxy; 217 | } 218 | 219 | /** 220 | * parseHeaders 221 | * 222 | * @return void 223 | */ 224 | private function parseHeaders() { 225 | 226 | foreach($this->amfResponse->getHeaders() as $header) { 227 | 228 | switch($header['name']) { 229 | 230 | case 'ReplaceGatewayUrl' : 231 | if (is_string($header['data'])) { 232 | $this->endPoint = $header['data']; 233 | } 234 | break; 235 | 236 | } 237 | 238 | 239 | } 240 | 241 | } 242 | 243 | /** 244 | * Change the AMF encoding (0 or 3) 245 | * 246 | * @param int $encoding 247 | * @return void 248 | */ 249 | public function setEncoding($encoding) { 250 | 251 | $this->encoding = $encoding; 252 | $this->amfRequest->setEncoding($encoding & SabreAMF_Const::AMF3); 253 | 254 | } 255 | 256 | } 257 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /lib/SabreAMF/Const.php: -------------------------------------------------------------------------------- 1 | stream = $stream; 44 | $this->savedreferences = $savedRefs; 45 | 46 | } 47 | 48 | /** 49 | * readAMFData 50 | * 51 | * Starts reading an AMF block from the stream 52 | * 53 | * @param mixed $settype 54 | * @return mixed 55 | */ 56 | public abstract function readAMFData($settype = null); 57 | 58 | 59 | /** 60 | * getLocalClassName 61 | * 62 | * @param string $remoteClass 63 | * @return mixed 64 | */ 65 | protected function getLocalClassName($remoteClass) { 66 | 67 | return SabreAMF_ClassMapper::getLocalClass($remoteClass); 68 | 69 | } 70 | 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /lib/SabreAMF/DetailException.php: -------------------------------------------------------------------------------- 1 | rawData = $data; 44 | 45 | } 46 | 47 | /** 48 | * &readBuffer 49 | * 50 | * @param int $length 51 | * @return mixed 52 | */ 53 | public function &readBuffer($length) { 54 | 55 | if ($length+$this->cursor > strlen($this->rawData)) { 56 | throw new Exception('Buffer underrun at position: '. $this->cursor . '. Trying to fetch '. $length . ' bytes'); 57 | return false; 58 | } 59 | $data = substr($this->rawData,$this->cursor,$length); 60 | $this->cursor+=$length; 61 | return $data; 62 | 63 | } 64 | 65 | /** 66 | * readByte 67 | * 68 | * @return int 69 | */ 70 | public function readByte() { 71 | 72 | return ord($this->readBuffer(1)); 73 | 74 | } 75 | 76 | /** 77 | * readInt 78 | * 79 | * @return int 80 | */ 81 | public function readInt() { 82 | 83 | $block = $this->readBuffer(2); 84 | $int = unpack("n",$block); 85 | return $int[1]; 86 | 87 | } 88 | 89 | 90 | /** 91 | * readDouble 92 | * 93 | * @return float 94 | */ 95 | public function readDouble() { 96 | 97 | $double = $this->readBuffer(8); 98 | 99 | $testEndian = unpack("C*",pack("S*",256)); 100 | $bigEndian = !$testEndian[1]==1; 101 | 102 | if ($bigEndian) $double = strrev($double); 103 | $double = unpack("d",$double); 104 | return $double[1]; 105 | } 106 | 107 | /** 108 | * readLong 109 | * 110 | * @return int 111 | */ 112 | public function readLong() { 113 | 114 | $block = $this->readBuffer(4); 115 | $long = unpack("N",$block); 116 | return $long[1]; 117 | } 118 | 119 | /** 120 | * readInt24 121 | * 122 | * return int 123 | */ 124 | public function readInt24() { 125 | 126 | $block = chr(0) . $this->readBuffer(3); 127 | $long = unpack("N",$block); 128 | return $long[1]; 129 | 130 | } 131 | 132 | } 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /lib/SabreAMF/InvalidAMFException.php: -------------------------------------------------------------------------------- 1 | 10 | * @licence http://www.freebsd.org/copyright/license.html BSD License (4 Clause) 11 | */ 12 | 13 | 14 | /** 15 | * In valid AMF exception 16 | * 17 | * @uses SabreAMF_DetailException 18 | */ 19 | class SabreAMF_InvalidAMFException extends Exception implements SabreAMF_DetailException { 20 | 21 | /** 22 | * Constructor 23 | */ 24 | public function __construct() { 25 | // Specific message to ClassException 26 | $this->message = "No valid AMF request received"; 27 | $this->code = "Server.Processing"; 28 | 29 | // Call parent class constructor 30 | parent::__construct( $this->message ); 31 | } 32 | 33 | public function getDetail() { 34 | 35 | return "Please check that you are calling this page with Flash and AMF."; 36 | 37 | } 38 | 39 | } 40 | 41 | ?> 42 | -------------------------------------------------------------------------------- /lib/SabreAMF/Message.php: -------------------------------------------------------------------------------- 1 | outputStream = $stream; 56 | $stream->writeByte(0x00); 57 | $stream->writeByte($this->encoding); 58 | $stream->writeInt(count($this->headers)); 59 | 60 | foreach($this->headers as $header) { 61 | 62 | $serializer = new SabreAMF_AMF0_Serializer($stream); 63 | $serializer->writeString($header['name']); 64 | $stream->writeByte($header['required']==true); 65 | $stream->writeLong(-1); 66 | $serializer->writeAMFData($header['data']); 67 | } 68 | 69 | $stream->writeInt(count($this->bodies)); 70 | 71 | 72 | foreach($this->bodies as $body) { 73 | $serializer = new SabreAMF_AMF0_Serializer($stream); 74 | $serializer->writeString($body['target']); 75 | $serializer->writeString($body['response']); 76 | $stream->writeLong(-1); 77 | 78 | switch($this->encoding) { 79 | 80 | case SabreAMF_Const::AMF0 : 81 | $serializer->writeAMFData($body['data']); 82 | break; 83 | case SabreAMF_Const::AMF3 : 84 | $serializer->writeAMFData(new SabreAMF_AMF3_Wrapper($body['data'])); 85 | break; 86 | 87 | } 88 | 89 | } 90 | 91 | } 92 | 93 | /** 94 | * deserialize 95 | * 96 | * This method deserializes a request. It requires an SabreAMF_InputStream with valid AMF data. After 97 | * deserialization the contents of the request can be found through the getBodies and getHeaders methods 98 | * 99 | * @param SabreAMF_InputStream $stream 100 | * @return void 101 | */ 102 | public function deserialize(SabreAMF_InputStream $stream) { 103 | 104 | $this->headers = array(); 105 | $this->bodies = array(); 106 | 107 | $this->InputStream = $stream; 108 | 109 | $stream->readByte(); 110 | 111 | $this->clientType = $stream->readByte(); 112 | 113 | $deserializer = new SabreAMF_AMF0_Deserializer($stream); 114 | 115 | $totalHeaders = $stream->readInt(); 116 | 117 | for($i=0;$i<$totalHeaders;$i++) { 118 | 119 | $header = array( 120 | 'name' => $deserializer->readString(), 121 | 'required' => $stream->readByte()==true 122 | ); 123 | $stream->readLong(); 124 | $header['data'] = $deserializer->readAMFData(null,true); 125 | $this->headers[] = $header; 126 | 127 | } 128 | 129 | $totalBodies = $stream->readInt(); 130 | 131 | for($i=0;$i<$totalBodies;$i++) { 132 | 133 | try { 134 | $target = $deserializer->readString(); 135 | } catch (Exception $e) { 136 | // Could not fetch next body.. this happens with some versions of AMFPHP where the body 137 | // count isn't properly set. If this happens we simply stop decoding 138 | //var_dump($e); 139 | break; 140 | } 141 | 142 | $body = array( 143 | 'target' => $target, 144 | 'response' => $deserializer->readString(), 145 | 'length' => $stream->readLong(), 146 | 'data' => $deserializer->readAMFData(null,true) 147 | ); 148 | 149 | if (is_object($body['data']) && $body['data'] instanceof SabreAMF_AMF3_Wrapper) { 150 | $body['data'] = $body['data']->getData(); 151 | $this->encoding = SabreAMF_Const::AMF3; 152 | } else if (is_array($body['data'])) { 153 | if (!defined("SABREAMF_AMF3_PRESERVE_ARGUMENTS")) { 154 | $body['data'] = $body['data'][0]->getData(); 155 | } else { 156 | $i = 0; 157 | while($i < count($body['data'])) { 158 | if($body['data'][$i] instanceof SabreAMF_AMF3_Wrapper) { 159 | $body['data'][$i] = $body['data'][$i]->getData(); 160 | } 161 | $i++; 162 | } 163 | } 164 | 165 | $this->encoding = SabreAMF_Const::AMF3; 166 | } 167 | 168 | $this->bodies[] = $body; 169 | 170 | } 171 | 172 | 173 | } 174 | 175 | /** 176 | * getClientType 177 | * 178 | * Returns the ClientType for the request. Check SabreAMF_Const for possible (known) values 179 | * 180 | * @return int 181 | */ 182 | public function getClientType() { 183 | 184 | return $this->clientType; 185 | 186 | } 187 | 188 | /** 189 | * getBodies 190 | * 191 | * Returns the bodies int the message 192 | * 193 | * @return array 194 | */ 195 | public function getBodies() { 196 | 197 | return $this->bodies; 198 | 199 | } 200 | 201 | /** 202 | * getHeaders 203 | * 204 | * Returns the headers in the message 205 | * 206 | * @return array 207 | */ 208 | public function getHeaders() { 209 | 210 | return $this->headers; 211 | 212 | } 213 | 214 | /** 215 | * addBody 216 | * 217 | * Adds a body to the message 218 | * 219 | * @param mixed $body 220 | * @return void 221 | */ 222 | public function addBody($body) { 223 | 224 | $this->bodies[] = $body; 225 | 226 | } 227 | 228 | /** 229 | * addHeader 230 | * 231 | * Adds a message header 232 | * 233 | * @param mixed $header 234 | * @return void 235 | */ 236 | public function addHeader($header) { 237 | 238 | $this->headers[] = $header; 239 | 240 | } 241 | 242 | /** 243 | * setEncoding 244 | * 245 | * @param int $encoding 246 | * @return void 247 | */ 248 | public function setEncoding($encoding) { 249 | 250 | $this->encoding = $encoding; 251 | 252 | } 253 | 254 | /** 255 | * getEncoding 256 | * 257 | * @return int 258 | */ 259 | public function getEncoding() { 260 | 261 | return $this->encoding; 262 | 263 | } 264 | 265 | } 266 | 267 | 268 | -------------------------------------------------------------------------------- /lib/SabreAMF/OutputStream.php: -------------------------------------------------------------------------------- 1 | rawData.=$str; 31 | } 32 | 33 | /** 34 | * writeByte 35 | * 36 | * @param int $byte 37 | * @return void 38 | */ 39 | public function writeByte($byte) { 40 | 41 | $this->rawData.=pack('c',$byte); 42 | 43 | } 44 | 45 | /** 46 | * writeInt 47 | * 48 | * @param int $int 49 | * @return void 50 | */ 51 | public function writeInt($int) { 52 | 53 | $this->rawData.=pack('n',$int); 54 | 55 | } 56 | 57 | /** 58 | * writeDouble 59 | * 60 | * @param float $double 61 | * @return void 62 | */ 63 | public function writeDouble($double) { 64 | 65 | $bin = pack("d",$double); 66 | $testEndian = unpack("C*",pack("S*",256)); 67 | $bigEndian = !$testEndian[1]==1; 68 | if ($bigEndian) $bin = strrev($bin); 69 | $this->rawData.=$bin; 70 | 71 | } 72 | 73 | /** 74 | * writeLong 75 | * 76 | * @param int $long 77 | * @return void 78 | */ 79 | public function writeLong($long) { 80 | 81 | $this->rawData.=pack("N",$long); 82 | 83 | 84 | } 85 | 86 | /** 87 | * getRawData 88 | * 89 | * @return string 90 | */ 91 | public function getRawData() { 92 | 93 | return $this->rawData; 94 | 95 | } 96 | 97 | 98 | } 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /lib/SabreAMF/RecordSet.php: -------------------------------------------------------------------------------- 1 | (object)array( 51 | 'totalCount' => $this->count(), 52 | 'initialData' => $this->getData(), 53 | 'cursor' => 1, 54 | 'serviceName' => false, 55 | 'columnNames' => $this->getColumnNames(), 56 | 'version' => 1, 57 | 'id' => false, 58 | ) 59 | ); 60 | 61 | 62 | } 63 | 64 | } 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /lib/SabreAMF/Serializer.php: -------------------------------------------------------------------------------- 1 | stream = $stream; 36 | 37 | } 38 | 39 | /** 40 | * writeAMFData 41 | * 42 | * @param mixed $data 43 | * @param int $forcetype 44 | * @return mixed 45 | */ 46 | public abstract function writeAMFData($data,$forcetype=null); 47 | 48 | /** 49 | * getStream 50 | * 51 | * @return SabreAMF_OutputStream 52 | */ 53 | public function getStream() { 54 | 55 | return $this->stream; 56 | 57 | } 58 | 59 | /** 60 | * getRemoteClassName 61 | * 62 | * @param string $localClass 63 | * @return mixed 64 | */ 65 | protected function getRemoteClassName($localClass) { 66 | 67 | return SabreAMF_ClassMapper::getRemoteClass($localClass); 68 | 69 | } 70 | 71 | /** 72 | * Checks wether the provided array has string keys and if it's not sparse. 73 | * 74 | * @param array $arr 75 | * @return bool 76 | */ 77 | protected function isPureArray(array $array ) { 78 | $i=0; 79 | foreach($array as $k=>$v) { 80 | if ( $k !== $i ) { 81 | return false; 82 | } 83 | $i++; 84 | } 85 | 86 | return true; 87 | } 88 | 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /lib/SabreAMF/Server.php: -------------------------------------------------------------------------------- 1 | readInput(); 70 | 71 | //file_put_contents($dump.'/' . md5($data),$data); 72 | 73 | $this->amfInputStream = new SabreAMF_InputStream($data); 74 | 75 | $this->amfRequest = new SabreAMF_Message(); 76 | $this->amfOutputStream = new SabreAMF_OutputStream(); 77 | $this->amfResponse = new SabreAMF_Message(); 78 | 79 | $this->amfRequest->deserialize($this->amfInputStream); 80 | 81 | } 82 | 83 | /** 84 | * getRequests 85 | * 86 | * Returns the requests that are made to the gateway. 87 | * 88 | * @return array 89 | */ 90 | public function getRequests() { 91 | 92 | return $this->amfRequest->getBodies(); 93 | 94 | } 95 | 96 | /** 97 | * setResponse 98 | * 99 | * Send a response back to the client (based on a request you got through getRequests) 100 | * 101 | * @param string $target This parameter should contain the same as the 'response' item you got through getRequests. This connects the request to the response 102 | * @param int $responsetype Set as either SabreAMF_Const::R_RESULT or SabreAMF_Const::R_STATUS, depending on if the call succeeded or an error was produced 103 | * @param mixed $data The result data 104 | * @return void 105 | */ 106 | public function setResponse($target,$responsetype,$data) { 107 | 108 | 109 | switch($responsetype) { 110 | 111 | case SabreAMF_Const::R_RESULT : 112 | $target = $target.='/onResult'; 113 | break; 114 | case SabreAMF_Const::R_STATUS : 115 | $target = $target.='/onStatus'; 116 | break; 117 | case SabreAMF_Const::R_DEBUG : 118 | $target = '/onDebugEvents'; 119 | break; 120 | } 121 | return $this->amfResponse->addBody(array('target'=>$target,'response'=>'','data'=>$data)); 122 | 123 | } 124 | 125 | /** 126 | * sendResponse 127 | * 128 | * Sends the responses back to the client. Call this after you answered all the requests with setResponse 129 | * 130 | * @return void 131 | */ 132 | public function sendResponse() { 133 | 134 | header('Content-Type: ' . SabreAMF_Const::MIMETYPE); 135 | $this->amfResponse->setEncoding($this->amfRequest->getEncoding()); 136 | $this->amfResponse->serialize($this->amfOutputStream); 137 | echo($this->amfOutputStream->getRawData()); 138 | 139 | } 140 | 141 | /** 142 | * addHeader 143 | * 144 | * Add a header to the server response 145 | * 146 | * @param string $name 147 | * @param bool $required 148 | * @param mixed $data 149 | * @return void 150 | */ 151 | public function addHeader($name,$required,$data) { 152 | 153 | $this->amfResponse->addHeader(array('name'=>$name,'required'=>$required==true,'data'=>$data)); 154 | 155 | } 156 | 157 | /** 158 | * getRequestHeaders 159 | * 160 | * returns the request headers 161 | * 162 | * @return void 163 | */ 164 | public function getRequestHeaders() { 165 | 166 | return $this->amfRequest->getHeaders(); 167 | 168 | } 169 | 170 | /** 171 | * setInputFile 172 | * 173 | * returns the true/false depended on wheater the stream is readable 174 | * 175 | * @param string $stream New input stream 176 | * 177 | * @author Asbjørn Sloth Tønnesen 178 | * @return bool 179 | */ 180 | static public function setInputFile($stream) { 181 | 182 | if (!is_readable($stream)) return false; 183 | 184 | self::$dataInputStream = $stream; 185 | return true; 186 | 187 | } 188 | 189 | /** 190 | * setInputString 191 | * 192 | * Returns the true/false depended on wheater the string was accepted. 193 | * That a string is accepted by this method, does NOT mean that it is a valid AMF request. 194 | * 195 | * @param string $string New input string 196 | * 197 | * @author Asbjørn Sloth Tønnesen 198 | * @return bool 199 | */ 200 | static public function setInputString($string) { 201 | 202 | if (!(is_string($string) && strlen($string) > 0)) 203 | throw new SabreAMF_InvalidAMFException(); 204 | 205 | self::$dataInputStream = null; 206 | self::$dataInputData = $string; 207 | return true; 208 | 209 | } 210 | 211 | /** 212 | * readInput 213 | * 214 | * Reads the input from stdin unless it has been overwritten 215 | * with setInputFile or setInputString. 216 | * 217 | * @author Asbjørn Sloth Tønnesen 218 | * @return string Binary string containing the AMF data 219 | */ 220 | protected function readInput() { 221 | 222 | if (is_null(self::$dataInputStream)) return self::$dataInputData; 223 | 224 | $data = file_get_contents(self::$dataInputStream); 225 | if (!$data) throw new SabreAMF_InvalidAMFException(); 226 | 227 | return $data; 228 | 229 | } 230 | 231 | } 232 | 233 | 234 | -------------------------------------------------------------------------------- /lib/SabreAMF/TypedObject.php: -------------------------------------------------------------------------------- 1 | setAMFClassName($classname); 21 | $this->setAMFData($data); 22 | 23 | } 24 | 25 | /** 26 | * getAMFClassName 27 | * 28 | * @return string 29 | */ 30 | public function getAMFClassName() { 31 | 32 | return $this->amfClassName; 33 | 34 | } 35 | 36 | /** 37 | * getAMFData 38 | * 39 | * @return mixed 40 | */ 41 | public function getAMFData() { 42 | 43 | return $this->amfData; 44 | 45 | } 46 | 47 | /** 48 | * setAMFClassName 49 | * 50 | * @param string $classname 51 | * @return void 52 | */ 53 | public function setAMFClassName($classname) { 54 | 55 | $this->amfClassName = $classname; 56 | 57 | } 58 | 59 | /** 60 | * setAMFData 61 | * 62 | * @param mixed $data 63 | * @return void 64 | */ 65 | public function setAMFData($data) { 66 | 67 | $this->amfData = $data; 68 | 69 | } 70 | 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /lib/SabreAMF/UndefinedMethodException.php: -------------------------------------------------------------------------------- 1 | message = "Undefined method '$method' in class $class"; 26 | $this->code = "Server.Processing"; 27 | 28 | // Call parent class constructor 29 | parent::__construct( $this->message ); 30 | 31 | } 32 | 33 | public function getDetail() { 34 | 35 | return "Check to ensure that the method is defined, and that it is spelled correctly."; 36 | 37 | } 38 | 39 | 40 | } 41 | 42 | ?> 43 | -------------------------------------------------------------------------------- /lib/SabreAMF/tests/README: -------------------------------------------------------------------------------- 1 | Running tests 2 | ============= 3 | 4 | From SabreAMF directory run the following command: 5 | 6 | $ phpunit tests/alltests.php 7 | 8 | Installing PHPUnit 9 | ================== 10 | 11 | see http://www.phpunit.de/manual/current/en/installation.html 12 | 13 | - or - 14 | 15 | on debian based systems: 16 | sudo aptitude install phpunit 17 | 18 | -------------------------------------------------------------------------------- /lib/SabreAMF/tests/alltests.php: -------------------------------------------------------------------------------- 1 | addTestSuite('AMF3_Tests'); 23 | 24 | return $suite; 25 | } 26 | } 27 | ?> 28 | -------------------------------------------------------------------------------- /lib/SabreAMF/tests/amf3.php: -------------------------------------------------------------------------------- 1 | addTestSuite('Test_AMF3_int'); 14 | 15 | return $suite; 16 | 17 | } 18 | 19 | } 20 | ?> 21 | -------------------------------------------------------------------------------- /lib/SabreAMF/tests/amf3/int.php: -------------------------------------------------------------------------------- 1 | readAMFData(); 19 | 20 | $this->assertEquals($value, $deserialized); 21 | } 22 | 23 | /** 24 | * @dataProvider providerInt 25 | */ 26 | public function testWrite($input, $value, $writebytetest) 27 | { 28 | $amfOutputStream = new SabreAMF_OutputStream($input); 29 | $amfSerializer = new SabreAMF_AMF3_Serializer($amfOutputStream); 30 | $amfSerializer->writeAMFData($value); 31 | $serialized = $amfOutputStream->getRawData(); 32 | 33 | $this->testRead($serialized, $value); 34 | 35 | if ($writebytetest) { 36 | $this->assertEquals($serialized, $input); 37 | } 38 | } 39 | 40 | public function providerInt() 41 | { 42 | 43 | return array( 44 | array( 45 | "\x04\xb7\xfd\x98\x68", 46 | 234788968, 47 | true 48 | ), array( 49 | "\x04\xbf\xff\xff\xff", 50 | 268435455, 51 | true 52 | ), array( 53 | "\x04\x00", 54 | 0, 55 | true 56 | ), array( 57 | "\x04\xff\xff\xff\xff", 58 | -1, 59 | true 60 | ), array( 61 | // signed positive 62 | "\x04\xC0\xA4\xB4\x56", 63 | 1193046, 64 | false // encodes as uint 65 | ), array( 66 | "\x04\xC8\xE8\x56", 67 | 1193046, 68 | true 69 | ), array( 70 | "\x04\xA4\xB4\x56", 71 | 596566, 72 | true 73 | ), array( 74 | "\x04\xe0\x80\x80\x00", 75 | -134217728, 76 | true 77 | ), array( 78 | "\x04\xbf\xff\xff\xff", 79 | 268435455, 80 | true 81 | ), array( 82 | "\x04\xbf\xff\x7f", 83 | 1048575, 84 | true 85 | ), array( 86 | "\x04\xbf\x7f", 87 | 8191, 88 | true 89 | ), array( 90 | "\x04\x3f", 91 | 63, 92 | true 93 | ) 94 | ); 95 | 96 | } 97 | 98 | } 99 | ?> 100 | --------------------------------------------------------------------------------