source: trunk/zpush/backend/combined/combined.php @ 7589

Revision 7589, 15.7 KB checked in by douglas, 11 years ago (diff)

Ticket #3209 - Integrar módulo de sincronização Z-push ao Expresso

Line 
1<?php
2/***********************************************
3* File      :   backend/combined/combined.php
4* Project   :   Z-Push
5* Descr     :   Combines several backends. Each type of message
6*               (Emails, Contacts, Calendar, Tasks) can be handled by
7*               a separate backend.
8*               As the CombinedBackend is a subclass of the default Backend
9*               class, it returns by that the supported AS version is 2.5.
10*               The method GetSupportedASVersion() could be implemented
11*               here, checking the version with all backends.
12*               But still, the lowest version in common must be
13*               returned, even if some backends support a higher version.
14*
15* Created   :   29.11.2010
16*
17* Copyright 2007 - 2012 Zarafa Deutschland GmbH
18*
19* This program is free software: you can redistribute it and/or modify
20* it under the terms of the GNU Affero General Public License, version 3,
21* as published by the Free Software Foundation with the following additional
22* term according to sec. 7:
23*
24* According to sec. 7 of the GNU Affero General Public License, version 3,
25* the terms of the AGPL are supplemented with the following terms:
26*
27* "Zarafa" is a registered trademark of Zarafa B.V.
28* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
29* The licensing of the Program under the AGPL does not imply a trademark license.
30* Therefore any rights, title and interest in our trademarks remain entirely with us.
31*
32* However, if you propagate an unmodified version of the Program you are
33* allowed to use the term "Z-Push" to indicate that you distribute the Program.
34* Furthermore you may use our trademarks where it is necessary to indicate
35* the intended purpose of a product or service provided you use it in accordance
36* with honest practices in industrial or commercial matters.
37* If you want to propagate modified versions of the Program under the name "Z-Push",
38* you may only do so if you have a written permission by Zarafa Deutschland GmbH
39* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
40*
41* This program is distributed in the hope that it will be useful,
42* but WITHOUT ANY WARRANTY; without even the implied warranty of
43* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44* GNU Affero General Public License for more details.
45*
46* You should have received a copy of the GNU Affero General Public License
47* along with this program.  If not, see <http://www.gnu.org/licenses/>.
48*
49* Consult LICENSE file for details
50************************************************/
51
52// default backend
53include_once('lib/default/backend.php');
54
55//include the CombinedBackend's own config file
56require_once("backend/combined/config.php");
57require_once("backend/combined/importer.php");
58require_once("backend/combined/exporter.php");
59
60class BackendCombined extends Backend {
61    public $config;
62    public $backends;
63    private $activeBackend;
64    private $activeBackendID;
65
66    /**
67     * Constructor of the combined backend
68     *
69     * @access public
70     */
71    public function BackendCombined() {
72        parent::Backend();
73        $this->config = BackendCombinedConfig::GetBackendCombinedConfig();
74
75        foreach ($this->config['backends'] as $i => $b){
76            // load and instatiate backend
77            ZPush::IncludeBackend($b['name']);
78            $this->backends[$i] = new $b['name']($b['config']);
79        }
80        ZLog::Write(LOGLEVEL_INFO, sprintf("Combined %d backends loaded.", count($this->backends)));
81    }
82
83    /**
84     * Authenticates the user on each backend
85     *
86     * @param string        $username
87     * @param string        $domain
88     * @param string        $password
89     *
90     * @access public
91     * @return boolean
92     */
93    public function Logon($username, $domain, $password) {
94        ZLog::Write(LOGLEVEL_DEBUG, sprintf("Combined->Logon('%s', '%s',***))", $username, $domain));
95        if(!is_array($this->backends)){
96            return false;
97        }
98        foreach ($this->backends as $i => $b){
99            $u = $username;
100            $d = $domain;
101            $p = $password;
102            if(isset($this->config['backends'][$i]['users'])){
103                if(!isset($this->config['backends'][$i]['users'][$username])){
104                    unset($this->backends[$i]);
105                    continue;
106                }
107                if(isset($this->config['backends'][$i]['users'][$username]['username']))
108                    $u = $this->config['backends'][$i]['users'][$username]['username'];
109                if(isset($this->config['backends'][$i]['users'][$username]['password']))
110                    $p = $this->config['backends'][$i]['users'][$username]['password'];
111                if(isset($this->config['backends'][$i]['users'][$username]['domain']))
112                    $d = $this->config['backends'][$i]['users'][$username]['domain'];
113            }
114            if($this->backends[$i]->Logon($u, $d, $p) == false){
115                ZLog::Write(LOGLEVEL_DEBUG, sprintf("Combined->Logon() failed on %s ", $this->config['backends'][$i]['name']));
116                return false;
117            }
118        }
119        ZLog::Write(LOGLEVEL_INFO, "Combined->Logon() success");
120        return true;
121    }
122
123    /**
124     * Setup the backend to work on a specific store or checks ACLs there.
125     * If only the $store is submitted, all Import/Export/Fetch/Etc operations should be
126     * performed on this store (switch operations store).
127     * If the ACL check is enabled, this operation should just indicate the ACL status on
128     * the submitted store, without changing the store for operations.
129     * For the ACL status, the currently logged on user MUST have access rights on
130     *  - the entire store - admin access if no folderid is sent, or
131     *  - on a specific folderid in the store (secretary/full access rights)
132     *
133     * The ACLcheck MUST fail if a folder of the authenticated user is checked!
134     *
135     * @param string        $store              target store, could contain a "domain\user" value
136     * @param boolean       $checkACLonly       if set to true, Setup() should just check ACLs
137     * @param string        $folderid           if set, only ACLs on this folderid are relevant
138     *
139     * @access public
140     * @return boolean
141     */
142    public function Setup($store, $checkACLonly = false, $folderid = false) {
143        ZLog::Write(LOGLEVEL_DEBUG, sprintf("Combined->Setup('%s', '%s', '%s')", $store, Utils::PrintAsString($checkACLonly), $folderid));
144        if(!is_array($this->backends)){
145            return false;
146        }
147        foreach ($this->backends as $i => $b){
148            $u = $store;
149            if(isset($this->config['backends'][$i]['users']) && isset($this->config['backends'][$i]['users'][$store]['username'])){
150                $u = $this->config['backends'][$i]['users'][$store]['username'];
151            }
152            if($this->backends[$i]->Setup($u, $checkACLonly, $folderid) == false){
153                ZLog::Write(LOGLEVEL_WARN, "Combined->Setup() failed");
154                return false;
155            }
156        }
157        ZLog::Write(LOGLEVEL_INFO, "Combined->Setup() success");
158        return true;
159    }
160
161    /**
162     * Logs off each backend
163     *
164     * @access public
165     * @return boolean
166     */
167    public function Logoff() {
168        ZLog::Write(LOGLEVEL_DEBUG, "Combined->Logoff()");
169        foreach ($this->backends as $i => $b){
170            $this->backends[$i]->Logoff();
171        }
172        ZLog::Write(LOGLEVEL_DEBUG, "Combined->Logoff() success");
173        return true;
174    }
175
176    /**
177     * Returns an array of SyncFolder types with the entire folder hierarchy
178     * from all backends combined
179     *
180     * provides AS 1.0 compatibility
181     *
182     * @access public
183     * @return array SYNC_FOLDER
184     */
185    public function GetHierarchy(){
186        ZLog::Write(LOGLEVEL_DEBUG, "Combined->GetHierarchy()");
187        $ha = array();
188        foreach ($this->backends as $i => $b){
189            if(!empty($this->config['backends'][$i]['subfolder'])){
190                $f = new SyncFolder();
191                $f->serverid = $i.$this->config['delimiter'].'0';
192                $f->parentid = '0';
193                $f->displayname = $this->config['backends'][$i]['subfolder'];
194                $f->type = SYNC_FOLDER_TYPE_OTHER;
195                $ha[] = $f;
196            }
197            $h = $this->backends[$i]->GetHierarchy();
198            if(is_array($h)){
199                foreach($h as $j => $f){
200                    $h[$j]->serverid = $i.$this->config['delimiter'].$h[$j]->serverid;
201                    if($h[$j]->parentid != '0' || !empty($this->config['backends'][$i]['subfolder'])){
202                        $h[$j]->parentid = $i.$this->config['delimiter'].$h[$j]->parentid;
203                    }
204                    if(isset($this->config['folderbackend'][$h[$j]->type]) && $this->config['folderbackend'][$h[$j]->type] != $i){
205                        $h[$j]->type = SYNC_FOLDER_TYPE_OTHER;
206                    }
207                }
208                $ha = array_merge($ha, $h);
209            }
210        }
211        ZLog::Write(LOGLEVEL_DEBUG, "Combined->GetHierarchy() success");
212        return $ha;
213    }
214
215    /**
216     * Returns the importer to process changes from the mobile
217     *
218     * @param string        $folderid (opt)
219     *
220     * @access public
221     * @return object(ImportChanges)
222     */
223    public function GetImporter($folderid = false) {
224        if($folderid !== false) {
225            ZLog::Write(LOGLEVEL_DEBUG, sprintf("Combined->GetImporter() Content: ImportChangesCombined:('%s')", $folderid));
226
227            // get the contents importer from the folder in a backend
228            // the importer is wrapped to check foldernames in the ImportMessageMove function
229            $backend = $this->GetBackend($folderid);
230            if($backend === false)
231                return false;
232            $importer = $backend->GetImporter($this->GetBackendFolder($folderid));
233            if($importer){
234                return new ImportChangesCombined($this, $folderid, $importer);
235            }
236            return false;
237        }
238        else {
239            ZLog::Write(LOGLEVEL_DEBUG, "Combined->GetImporter() -> Hierarchy: ImportChangesCombined()");
240            //return our own hierarchy importer which send each change to the right backend
241            return new ImportChangesCombined($this);
242        }
243    }
244
245    /**
246     * Returns the exporter to send changes to the mobile
247     * the exporter from right backend for contents exporter and our own exporter for hierarchy exporter
248     *
249     * @param string        $folderid (opt)
250     *
251     * @access public
252     * @return object(ExportChanges)
253     */
254    public function GetExporter($folderid = false){
255        ZLog::Write(LOGLEVEL_DEBUG, sprintf("Combined->GetExporter('%s')", $folderid));
256        if($folderid){
257            $backend = $this->GetBackend($folderid);
258            if($backend == false)
259                return false;
260            return $backend->GetExporter($this->GetBackendFolder($folderid));
261        }
262        return new ExportChangesCombined($this);
263    }
264
265    /**
266     * Sends an e-mail
267     * This messages needs to be saved into the 'sent items' folder
268     *
269     * @param SyncSendMail  $sm     SyncSendMail object
270     *
271     * @access public
272     * @return boolean
273     * @throws StatusException
274     */
275    public function SendMail($sm) {
276        ZLog::Write(LOGLEVEL_DEBUG, "Combined->SendMail()");
277        foreach ($this->backends as $i => $b){
278            if($this->backends[$i]->SendMail($sm) == true){
279                return true;
280            }
281        }
282        return false;
283    }
284
285    /**
286     * Returns all available data of a single message
287     *
288     * @param string            $folderid
289     * @param string            $id
290     * @param ContentParameters $contentparameters flag
291     *
292     * @access public
293     * @return object(SyncObject)
294     * @throws StatusException
295     */
296    public function Fetch($folderid, $id, $contentparameters) {
297        ZLog::Write(LOGLEVEL_DEBUG, sprintf("Combined->Fetch('%s', '%s', CPO)", $folderid, $id));
298        $backend = $this->GetBackend($folderid);
299        if($backend == false)
300            return false;
301        return $backend->Fetch($this->GetBackendFolder($folderid), $id, $contentparameters);
302    }
303
304    /**
305     * Returns the waste basket
306     * If the wastebasket is set to one backend, return the wastebasket of that backend
307     * else return the first waste basket we can find
308     *
309     * @access public
310     * @return string
311     */
312    function GetWasteBasket(){
313        ZLog::Write(LOGLEVEL_DEBUG, "Combined->GetWasteBasket()");
314
315        if (isset($this->activeBackend)) {
316            if (!$this->activeBackend->GetWasteBasket())
317                return false;
318            else
319                return $this->activeBackendID . $this->config['delimiter'] . $this->activeBackend->GetWasteBasket();
320        }
321
322        return false;
323    }
324
325    /**
326     * Returns the content of the named attachment as stream.
327     * There is no way to tell which backend the attachment is from, so we try them all
328     *
329     * @param string        $attname
330     *
331     * @access public
332     * @return SyncItemOperationsAttachment
333     * @throws StatusException
334     */
335    public function GetAttachmentData($attname) {
336        ZLog::Write(LOGLEVEL_DEBUG, sprintf("Combined->GetAttachmentData('%s')", $attname));
337        foreach ($this->backends as $i => $b) {
338            try {
339                $attachment = $this->backends[$i]->GetAttachmentData($attname);
340                if ($attachment instanceof SyncItemOperationsAttachment)
341                    return $attachment;
342            }
343            catch (StatusException $s) {
344                // backends might throw StatusExceptions if it's not their attachment
345            }
346        }
347        throw new StatusException("Combined->GetAttachmentData(): no backend found", SYNC_ITEMOPERATIONSSTATUS_INVALIDATT);
348    }
349
350    /**
351     * Processes a response to a meeting request.
352     *
353     * @param string        $requestid      id of the object containing the request
354     * @param string        $folderid       id of the parent folder of $requestid
355     * @param string        $response
356     *
357     * @access public
358     * @return string       id of the created/updated calendar obj
359     * @throws StatusException
360     */
361    public function MeetingResponse($requestid, $folderid, $error) {
362        $backend = $this->GetBackend($folderid);
363        if($backend === false)
364            return false;
365        return $backend->MeetingResponse($requestid, $this->GetBackendFolder($folderid), $error);
366    }
367
368    /**
369     * Finds the correct backend for a folder
370     *
371     * @param string        $folderid       combinedid of the folder
372     *
373     * @access public
374     * @return object
375     */
376    public function GetBackend($folderid){
377        $pos = strpos($folderid, $this->config['delimiter']);
378        if($pos === false)
379            return false;
380        $id = substr($folderid, 0, $pos);
381        if(!isset($this->backends[$id]))
382            return false;
383
384        $this->activeBackend = $this->backends[$id];
385        $this->activeBackendID = $id;
386        return $this->backends[$id];
387    }
388
389    /**
390     * Returns an understandable folderid for the backend
391     *
392     * @param string        $folderid       combinedid of the folder
393     *
394     * @access public
395     * @return string
396     */
397    public function GetBackendFolder($folderid){
398        $pos = strpos($folderid, $this->config['delimiter']);
399        if($pos === false)
400            return false;
401        return substr($folderid,$pos + strlen($this->config['delimiter']));
402    }
403
404    /**
405     * Returns backend id for a folder
406     *
407     * @param string        $folderid       combinedid of the folder
408     *
409     * @access public
410     * @return object
411     */
412    public function GetBackendId($folderid){
413        $pos = strpos($folderid, $this->config['delimiter']);
414        if($pos === false)
415            return false;
416        return substr($folderid,0,$pos);
417    }
418}
419?>
Note: See TracBrowser for help on using the repository browser.