"Fossies" - the Fresh Open Source Software Archive

Member "z-push/streamer.php" (2 Aug 2013, 14235 Bytes) of package /linux/www/old/group-e_z-push_v3.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "streamer.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 /***********************************************
    3 * File      :   streamer.php
    4 * Project   :   Z-Push
    5 * Descr     :   This file handles streaming of
    6 *                WBXML objects. It must be
    7 *                subclassed so the internals of
    8 *                the object can be specified via
    9 *                $mapping. Basically we set/read
   10 *                the object variables of the
   11 *                subclass according to the mappings
   12 *
   13 *
   14 * Created   :   01.10.2007
   15 *
   16 * � Zarafa Deutschland GmbH, www.zarafaserver.de
   17 * This file is distributed under GPL v2.
   18 * Consult LICENSE file for details
   19 ************************************************/
   20 include_once("zpushdtd.php");
   21 
   22 define('STREAMER_VAR', 1);
   23 define('STREAMER_ARRAY', 2);
   24 define('STREAMER_TYPE', 3);
   25 
   26 define('STREAMER_TYPE_DATE', 1);
   27 define('STREAMER_TYPE_HEX', 2);
   28 define('STREAMER_TYPE_DATE_DASHES', 3);
   29 define('STREAMER_TYPE_MAPI_STREAM', 4);
   30 
   31 
   32 class Streamer {
   33     var $_mapping;
   34 
   35     var $content;
   36     var $attributes;
   37     var $flags;
   38     var $_setread;
   39     var $_setchange;
   40     var $_setflag;
   41 
   42     function Streamer($mapping) {
   43         $this->_mapping = $mapping;
   44         $this->flags = false;
   45         $this->_setflag = false;
   46         $this->_setchange = false;
   47         $this->_setread = false;
   48         $this->_setcategories = false;
   49     }
   50 
   51     // Decodes the WBXML from $input until we reach the same depth level of WBXML. This
   52     // means that if there are multiple objects at this level, then only the first is decoded
   53     // SubOjects are auto-instantiated and decoded using the same functionality
   54     function decode(&$decoder) {
   55 
   56         // START HACK dw2412
   57         // We need this just for decoding items sent by HTC Android Devices (HTC DESIRE Z - maybe others!) the right way...
   58         switch (get_class($this)) {
   59             case "SyncAppointment" :
   60                 if (!isset($this->_mapping[SYNC_POOMCAL_BODY]))
   61                     $this->_mapping += array(
   62                                 SYNC_POOMCAL_BODY => array (STREAMER_VAR => "body"),
   63                                 SYNC_POOMCAL_BODYTRUNCATED => array (STREAMER_VAR => "bodytruncated"),
   64                                 SYNC_POOMCAL_RTF => array (STREAMER_VAR => "rtf"),
   65                             );
   66                 break;
   67             case "SyncContact" :
   68                 if (!isset($this->_mapping[SYNC_POOMCONTACTS_BODY]))
   69                     $this->_mapping += array(
   70                                 SYNC_POOMCONTACTS_RTF => array (STREAMER_VAR => "rtf"),
   71                                 SYNC_POOMCONTACTS_BODY => array (STREAMER_VAR => "body"),
   72                                 SYNC_POOMCONTACTS_BODYSIZE => array (STREAMER_VAR => "bodysize"),
   73                                 SYNC_POOMCONTACTS_BODYTRUNCATED => array (STREAMER_VAR => "bodytruncated"),
   74                             );
   75                 break;
   76         }
   77         // END HACK dw2412
   78 
   79         while(1) {
   80             $entity = $decoder->getElement();
   81             if (isset($entity[EN_TAG])) {
   82                 switch ($entity[EN_TAG]) {
   83                     case "POOMMAIL:Read" : 
   84                         $this->_setread=true; break;
   85                     case "POOMMAIL:Flag" : 
   86                         $this->_setflag=true; break;
   87                     case "POOMMAIL:Categories" : 
   88                         $this->_setcategories=true; break;
   89                     default : 
   90                         $this->_setflag=false; 
   91                         $this->_setread=false; 
   92                         $this->_setcategories=false; 
   93                         $this->_setchange=true;
   94                 };
   95             };
   96 
   97             if($entity[EN_TYPE] == EN_TYPE_STARTTAG) {
   98                 if(! ($entity[EN_FLAGS] & EN_FLAGS_CONTENT) && (isset($entity[EN_TAG]) && $entity[EN_TAG] != '' && isset($this->_mapping[$entity[EN_TAG]]))) {
   99                     $map = $this->_mapping[$entity[EN_TAG]];
  100                     if(!isset($map[STREAMER_TYPE])) {
  101                         $this->$map[STREAMER_VAR] = "";
  102                     } else if ($map[STREAMER_TYPE] == STREAMER_TYPE_DATE || $map[STREAMER_TYPE] == STREAMER_TYPE_DATE_DASHES ) {
  103                         $this->$map[STREAMER_VAR] = "";
  104                     } else if ($map[STREAMER_TYPE] == "SyncPoommailFlag") { // added dw2412 to support empty flag = flag to delete
  105                         $this->poommailflag = new SyncPoommailFlag();
  106                         $this->poommailflag->flagstatus="";
  107                     }
  108                     continue;
  109                 } else if (! ($entity[EN_FLAGS] & EN_FLAGS_CONTENT) && (!isset($entity[EN_TAG]) || $entity[EN_TAG] == '' || !isset($this->_mapping[$entity[EN_TAG]])))
  110                     debugLog("Streamer::DEBUGDEBUGDEBUG:".print_r($entity,true));
  111                 // Found a start tag
  112                 if(!isset($this->_mapping[$entity[EN_TAG]])) {
  113                     // This tag shouldn't be here, abort
  114                     debugLog("Tag " . $entity[EN_TAG] . " unexpected in type XML type " . get_class($this));
  115                     return false;
  116                 } else {
  117                     $map = $this->_mapping[$entity[EN_TAG]];
  118 
  119                     // Handle an array
  120                     if(isset($map[STREAMER_ARRAY])) {
  121                         while(1) {
  122                             if(!$decoder->getElementStartTag($map[STREAMER_ARRAY]))
  123                                 break;
  124                             if(isset($map[STREAMER_TYPE])) {
  125                                 $decoded = new $map[STREAMER_TYPE];
  126                                 $decoded->decode($decoder);
  127                             } else {
  128                                 $decoded = $decoder->getElementContent();
  129                             }
  130 
  131                             if(!isset($this->$map[STREAMER_VAR]))
  132                                 $this->$map[STREAMER_VAR] = array($decoded);
  133                             else
  134                                 array_push($this->$map[STREAMER_VAR], $decoded);
  135 
  136                             if(!$decoder->getElementEndTag())
  137                                 return false;
  138                         }
  139                         if(!$decoder->getElementEndTag())
  140                             return false;
  141                     } else { // Handle single value
  142                         if(isset($map[STREAMER_TYPE])) {
  143                             // Complex type, decode recursively
  144                             if($map[STREAMER_TYPE] == STREAMER_TYPE_DATE || $map[STREAMER_TYPE] == STREAMER_TYPE_DATE_DASHES) {
  145                                 $decoded = $this->parseDate($decoder->getElementContent());
  146                                 if(!$decoder->getElementEndTag())
  147                                     return false;
  148                             } else if($map[STREAMER_TYPE] == STREAMER_TYPE_HEX) {
  149                                 $decoded = hex2bin($decoder->getElementContent());
  150                                 if(!$decoder->getElementEndTag())
  151                                     return false;
  152                             } else {
  153                                 $subdecoder = new $map[STREAMER_TYPE]();
  154                                 if($subdecoder->decode($decoder) === false)
  155                                     return false;
  156 
  157                                 $decoded = $subdecoder;
  158 
  159                                 if(!$decoder->getElementEndTag()) {
  160                                     debugLog("No end tag for " . $entity[EN_TAG]);
  161                                     return false;
  162                                 }
  163                             }
  164                         } else {
  165                             // Simple type, just get content
  166                             $decoded = $decoder->getElementContent();
  167 
  168                             if($decoded === false) {
  169 //                                debug("Unable to get content for " . $entity[EN_TAG]);
  170 //                                return false;
  171                                 // the tag is declared to have content, but no content is available.
  172                                 // set an empty content
  173                                 $decoded = "";
  174                             }
  175 
  176                             if(!$decoder->getElementEndTag()) {
  177                                 debugLog("Unable to get end tag for " . $entity[EN_TAG]);
  178                                 return false;
  179                             }
  180                         }
  181                         // $decoded now contains data object (or string)
  182                         $this->$map[STREAMER_VAR] = $decoded;
  183                     }
  184                 }
  185             }
  186             else if($entity[EN_TYPE] == EN_TYPE_ENDTAG) {
  187                 $decoder->ungetElement($entity);
  188                 break;
  189             }
  190             else {
  191                 debugLog("Unexpected content in type");
  192                 break;
  193             }
  194         }
  195     }
  196 
  197     // Encodes this object and any subobjects - output is ordered according to mapping
  198     function encode(&$encoder) {
  199         $attributes = isset($this->attributes) ? $this->attributes : array();
  200 
  201         foreach($this->_mapping as $tag => $map) {
  202             if(isset($this->$map[STREAMER_VAR])) {
  203                 // Variable is available
  204                 if(is_object($this->$map[STREAMER_VAR])) {
  205                     // Subobjects can do their own encoding
  206                     $encoder->startTag($tag);
  207                     $this->$map[STREAMER_VAR]->encode($encoder);
  208                     $encoder->endTag();
  209                 } else if(isset($map[STREAMER_ARRAY])) {
  210                     // Array of objects
  211                     $encoder->startTag($tag); // Outputs array container (eg Attachments)
  212                     foreach ($this->$map[STREAMER_VAR] as $element) {
  213                         if(is_object($element)) {
  214                             $encoder->startTag($map[STREAMER_ARRAY]); // Outputs object container (eg Attachment)
  215                             $element->encode($encoder);
  216                             $encoder->endTag();
  217                         } else {
  218                             if(strlen($element) == 0)
  219                                   // Do not output empty items. Not sure if we should output an empty tag with $encoder->startTag($map[STREAMER_ARRAY], false, true);
  220                                   ;
  221                             else {
  222                                 $encoder->startTag($map[STREAMER_ARRAY]);
  223                                 $encoder->content($element);
  224                                 $encoder->endTag();
  225                             }
  226                         }
  227                     }
  228                     $encoder->endTag();
  229                 } else {
  230                     // Simple type
  231                     if(strlen($this->$map[STREAMER_VAR]) == 0) {
  232                           // Do not output empty items. See above: $encoder->startTag($tag, false, true);
  233                         continue;
  234                     } else if ($encoder->_multipart == true &&
  235                         ($tag == SYNC_AIRSYNCBASE_DATA ||
  236                          $tag == SYNC_AIRSYNCBASE_ATTACHMENT ||
  237                          $tag == SYNC_ITEMOPERATIONS_DATA)) {  // START ADDED dw2412 to support mulitpart output
  238                     $encoder->_bodyparts[] = $this->$map[STREAMER_VAR];
  239                     $encoder->startTag(SYNC_ITEMOPERATIONS_PART);
  240                     $encoder->content("".(sizeof($encoder->_bodyparts)-1)."");
  241                     $encoder->endTag();
  242             continue; // END ADDED dw2412 to support mulitpart output
  243                     } else if ($encoder->_multipart == false &&
  244                         ($tag == SYNC_ITEMOPERATIONS_DATA)) {  // START ADDED dw2412 to support mulitpart output
  245                     $encoder->startTag($tag);
  246                     $encoder->content(base64_encode($this->$map[STREAMER_VAR]));
  247                     $encoder->endTag();
  248             continue; // END ADDED dw2412 to support mulitpart output
  249                     } else
  250                         $encoder->startTag($tag);
  251 
  252                     if(isset($map[STREAMER_TYPE]) && ($map[STREAMER_TYPE] == STREAMER_TYPE_DATE || $map[STREAMER_TYPE] == STREAMER_TYPE_DATE_DASHES)) {
  253                         if($this->$map[STREAMER_VAR] != 0) // don't output 1-1-1970
  254                             $encoder->content($this->formatDate($this->$map[STREAMER_VAR], $map[STREAMER_TYPE]));
  255                     } else if(isset($map[STREAMER_TYPE]) && $map[STREAMER_TYPE] == STREAMER_TYPE_HEX) {
  256                         $encoder->content(strtoupper(bin2hex($this->$map[STREAMER_VAR])));
  257                     } else if(isset($map[STREAMER_TYPE]) && $map[STREAMER_TYPE] == STREAMER_TYPE_MAPI_STREAM) {
  258                         $encoder->content($this->$map[STREAMER_VAR]);
  259                     } else if ($tag == SYNC_POOMMAIL2_CONVERSATIONINDEX ||
  260                     $tag == SYNC_POOMMAIL2_CONVERSATIONID) {
  261                         $encoder->contentopaque($this->$map[STREAMER_VAR]);
  262                     } else {
  263                         $encoder->content($this->$map[STREAMER_VAR]);
  264                     }
  265                     $encoder->endTag();
  266                 }
  267             }
  268         }
  269         // Output our own content
  270         if(isset($this->content))
  271             $encoder->content($this->content);
  272 
  273     }
  274 
  275 
  276 
  277     // Oh yeah. This is beautiful. Exchange outputs date fields differently in calendar items
  278     // and emails. We could just always send one or the other, but unfortunately nokia's 'Mail for
  279     // exchange' depends on this quirk. So we have to send a different date type depending on where
  280     // it's used. Sigh.
  281     function formatDate($ts, $type) {
  282         if($type == STREAMER_TYPE_DATE)
  283             return gmstrftime("%Y%m%dT%H%M%SZ", $ts);
  284         else if($type == STREAMER_TYPE_DATE_DASHES)
  285             return gmstrftime("%Y-%m-%dT%H:%M:%S.000Z", $ts);
  286     }
  287 
  288     function parseDate($ts) {
  289         if(preg_match("/(\d{4})[^0-9]*(\d{2})[^0-9]*(\d{2})T(\d{2})[^0-9]*(\d{2})[^0-9]*(\d{2})(.\d+)?Z/", $ts, $matches)) {
  290             if ($matches[1] >= 2038){
  291                 $matches[1] = 2038;
  292                 $matches[2] = 1;
  293                 $matches[3] = 18;
  294                 $matches[4] = $matches[5] = $matches[6] = 0;
  295             }
  296             return gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
  297         } else if (preg_match("/(\d{4})[^0-9]*(\d{2})[^0-9]*(\d{2})/", $ts, $matches)) { // Fixes SAMSUNG Date Problem. Samsung send in Contacts dates only the date without time information... unfortunately...
  298             if ($matches[1] >= 2038){
  299                 $matches[1] = 2038;
  300                 $matches[2] = 1;
  301                 $matches[3] = 18;
  302             }
  303             $matches[4] = $matches[5] = $matches[6] = 0;
  304             return gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
  305         }
  306         return 0;
  307     }
  308 };
  309 
  310 ?>