Merge branch 'master' of http://git.syncroton.org/Syncroton into SyncrotonMerge
[tine20] / tine20 / library / Syncroton / lib / Syncroton / Wbxml / Abstract.php
1 <?php
2 /**
3  * Syncroton
4  *
5  * @package     Wbxml
6  * @subpackage  Wbxml
7  * @license     http://www.tine20.org/licenses/lgpl.html LGPL Version 3
8  * @copyright   Copyright (c) 2008-2009 Metaways Infosystems GmbH (http://www.metaways.de)
9  * @author      Lars Kneschke <l.kneschke@metaways.de>
10  * @version     $Id:Abstract.php 4968 2008-10-17 09:09:33Z l.kneschke@metaways.de $
11  */
12
13 /**
14  * class documentation
15  *
16  * @package     Wbxml
17  * @subpackage  Wbxml
18  */
19  
20 abstract class Syncroton_Wbxml_Abstract
21 {
22     /**
23      * stream containing the wbxml encoded data
24      *
25      * @var resource
26      */
27     protected $_stream;
28     
29     /**
30      * the wbxml version
31      *
32      * @var string
33      */
34     protected $_version;
35     
36     /**
37      * the Document Public Identifier 
38      *
39      * @var string
40      */
41     protected $_dpi;
42     
43     /**
44      * the current active dtd
45      *
46      * @var Syncroton_Wbxml_Dtd_Syncml_Abstract
47      */
48     protected $_dtd;
49     
50     /**
51      * the charSet used in the wbxml file
52      *
53      * @var string
54      */
55     protected $_charSet;
56     
57     /**
58      * currently active code page
59      *
60      * @var array
61      */
62     protected $_codePage;
63     
64     /**
65      * see section 5.5
66      *
67      */
68     const DPI_WELLKNOWN = 'WELLKNOWN';
69     
70     /**
71      * see section 5.5
72      *
73      */
74     const DPI_STRINGTABLE = 'STRINGTABLE';
75     
76     const SWITCH_PAGE   = 0x00;
77     const END           = 0x01;
78     const ENTITY        = 0x02;
79     const STR_I         = 0x03;
80     const LITERAL       = 0x04;
81     const EXT_I_0       = 0x40;
82     const EXT_I_1       = 0x41;
83     const EXT_I_2       = 0x42;
84     const PI            = 0x43;
85     const LITERAL_C     = 0x44;
86     const EXT_T_0       = 0x80;
87     const EXT_T_1       = 0x81;
88     const EXT_T_2       = 0x82;
89     const STR_T         = 0x83;
90     const LITERAL_A     = 0x84;
91     const EXT_0         = 0xC0;
92     const EXT_1         = 0xC1;
93     const EXT_2         = 0xC2;
94     const OPAQUE        = 0xC3;
95     const LITERAL_AC    = 0xC4;
96     
97     /**
98      * the real name for this DPI is "unknown"
99      * But Microsoft is using them for their ActiveSync stuff
100      * instead defining their own DPI like the sycnml creators did
101      *
102      */
103     const DPI_1         = '-//AIRSYNC//DTD AirSync//EN';
104     
105     /**
106      * return wellknown identifiers
107      *
108      * @param integer $_uInt
109      * @todo add well known identifiers from section 7.2
110      * @return string
111      */
112     public function getDPI($_uInt = 0)
113     {
114         if(!defined('Syncroton_Wbxml_Abstract::DPI_' . $_uInt)) {
115             throw new Syncroton_Wbxml_Exception('unknown wellknown identifier: ' . $_uInt);
116         }
117         
118         $dpi = constant('Syncroton_Wbxml_Abstract::DPI_' . $_uInt);
119         
120         return $dpi;
121     }
122     
123     /**
124      * return multibyte integer
125      *
126      * @return integer
127      */
128     protected function _getMultibyteUInt()
129     {
130         $uInt = 0;
131         
132         do {
133             $byte = $this->_getByte();
134             $uInt <<= 7;
135             $uInt += ($byte & 127);
136         } while (($byte & 128) != 0);
137          
138         return $uInt;
139     }
140         
141     protected function _getByte()
142     {
143         $byte = fread($this->_stream, 1);
144         
145         if($byte === false) {
146             throw new Syncroton_Wbxml_Exception("failed reading one byte");
147         }
148         
149         return ord($byte);
150     }
151     
152     protected function _getOpaque($_length)
153     {
154         $string = fread($this->_stream, $_length);
155         
156         if($string === false) {
157             throw new Syncroton_Wbxml_Exception("failed reading opaque data");
158         }
159         
160         return $string;
161     }
162     
163     /**
164      * get a 0 terminated string
165      *
166      * @return string
167      */
168     protected function _getTerminatedString()
169     {
170         $string = '';
171         
172         while (($byte = $this->_getByte()) != 0) {
173             $string .= chr($byte);
174         }        
175         
176         return $string;
177     }
178     
179     protected function _writeByte($_byte)
180     {
181         fwrite($this->_stream, chr($_byte));
182     }
183     
184     protected function _writeMultibyteUInt($_integer)
185     {
186         $multibyte = NULL;
187         $remainder = $_integer;
188         
189         do {
190             $byte = ($remainder & 127);
191             $remainder >>= 7;
192             if($multibyte === NULL) {
193                 $multibyte = chr($byte);
194             } else {
195                 $multibyte = chr($byte | 128) . $multibyte;
196             }
197         } while ($remainder != 0);
198
199         fwrite($this->_stream, $multibyte);
200     }
201     
202     protected function _writeString($_string)
203     {
204         fwrite($this->_stream, $_string);
205     }
206     
207     /**
208      * write opaque string to stream
209      * 
210      * @param string|resource $_string
211      * @throws Syncroton_Wbxml_Exception
212      */
213     protected function _writeOpaqueString($_string)
214     {
215         if (is_resource($_string)) {
216             $stream = $_string;
217         } else {
218             $stream = fopen("php://temp", 'r+');
219             fwrite($stream, $_string);
220         }
221         $length = ftell($stream);
222         rewind($stream);
223         
224         $this->_writeByte(Syncroton_Wbxml_Abstract::OPAQUE);\r
225         $this->_writeMultibyteUInt($length);
226         $writenBytes = stream_copy_to_stream($stream, $this->_stream);\r
227         
228         if($writenBytes !== $length) {\r
229             throw new Syncroton_Wbxml_Exception('blow');\r
230         }
231         
232         fclose($stream);
233     }
234     
235     protected function _writeTerminatedString($_string)
236     {
237         $this->_writeByte(Syncroton_Wbxml_Abstract::STR_I);
238         fwrite($this->_stream, $_string);
239         fwrite($this->_stream, chr(0));
240     }
241 }