[ Index ]
 

Code source de Horde 3.1.3

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/SyncML/ -> Device.php (source)

   1  <?php
   2  
   3  
   4  /**
   5   * The SyncML_Device:: class provides functionality that is
   6   * potentially (client) device dependant.
   7   *
   8   * So if a sync client needs any kind of special data of the data sent
   9   * to it or received from it, this is done here. There are two source
  10   * of information to identify an device: The first (and better) one is
  11   * the DevInf device info sent by the device upon a get request. If
  12   * DevInf is not supported or sent by the client, the SourceURI of the
  13   * device may be sufficent to identify it.
  14   *
  15   * Information about a few devices already working with SyncML::
  16   *
  17   * P800/P900/P910:
  18   * ---------------
  19   * Charset:
  20   * This device is able to handle UTF-8 and sends its XML packages in UTF8.
  21   * However even though the XML itself is UTF-8, it expects the enclosed
  22   * vcard-data to be ISO-8859-1 unless explicitly stated otherwise (using the
  23   * CHARSET option, which is deprecated for VCARD 3.0)
  24   *
  25   * Encoding:
  26   * String values are encoded "QUOTED-PRINTABLE"
  27   *
  28   * Other:
  29   * This devices handles tasks and events in one database.
  30   *
  31   * Copyright 2005-2006 Karsten Fourmont <karsten@horde.org>
  32   *
  33   * See the enclosed file COPYING for license information (LGPL). If you did not
  34   * receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  35   *
  36   * $Horde: framework/SyncML/SyncML/Device.php,v 1.7.2.8 2006/05/03 21:42:54 jan Exp $
  37   *
  38   * @author  Karsten Fourmont <karsten@horde.org>
  39   * @package SyncML
  40   */
  41  class SyncML_Device {
  42  
  43      function &factory()
  44      {
  45          $si = SyncML_Device::sourceURI();
  46          $di = SyncML_Device::deviceInfo();
  47  
  48          if (stristr($si, 'sync4j') !== false || stristr($si, 'sc-pim') !== false) {
  49              include_once 'SyncML/Device/Sync4j.php';
  50              $device = &new SyncML_Device_sync4j();
  51          } elseif (!empty($di->_Man) && stristr($di->_Man, 'Sony Ericsson') !== false) {
  52              include_once 'SyncML/Device/P800.php';
  53              $device = &new SyncML_Device_P800();
  54          } elseif (!empty($di->_Man) && stristr($di->_Man, 'synthesis') !== false) {
  55              include_once 'SyncML/Device/Synthesis.php';
  56              $device = &new SyncML_Device_Synthesis();
  57          } elseif (!empty($di->_Man) && stristr($di->_Man, 'nokia') !== false) {
  58              include_once 'SyncML/Device/Nokia.php';
  59              $device = &new SyncML_Device_Nokia();
  60          } else {
  61              $device = &new SyncML_Device();
  62          }
  63  
  64          $GLOBALS['backend']->logMessage('Using device class ' . get_class($device),
  65                                          __FILE__, __LINE__, PEAR_LOG_DEBUG);
  66  
  67          return $device;
  68      }
  69  
  70      function &singleton()
  71      {
  72          static $instance;
  73  
  74          if (!isset($instance)) {
  75              $instance = SyncML_Device::factory();
  76          }
  77  
  78          return $instance;
  79      }
  80  
  81      /**
  82       * Returns the SourceURI from state.
  83       */
  84      function sourceURI()
  85      {
  86          return $_SESSION['SyncML.state']->getSourceURI();
  87      }
  88  
  89      /**
  90       * Returns the DevInf class from state.
  91       */
  92      function deviceInfo()
  93      {
  94          return $_SESSION['SyncML.state']->getDeviceInfo();
  95      }
  96  
  97      /**
  98       * When a client sends data during a sync but does not provide
  99       * information about the contenttype with this individual item,
 100       * this function returns the contenttype the item is supposed to be in.
 101       *
 102       * As this is only used to parse to the horde's importdata api functions,
 103       * some simple guesses for the contenttype are completely sufficient:
 104       * Horde does not care whether data is text/x-vcalendar or text/calendar.
 105       */
 106      function getPreferredContentType($type)
 107      {
 108          if ($type == 'contacts') {
 109              return 'text/x-vcard';
 110          } elseif ($type == 'notes') {
 111              return 'text/x-vnote';
 112          } elseif ($type == 'tasks') {
 113              return 'text/calendar';
 114          } elseif ($type == 'calendar') {
 115              return 'text/calendar';
 116          }
 117      }
 118  
 119      /**
 120       * Returns the preferrred contenttype of the client for the given
 121       * sync data type (contacts/tasks/notes/calendar).
 122       *
 123       * The result is passed as an option to the Horde API export functions.
 124       * Please note that this is not the contentType ultimately passed to the
 125       * client but rather the contentType presented to the Horde API export
 126       * functions. For example the contact api supports a contenttype 
 127       * text/x-vcard;version=2.1 to create a vcard in vcard 2.1 format.
 128       *
 129       * After the data is retrieved from horde, convertServer2Client can do
 130       * some post-processing and set the correct contentType acceptable for
 131       * the client if necessary.
 132       *
 133       * The default implementation tries to extract the contenttype from the
 134       * presented device info. If this does not work, some default are used.
 135       *
 136       * If the client does not provice proper DevInf data, this function may
 137       * have to be overwritten to return the correct values.
 138       *
 139       * ServerSyncURI: The server database of the sync:
 140       *                contacts|notes|calendar|tasks
 141       * sourceSyncURI: The URI for the client database. This is needed as
 142       *                the DevInf is arranged by sourceSyncURIs
 143       */
 144       
 145      function getPreferredContentTypeClient($serverSyncURI, $sourceSyncURI)
 146      {
 147          $di = $this->deviceInfo();
 148          $ds = $di->getDataStore($sourceSyncURI);
 149          if (!empty($ds)) {
 150              $r = $ds->getPreferredRXContentType();
 151              if (!empty($ds)) {
 152                  if ($r == 'text/x-vcard' &&
 153                          $ds->getPreferredRXContentTypeVersion() == '2.1') {
 154                      /* Special custom mimetype which makes the horde turba API
 155                       * return a version 2.1 rather than 3.0 vcard.
 156                       */
 157                      return 'text/x-vcard;version=2.1';
 158                  }
 159                  return $r;
 160              }
 161          }
 162  
 163          /* No Info in DevInf. Use defaults: */
 164          if ($serverSyncURI == 'contacts') {
 165              return 'text/x-vcard';
 166          } elseif ($serverSyncURI == 'notes') {
 167              return 'text/x-vnote';
 168          } elseif ($serverSyncURI == 'tasks') {
 169              return 'text/x-vtodo';
 170          } elseif ($serverSyncURI == 'calendar') {
 171              return 'text/calendar';
 172          }
 173      }
 174  
 175      /**
 176       * Convert the content received from the client for the horde backend.
 177       *
 178       * Currently strips uid (primary key) information as client and
 179       * server might use different ones.
 180       *
 181       * Charset conversions might be added here too.
 182       *
 183       * @param string $content       The content to convert
 184       * @param string $contentType   The contentType of the content
 185       *
 186       * @return array                array($newcontent, $newcontentType):
 187       *                              the converted content and the
 188       *                              (possibly changed) new ContentType.
 189       */
 190      function convertClient2Server($content, $contentType)
 191      {
 192          global $backend;
 193          if (DEBUGLOG_ICALENDARDATA) {
 194              $fp = @fopen('/tmp/sync/log.txt', 'a');
 195              if ($fp) {
 196                  @fwrite($fp, "\ninput received from client ($contentType)\n");
 197                  if (strstr($contentType,'sif/') !== false) {
 198                      // sync4fj sif/* data is base64_encoded.
 199                      @fwrite($fp, base64_decode($content) . "\n");
 200                  } else {
 201                      @fwrite($fp, $content . "\n");
 202                  }
 203                  @fclose($fp);
 204              }
 205          }
 206  
 207          // Always remove client UID. UID will be seperately passed in
 208          // XML.
 209          $content = preg_replace('/(\r\n|\r|\n)UID:.*?(\r\n|\r|\n)/', '\1', $content, 1);
 210  
 211          if ($this->needsCategoryMapping() &&
 212              preg_match('/(\r\n|\r|\n)CATEGORIES[^\:]*:(.*?)(\r\n|\r|\n)/',
 213                         $content, $m)) {
 214              $cats = explode(',', $m[2]);
 215              if( preg_match('/(\r\n|\r|\n)SUMMARY[^\:]*:(.*?)(\r\n|\r|\n)/',
 216                         $content, $m)) {
 217                  $summary = $m[2];
 218              } else {
 219                  $summary = 'unknown';
 220              }
 221  
 222  
 223              foreach ($cats as $cat) {
 224                  $results[] = $backend->mapClientCategory2Server($cat, $summary);
 225              }
 226              $content = preg_replace('/(\r\n|\r|\nCATEGORIES[^\:]*:)(.*?)(\r\n|\r|\n)/',
 227                                      '$1' . implode(',',$results) . '$3', $content);
 228  
 229          }
 230          // Ensure valid newline termination.
 231          if (substr($content, -1) != "\n" && substr($content, -1) != "\r") {
 232              $content .= "\r\n";
 233          }
 234  
 235          return array($content, $contentType);
 236      }
 237  
 238      /**
 239       * Converts the content from the backend to a format suitable for the
 240       * client device.
 241       *
 242       * Strips the uid (primary key) information as client and server might use
 243       * different ones.
 244       *
 245       * Charset conversions might be added here too.
 246       *
 247       * @param string $content       The content to convert
 248       * @param string $contentType   The contentType of content as returned from
 249       *                              the backend
 250       * @return array                array($newcontent, $newcontentType):
 251       *                              the converted content and the
 252       *                              (possibly changed) new ContentType.
 253       */
 254      function convertServer2Client($content, $contentType)
 255      {
 256          global $backend;
 257          if (is_array($contentType)) {
 258              $contentType = $contentType['ContentType'];
 259          }
 260  
 261          if (DEBUGLOG_ICALENDARDATA) {
 262              $fp = @fopen('/tmp/sync/log.txt', 'a');
 263              if ($fp) {
 264                  @fwrite($fp, "\noutput received from horde backend " .
 265                          "($contentType):\n");
 266                  @fwrite($fp,$content . "\n");
 267                  @fclose($fp);
 268              }
 269          }
 270  
 271          /* Remove special version=2.1 indicator used for horde api. */
 272          if ($contentType == 'text/x-vcard;version=2.1') {
 273              $contentType = 'text/x-vcard';
 274          }
 275  
 276          /* Always remove server UID. UID will be seperately passed in XML. */
 277          $content = preg_replace('/(\r\n|\r|\n)UID:.*?(\r\n|\r|\n)/', '\1', $content, 1);
 278  
 279          $di = $this->deviceInfo();
 280  
 281          if ($this->needsCategoryMapping() &&
 282              preg_match('/(\r\n|\r|\n)CATEGORIES[^\:]*:(.*?)(\r\n|\r|\n)/',
 283                         $content, $m)) {
 284              $cats = explode(',', $m[2]);
 285  
 286              if( preg_match('/(\r\n|\r|\n)SUMMARY[^\:]*:(.*?)(\r\n|\r|\n)/',
 287                         $content, $m)) {
 288                  $summary = $m[2];
 289              } else {
 290                  $summary = 'unknown';
 291              }
 292  
 293              foreach ($cats as $cat) {
 294                  $results[] = $backend->mapServerCategory2Client($cat, $summary);
 295              }
 296              preg_replace('/(\r\n|\r|\nCATEGORIES[^\:]*:)(.*?)(\r\n|\r|\n)/',
 297                           '$1' . implode(',',$results) . '$2', $content);
 298          }
 299  
 300          switch ($contentType) {
 301          case 'text/calendar' :
 302          case 'text/x-icalendar' :
 303          case 'text/x-vcalendar' :
 304          case 'text/x-vevent' :
 305          case 'text/x-vtodo' :
 306          case 'text/x-vnote':
 307              break;
 308  
 309          case 'text/x-vcard' :
 310              // If we can extract from the Device Info, that the client
 311              // uses TEL;WORK: 0800 123 instead of TEL;TYPE=WORK:
 312              // 0800123, convert the data accordingly.
 313              if (!empty($di->_CTCap['text/x-vcard']['TEL']) &&
 314                  empty($di->_CTCap['text/x-vcard']['TEL']->_params['TYPE']) &&
 315                  !empty($di->_CTCap['text/x-vcard']['TEL']->_params['VOICE'])) {
 316                  $content = preg_replace('/(\r\n|\r|\n)TEL;TYPE=HOME/', '\1TEL;HOME;VOICE', $content, 1);
 317                  $content = preg_replace('/(\r\n|\r|\n)TEL;TYPE=WORK/', '\1TEL;WORK;VOICE', $content, 1);
 318                  $content = preg_replace('/(\r\n|\r|\n)TEL;TYPE=CELL/', '\1TEL;VOICE;CELL', $content, 1);
 319                  $content = preg_replace('/(\r\n|\r|\n)TEL;TYPE=FAX/', '\1TEL;WORK;FAX', $content, 1);
 320                  $content = preg_replace('/(\r\n|\r|\n)TEL;TYPE=PAGER/', '\1TEL;PAGER;WORK', $content, 1);
 321              }
 322  
 323              // If we can extract from the Device Info, that the client
 324              // uses ADR;WORK: ... instead of ADR;TYPE=WORK: 0800123,
 325              // convert the data accordingly.
 326              if (!empty($di->_CTCap['text/x-vcard']['ADR']) &&
 327                  empty($di->_CTCap['text/x-vcard']['ADR']->_params['TYPE']) &&
 328                  !empty($di->_CTCap['text/x-vcard']['ADR']->_params['WORK'])) {
 329                  $content = preg_replace('/(\r\n|\r|\n)ADR;TYPE=WORK/', '\1ADR;WORK', $content, 1);
 330                  $content = preg_replace('/(\r\n|\r|\n)ADR;TYPE=HOME/', '\1ADR;HOME', $content, 1);
 331              }
 332  
 333              break;
 334          }
 335  
 336          return array($content, $contentType);
 337      }
 338  
 339      /**
 340       * Some devices like the Sony Ericsson P800/P900/P910 handle
 341       * vtodos (tasks) and vevents in the same "calendar" sync.  This
 342       * requires special actions on our side as we store this in
 343       * different databases (nag and kronolith).  This function
 344       * determines whether the client does it like that.  Currently
 345       * this is done by checking the DevInf information. For different
 346       * clients there may be different ways to find out how the client
 347       * likes its tasks.
 348       */
 349      function handleTasksInCalendar()
 350      {
 351          // Default: tasks and events are seperate databases.
 352          return false;
 353      }
 354  
 355      /**
 356       * Some devices need a mapping of client vs. server categorie names.
 357       * The backend provides a mechanism for this mapping. It is used
 358       * when this needsCategoryMapping returns true.
 359       * For special cases the mapping may also be implemented directly in
 360       * convertClient2Server and convertServer2Client. In this case
 361       * needsCategoryMapping may return false.
 362       */
 363      function needsCategoryMapping()
 364      {
 365          return false;
 366      }
 367  
 368  }


Généré le : Sun Feb 25 18:01:28 2007 par Balluche grâce à PHPXref 0.7