~ubuntu-branches/debian/sid/php-horde-turba/sid

« back to all changes in this revision

Viewing changes to turba-4.1.0/lib/Data/Ldif.php

  • Committer: Package Import Robot
  • Author(s): Mathieu Parent
  • Date: 2013-08-11 13:16:25 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20130811131625-z91stjvq51jr9onv
Tags: 4.1.1-1
New upstream version 4.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
/**
3
 
 * Horde_Data implementation for LDAP Data Interchange Format (LDIF).
4
 
 *
5
 
 * Copyright 2007-2013 Horde LLC (http://www.horde.org/)
6
 
 *
7
 
 * See the enclosed file LICENSE for license information (ASL).  If you
8
 
 * did not receive this file, see http://www.horde.org/licenses/apache.
9
 
 *
10
 
 * @author  Rita Selsky <ritaselsky@gmail.com>
11
 
 * @package Horde_Data
12
 
 */
13
 
class Turba_Data_Ldif extends Horde_Data_Base
14
 
{
15
 
    protected $_extension = 'ldif';
16
 
 
17
 
    protected $_contentType = 'text/ldif';
18
 
 
19
 
    /**
20
 
     * Useful Mozilla address book attribute names.
21
 
     *
22
 
     * @var array
23
 
     */
24
 
    protected $_mozillaAttr = array(
25
 
        'cn', 'givenName', 'sn', 'mail', 'mozillaNickname',
26
 
        'homeStreet', 'mozillaHomeStreet2', 'mozillaHomeLocalityName',
27
 
        'mozillaHomeState', 'mozillaHomePostalCode',
28
 
        'mozillaHomeCountryName', 'street',
29
 
        'mozillaWorkStreet2', 'l', 'st', 'postalCode',
30
 
        'c', 'homePhone', 'telephoneNumber', 'mobile',
31
 
        'fax', 'title', 'company', 'description', 'mozillaWorkUrl',
32
 
        'department', 'mozillaNickname'
33
 
    );
34
 
 
35
 
    /**
36
 
     * Useful Turba address book attribute names.
37
 
     *
38
 
     * @var array
39
 
     */
40
 
    protected $_turbaAttr = array(
41
 
        'name', 'firstname', 'lastname', 'email', 'alias',
42
 
        'homeAddress', 'homeStreet', 'homeCity',
43
 
        'homeProvince', 'homePostalCode', 'homeCountry',
44
 
        'workAddress', 'workStreet', 'workCity', 'workProvince',
45
 
        'workPostalCode', 'workCountry',
46
 
        'homePhone', 'workPhone', 'cellPhone',
47
 
        'fax', 'title', 'company', 'notes', 'website',
48
 
        'department', 'nickname'
49
 
    );
50
 
 
51
 
    /**
52
 
     * Turba address book attribute names and the corresponding Mozilla name.
53
 
     *
54
 
     * @var array
55
 
     */
56
 
    protected $_turbaMozillaMap = array(
57
 
        'name' => 'cn',
58
 
        'firstname' => 'givenName',
59
 
        'lastname' => 'sn',
60
 
        'email' => 'mail',
61
 
        'alias' => 'mozillaNickname',
62
 
        'homePhone' => 'homePhone',
63
 
        'workPhone' => 'telephoneNumber',
64
 
        'cellPhone' => 'mobile',
65
 
        'fax' => 'fax',
66
 
        'title' => 'title',
67
 
        'company' => 'company',
68
 
        'notes' => 'description',
69
 
        'homeAddress' => 'homeStreet',
70
 
        'homeStreet' => 'mozillaHomeStreet2',
71
 
        'homeCity' => 'mozillaHomeLocalityName',
72
 
        'homeProvince' => 'mozillaHomeState',
73
 
        'homePostalCode' => 'mozillaHomePostalCode',
74
 
        'homeCountry' => 'mozillaHomeCountryName',
75
 
        'workAddress' => 'street',
76
 
        'workStreet' => 'mozillaWorkStreet2',
77
 
        'workCity' => 'l',
78
 
        'workProvince' => 'st',
79
 
        'workPostalCode' => 'postalCode',
80
 
        'workCountry' => 'c',
81
 
        'website' => 'mozillaWorkUrl',
82
 
        'department' => 'department',
83
 
        'nickname' => 'mozillaNickname'
84
 
    );
85
 
 
86
 
    public function importData($contents, $header = false)
87
 
    {
88
 
        $data = array();
89
 
        $records = preg_split('/(\r?\n){2}/', $contents);
90
 
        foreach ($records as $record) {
91
 
            if (trim($record) == '') {
92
 
                /* Ignore empty records */
93
 
                continue;
94
 
            }
95
 
            /* one key:value pair per line */
96
 
            $lines = preg_split('/\r?\n/', $record);
97
 
            $hash = array();
98
 
            foreach ($lines as $line) {
99
 
                // [0] = key, [1] = delimiter, [2] = value
100
 
                $res = preg_split('/(:[:<]?) */', $line, 2, PREG_SPLIT_DELIM_CAPTURE);
101
 
                if ((count($res) == 3) &&
102
 
                    in_array($res[0], $this->_mozillaAttr)) {
103
 
                    $hash[$res[0]] = ($res[1] == '::')
104
 
                        ? base64_decode($res[2])
105
 
                        : $res[2];
106
 
                }
107
 
            }
108
 
            $data[] = $hash;
109
 
        }
110
 
 
111
 
        return $data;
112
 
    }
113
 
 
114
 
    /**
115
 
     * Builds a LDIF file from a given data structure and triggers its download.
116
 
     * It DOES NOT exit the current script but only outputs the correct headers
117
 
     * and data.
118
 
     *
119
 
     * @param string $filename  The name of the file to be downloaded.
120
 
     * @param array $data       A two-dimensional array containing the data
121
 
     *                          set.
122
 
     * @param boolean $header   If true, the rows of $data are associative
123
 
     *                          arrays with field names as their keys.
124
 
     */
125
 
    public function exportFile($filename, $data, $header = false)
126
 
    {
127
 
        $export = $this->exportData($data, $header);
128
 
        $GLOBALS['browser']->downloadHeaders($filename, 'text/ldif', false, strlen($export));
129
 
        echo $export;
130
 
    }
131
 
 
132
 
    /**
133
 
     * Builds a LDIF file from a given data structure and returns it as a
134
 
     * string.
135
 
     *
136
 
     * @param array $data      A two-dimensional array containing the data set.
137
 
     * @param boolean $header  If true, the rows of $data are associative
138
 
     *                         arrays with field names as their keys.
139
 
     *
140
 
     * @return string  The LDIF data.
141
 
     */
142
 
    public function exportData($data, $header = false)
143
 
    {
144
 
        if (!is_array($data) || !count($data)) {
145
 
            return '';
146
 
        }
147
 
        $export = '';
148
 
        $mozillaTurbaMap = array_flip($this->_turbaMozillaMap) ;
149
 
        foreach ($data as $row) {
150
 
            $recordData = '';
151
 
            foreach ($this->_mozillaAttr as $value) {
152
 
                if (isset($row[$mozillaTurbaMap[$value]])) {
153
 
                    // Base64 encode each value as necessary and store it.
154
 
                    // Store cn and mail separately for use in record dn
155
 
                    if (!$this->_is_safe_string($row[$mozillaTurbaMap[$value]])) {
156
 
                        $recordData .= $value . ':: ' . base64_encode($row[$mozillaTurbaMap[$value]]) . "\n";
157
 
                    } else {
158
 
                        $recordData .= $value . ': ' . $row[$mozillaTurbaMap[$value]] . "\n";
159
 
                    }
160
 
                }
161
 
            }
162
 
 
163
 
            $dn = 'cn=' . $row[$mozillaTurbaMap['cn']] . ',mail=' . $row[$mozillaTurbaMap['mail']];
164
 
            if (!$this->_is_safe_string($dn)) {
165
 
                $export .= 'dn:: ' . base64_encode($dn) . "\n";
166
 
            } else {
167
 
                $export .= 'dn: ' . $dn . "\n";
168
 
            }
169
 
 
170
 
            $export .= "objectclass: top\n"
171
 
                . "objectclass: person\n"
172
 
                . "objectclass: organizationalPerson\n"
173
 
                . "objectclass: inetOrgPerson\n"
174
 
                . "objectclass: mozillaAbPersonAlpha\n"
175
 
                . $recordData . "modifytimestamp: 0Z\n\n";
176
 
        }
177
 
 
178
 
        return $export;
179
 
    }
180
 
 
181
 
    /**
182
 
     * Takes all necessary actions for the given import step, parameters and
183
 
     * form values and returns the next necessary step.
184
 
     *
185
 
     * @param integer $action  The current step. One of the IMPORT_* constants.
186
 
     * @param array $param     An associative array containing needed
187
 
     *                         parameters for the current step.
188
 
     *
189
 
     * @return mixed  Either the next step as an integer constant or imported
190
 
     *                data set after the final step.
191
 
     * @throws Horde_Data_Exception
192
 
     */
193
 
    public function nextStep($action, $param = array())
194
 
    {
195
 
        switch ($action) {
196
 
        case Horde_Data::IMPORT_FILE:
197
 
            parent::nextStep($action, $param);
198
 
 
199
 
            $f_data = $this->importFile($_FILES['import_file']['tmp_name']);
200
 
 
201
 
            $data = array();
202
 
            foreach ($f_data as $record) {
203
 
                $turbaHash = array();
204
 
                foreach ($this->_turbaAttr as $value) {
205
 
                    switch ($value) {
206
 
                    case 'homeAddress':
207
 
                        // These are the keys we're interested in.
208
 
                        $keys = array('homeStreet', 'mozillaHomeStreet2',
209
 
                                      'mozillaHomeLocalityName', 'mozillaHomeState',
210
 
                                      'mozillaHomePostalCode', 'mozillaHomeCountryName');
211
 
 
212
 
                        // Grab all of them that exist in $record.
213
 
                        $values = array_intersect_key($record, array_flip($keys));
214
 
 
215
 
                        // Special handling for State if both State
216
 
                        // and Locality Name are set.
217
 
                        if (isset($values['mozillaHomeLocalityName'])
218
 
                            && isset($values['mozillaHomeState'])) {
219
 
                            $values['mozillaHomeLocalityName'] .= ', ' . $values['mozillaHomeState'];
220
 
                            unset($values['mozillaHomeState']);
221
 
                        }
222
 
 
223
 
                        if ($values) {
224
 
                            $turbaHash[$value] = implode("\n", $values);
225
 
                        }
226
 
                        break;
227
 
 
228
 
                    case 'workAddress':
229
 
                        // These are the keys we're interested in.
230
 
                        $keys = array('street', 'mozillaWorkStreet2', 'l',
231
 
                                      'st', 'postalCode', 'c');
232
 
 
233
 
                        // Grab all of them that exist in $record.
234
 
                        $values = array_intersect_key($record, array_flip($keys));
235
 
 
236
 
                        // Special handling for "st" if both "st" and
237
 
                        // "l" are set.
238
 
                        if (isset($values['l']) && isset($values['st'])) {
239
 
                            $values['l'] .= ', ' . $values['st'];
240
 
                            unset($values['st']);
241
 
                        }
242
 
 
243
 
                        if ($values) {
244
 
                            $turbaHash[$value] = implode("\n", $values);
245
 
                        }
246
 
                        break;
247
 
 
248
 
                    default:
249
 
                        if (isset($record[$this->_turbaMozillaMap[$value]])) {
250
 
                            $turbaHash[$value] = $record[$this->_turbaMozillaMap[$value]];
251
 
                        }
252
 
                        break;
253
 
                    }
254
 
                }
255
 
 
256
 
                $data[] = $turbaHash;
257
 
            }
258
 
 
259
 
            $this->storage->set('data', null);
260
 
            return $data;
261
 
 
262
 
        default:
263
 
            return parent::nextStep($action, $param);
264
 
        }
265
 
    }
266
 
 
267
 
    /**
268
 
     * Checks if a string is safe according to RFC 2849, or if it needs to be
269
 
     * base64 encoded.
270
 
     *
271
 
     * @param string $str  The string to check.
272
 
     *
273
 
     * @return boolean  True if the string is safe.
274
 
     */
275
 
    protected function _is_safe_string($str)
276
 
    {
277
 
        /*  SAFE-CHAR         = %x01-09 / %x0B-0C / %x0E-7F
278
 
         *                     ; any value <= 127 decimal except NUL, LF,
279
 
         *                     ; and CR
280
 
         *
281
 
         *  SAFE-INIT-CHAR    = %x01-09 / %x0B-0C / %x0E-1F /
282
 
         *                     %x21-39 / %x3B / %x3D-7F
283
 
         *                     ; any value <= 127 except NUL, LF, CR,
284
 
         *                     ; SPACE, colon (":", ASCII 58 decimal)
285
 
         *                     ; and less-than ("<" , ASCII 60 decimal) */
286
 
        if (!strlen($str)) {
287
 
            return true;
288
 
        }
289
 
        if ($str[0] == ' ' || $str[0] == ':' || $str[0] == '<') {
290
 
            return false;
291
 
        }
292
 
        for ($i = 0; $i < strlen($str); ++$i) {
293
 
            if (ord($str[$i]) > 127 || $str[$i] == NULL || $str[$i] == "\n" ||
294
 
                $str[$i] == "\r") {
295
 
                return false;
296
 
            }
297
 
        }
298
 
 
299
 
        return true;
300
 
    }
301
 
 
302
 
}