[ Index ] |
|
Code source de Horde 3.1.3 |
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 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |