The Sync4J outlook converter uses its native SIF format for data exchange. Conversion to text/vcalendar etc. is done by SifConverter.php The connector seems not support DevInf information, so Horde_SyncMl_Device can only detect it by the decice ID: so in the connector configuration the device ID must be set to 'sc-pim-' which should be the default anyhow. Copyright 2005-2016 Horde LLC (http://www.horde.org/) See the enclosed file COPYING for license information (LGPL). If you did not receive this file, see http://www.horde.org/licenses/lgpl21.
Author: Karsten Fourmont (karsten@horde.org)
Inheritance: extends Horde_SyncMl_Device
Example #1
0
 public function vtodo2sif($vcard)
 {
     $iCal = new Horde_Icalendar();
     if (!$iCal->parsevCalendar($vcard)) {
         return PEAR::raiseError('There was an error importing the data.');
     }
     $components = $iCal->getComponents();
     switch (count($components)) {
         case 0:
             return PEAR::raiseError('No data was found');
         case 1:
             $content = $components[0];
             break;
         default:
             return PEAR::raiseError('Multiple components found; only one is supported.');
     }
     $hash['Complete'] = 0;
     $due = false;
     $attr = $content->getAllAttributes();
     foreach ($attr as $item) {
         switch ($item['name']) {
             case 'SUMMARY':
                 $hash['Subject'] = $item['value'];
                 break;
             case 'DESCRIPTION':
                 $hash['Body'] = $item['value'];
                 break;
             case 'PRIORITY':
                 if ($item['value'] == 1) {
                     $hash['Importance'] = 2;
                 } elseif ($item['value'] == 5) {
                     $hash['Importance'] = 0;
                 } else {
                     $hash['Importance'] = 1;
                 }
                 break;
             case 'DTSTART':
                 $hash['StartDate'] = Horde_Icalendar::_exportDateTime($item['value']);
                 break;
             case 'DUE':
                 $hash['DueDate'] = Horde_Icalendar::_exportDateTime($item['value']);
                 $due = $item['value'];
                 break;
             case 'AALARM':
                 $hash['ReminderTime'] = $item['value'];
                 $hash['ReminderSet'] = 1;
                 break;
             case 'STATUS':
                 $hash['Complete'] = $item['value'] == 'COMPLETED' ? 1 : 0;
                 break;
             case 'CATEGORIES':
                 $hash['Categories'] = $item['value'];
                 break;
             case 'CLASS':
                 switch (Horde_String::upper($item['value'])) {
                     case 'PUBLIC':
                         $hash['Sensitivity'] = 0;
                         break;
                     case 'PRIVATE':
                         $hash['Sensitivity'] = 2;
                         break;
                     case 'CONFIDENTIAL':
                         $hash['Sensitivity'] = 3;
                         break;
                 }
                 break;
         }
     }
     if ($due && !isset($hash['ReminderSet'])) {
         // Parse VALARM components.
         foreach ($content->getComponents() as $component) {
             if ($component->getType() != 'vAlarm') {
                 continue;
             }
             try {
                 $trigger = $component->getAttribute('TRIGGER');
             } catch (Horde_Icalendar_Exception $e) {
                 continue;
             }
             if (is_array($trigger) || empty($trigger)) {
                 continue;
             }
             $hash['ReminderSet'] = 1;
             $hash['ReminderTime'] = Horde_Icalendar::_exportDateTime($due - $trigger);
         }
     }
     return Horde_SyncMl_Device_sync4j::array2sif($hash, '<?xml version="1.0"?><task>', '</task>');
 }
Example #2
0
/**
 * When a test case contains adds/modifies/deletes being sent to the server,
 * these changes must be extracted from the test data and manually performed
 * using the api to achieve the desired behaviour by the server
 *
 * @throws Horde_Exception
 */
function testPre($name, $number)
{
    global $debuglevel;
    $ref0 = getClient($name, $number);
    // Extract database (in horde: service).
    if (preg_match('|<Alert>.*?<Target>\\s*<LocURI>([^>]*)</LocURI>.*?</Alert>|si', $ref0, $m)) {
        $GLOBALS['service'] = $m[1];
    }
    if (!preg_match('|<SyncHdr>.*?<Source>\\s*<LocURI>(.*?)</LocURI>.*?</SyncHdr>|si', $ref0, $m)) {
        echo $ref0;
        throw new Horde_Exception('Unable to find device id');
    }
    $device_id = $m[1];
    // Start backend session if not already done.
    if ($GLOBALS['testbackend']->getSyncDeviceID() != $device_id) {
        $GLOBALS['testbackend']->sessionStart($device_id, null, Horde_SyncMl_Backend::MODE_TEST);
    }
    // This makes a login even when a logout has occured when the session got
    // deleted.
    $GLOBALS['testbackend']->setUser(SYNCMLTEST_USERNAME);
    $ref1 = getServer($name, $number + 1);
    if (!$ref1) {
        return;
    }
    $ref1 = str_replace(array('<![CDATA[', ']]>', '<?xml version="1.0"?><!DOCTYPE SyncML PUBLIC "-//SYNCML//DTD SyncML 1.1//EN" "http://www.syncml.org/docs/syncml_represent_v11_20020213.dtd">'), '', $ref1);
    // Check for Adds.
    if (preg_match_all('|<Add>.*?<type[^>]*>(.*?)</type>.*?<LocURI[^>]*>(.*?)</LocURI>.*?<data[^>]*>(.*?)</data>.*?</Add|si', $ref1, $m, PREG_SET_ORDER)) {
        foreach ($m as $c) {
            list(, $contentType, $locuri, $data) = $c;
            // Some Sync4j tweaking.
            switch (Horde_String::lower($contentType)) {
                case 'text/x-s4j-sifn':
                    $data = Horde_SyncMl_Device_sync4j::sif2vnote(base64_decode($data));
                    $contentType = 'text/x-vnote';
                    $service = 'notes';
                    break;
                case 'text/x-s4j-sifc':
                    $data = Horde_SyncMl_Device_sync4j::sif2vcard(base64_decode($data));
                    $contentType = 'text/x-vcard';
                    $service = 'contacts';
                    break;
                case 'text/x-s4j-sife':
                    $data = Horde_SyncMl_Device_sync4j::sif2vevent(base64_decode($data));
                    $contentType = 'text/calendar';
                    $service = 'calendar';
                    break;
                case 'text/x-s4j-sift':
                    $data = Horde_SyncMl_Device_sync4j::sif2vtodo(base64_decode($data));
                    $contentType = 'text/calendar';
                    $service = 'tasks';
                    break;
                case 'text/x-vcalendar':
                case 'text/calendar':
                    if (preg_match('/(\\r\\n|\\r|\\n)BEGIN:\\s*VTODO/', $data)) {
                        $service = 'tasks';
                    } else {
                        $service = 'calendar';
                    }
                    break;
                default:
                    throw new Horde_Exception("Unable to find service for contentType={$contentType}");
            }
            $result = $GLOBALS['testbackend']->addEntry($service, $data, $contentType);
            if (is_a($result, 'PEAR_Error')) {
                echo "error importing data into {$service}:\n{$data}\n";
                throw new Horde_Exception_Wrapped($result);
            }
            if ($debuglevel >= 2) {
                echo "simulated {$service} add of {$result} as {$locuri}!\n";
                echo '   at ' . date('Y-m-d H:i:s') . "\n";
                if ($debuglevel >= 10) {
                    echo "data: {$data}\nsuid={$result}\n";
                }
            }
            // Store UID used by server.
            $GLOBALS['mapping_locuri2uid'][$locuri] = $result;
        }
    }
    // Check for Replaces.
    if (preg_match_all('|<Replace>.*?<type[^>]*>(.*?)</type>.*?<LocURI[^>]*>(.*?)</LocURI>.*?<data[^>]*>(.*?)</data>.*?</Replace|si', $ref1, $m, PREG_SET_ORDER)) {
        foreach ($m as $c) {
            list(, $contentType, $locuri, $data) = $c;
            // Some Sync4j tweaking.
            switch (Horde_String::lower($contentType)) {
                case 'sif/note':
                case 'text/x-s4j-sifn':
                    $data = Horde_SyncMl_Device_sync4j::sif2vnote(base64_decode($data));
                    $contentType = 'text/x-vnote';
                    $service = 'notes';
                    break;
                case 'sif/contact':
                case 'text/x-s4j-sifc':
                    $data = Horde_SyncMl_Device_sync4j::sif2vcard(base64_decode($data));
                    $contentType = 'text/x-vcard';
                    $service = 'contacts';
                    break;
                case 'sif/calendar':
                case 'text/x-s4j-sife':
                    $data = Horde_SyncMl_Device_sync4j::sif2vevent(base64_decode($data));
                    $contentType = 'text/calendar';
                    $service = 'calendar';
                    break;
                case 'sif/task':
                case 'text/x-s4j-sift':
                    $data = Horde_SyncMl_Device_sync4j::sif2vtodo(base64_decode($data));
                    $contentType = 'text/calendar';
                    $service = 'tasks';
                    break;
                case 'text/x-vcalendar':
                case 'text/calendar':
                    if (preg_match('/(\\r\\n|\\r|\\n)BEGIN:\\s*VTODO/', $data)) {
                        $service = 'tasks';
                    } else {
                        $service = 'calendar';
                    }
                    break;
                default:
                    throw new Horde_Exception("Unable to find service for contentType={$contentType}");
            }
            /* Get SUID. */
            $suid = $GLOBALS['testbackend']->getSuid($service, $locuri);
            if (empty($suid)) {
                throw new Horde_Exception("Unable to find SUID for CUID {$locuri} for simulating replace");
            }
            $result = $GLOBALS['testbackend']->replaceEntry($service, $data, $contentType, $suid);
            if (is_a($result, 'PEAR_Error')) {
                echo "Error replacing data {$locuri} suid={$suid}!\n";
                throw new Horde_Exception_Wrapped($result);
            }
            if ($debuglevel >= 2) {
                echo "simulated {$service} replace of {$locuri} suid={$suid}!\n";
                if ($debuglevel >= 10) {
                    echo "data: {$data}\nnew id={$result}\n";
                }
            }
        }
    }
    // Check for Deletes.
    // <Delete><CmdID>5</CmdID><Item><Target><LocURI>1798147</LocURI></Target></Item></Delete>
    if (preg_match_all('|<Delete>.*?<Target>\\s*<LocURI>(.*?)</LocURI>|si', $ref1, $m, PREG_SET_ORDER)) {
        foreach ($m as $d) {
            list(, $locuri) = $d;
            /* Get SUID. */
            $service = $GLOBALS['service'];
            $suid = $GLOBALS['testbackend']->getSuid($service, $locuri);
            if (empty($suid)) {
                // Maybe we have a handletaskincalendar.
                if ($service == 'calendar') {
                    if ($debuglevel >= 2) {
                        echo "special tasks delete...\n";
                    }
                    $service = 'tasks';
                    $suid = $GLOBALS['testbackend']->getSuid($service, $locuri);
                }
            }
            if (empty($suid)) {
                throw new Horde_Exception("Unable to find SUID for CUID {$locuri} for simulating {$service} delete");
            }
            $result = $GLOBALS['testbackend']->deleteEntry($service, $suid);
            // @TODO: simulate a delete by just faking some history data.
            if (is_a($result, 'PEAR_Error')) {
                echo "Error deleting data {$locuri}!";
                throw new Horde_Exception_Wrapped($result);
            }
            if ($debuglevel >= 2) {
                echo "simulated {$service} delete of {$suid}!\n";
            }
        }
    }
}