Compare commits
653
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
072f5f5a15 | ||
|
|
41fe9195f2 | ||
|
|
23789b48bc | ||
|
|
142296f71e | ||
|
|
3bae2387d4 | ||
|
|
6cecca6c4f | ||
|
|
28b1938bd9 | ||
|
|
31ace947cb | ||
|
|
0cea36df2e | ||
|
|
afd7452323 | ||
|
|
e4a21bcef5 | ||
|
|
0c99323db3 | ||
|
|
da208d5b4a | ||
|
|
158af71152 | ||
|
|
163bce39b5 | ||
|
|
02c72fee6a | ||
|
|
8bef84bded | ||
|
|
8db3b22eb9 | ||
|
|
1aabcf04b5 | ||
|
|
1db85743a0 | ||
|
|
c6b227160c | ||
|
|
5f2920db9b | ||
|
|
761a7e2be1 | ||
|
|
9ed1d57ec2 | ||
|
|
2b6428efd0 | ||
|
|
be36e0ceea | ||
|
|
070d3dd825 | ||
|
|
96f2552b45 | ||
|
|
2948920e0b | ||
|
|
212d7149ed | ||
|
|
668c7e8b49 | ||
|
|
9851c32a1e | ||
|
|
e7f27427c8 | ||
|
|
f0a29d3ca2 | ||
|
|
ec0a5ac4bf | ||
|
|
4ca8b9d0aa | ||
|
|
d560d0e470 | ||
|
|
401320e08b | ||
|
|
8083b41092 | ||
|
|
9218c7f253 | ||
|
|
4d1fdb33f5 | ||
|
|
2356562778 | ||
|
|
c686e3294d | ||
|
|
1ff91f7b59 | ||
|
|
b34c6324cd | ||
|
|
75c8362df8 | ||
|
|
ae07de5f6f | ||
|
|
06d2364ea2 | ||
|
|
29e081ec56 | ||
|
|
113b02fd71 | ||
|
|
35b108e645 | ||
|
|
70266155d3 | ||
|
|
fcfd8be771 | ||
|
|
b91032db8e | ||
|
|
f4874600fe | ||
|
|
b14e99b32a | ||
|
|
ea4b21e991 | ||
|
|
0307b8339a | ||
|
|
b5f1d3a19a | ||
|
|
8225f76279 | ||
|
|
c94595ea7f | ||
|
|
3a5e44e7eb | ||
|
|
80a0940765 | ||
|
|
7118bbe0ab | ||
|
|
eee5beb698 | ||
|
|
3363b253ac | ||
|
|
4070b9222d | ||
|
|
5ea56a6f8a | ||
|
|
379258de59 | ||
|
|
93b3685aa4 | ||
|
|
c4dc4d4eda | ||
|
|
c6d104fac5 | ||
|
|
ef79c09642 | ||
|
|
aeb712083a | ||
|
|
2c678101fc | ||
|
|
b95362f963 | ||
|
|
3175a9169f | ||
|
|
9311f05cc0 | ||
|
|
78cbcfb560 | ||
|
|
b8610b3eca | ||
|
|
1a7fc2a0e9 | ||
|
|
f7a20d0a83 | ||
|
|
a1cf066828 | ||
|
|
359b6a99aa | ||
|
|
826537ed01 | ||
|
|
3950e9d4c3 | ||
|
|
9885211a5b | ||
|
|
ef1be5dc5f | ||
|
|
4e42d5d410 | ||
|
|
31969d162d | ||
|
|
2ff3b5ef5f | ||
|
|
7fe48a1555 | ||
|
|
fcddeb4224 | ||
|
|
f1cb87aa02 | ||
|
|
a6424680cc | ||
|
|
b3dc645282 | ||
|
|
2f0419c18a | ||
|
|
9e9407cf30 | ||
|
|
d709a1216b | ||
|
|
588352be7d | ||
|
|
a40d7ca342 | ||
|
|
e4ce687e29 | ||
|
|
bcb0764b19 | ||
|
|
ddd7be4333 | ||
|
|
d9f4a9935a | ||
|
|
ae75fee512 | ||
|
|
8cdacd065f | ||
|
|
af6a69c9fc | ||
|
|
dc41e29f05 | ||
|
|
afc7519beb | ||
|
|
f2d5a76911 | ||
|
|
342ad84a24 | ||
|
|
9580a8f8ee | ||
|
|
a96380a0dc | ||
|
|
2fed02da59 | ||
|
|
84dc08adb6 | ||
|
|
c160edf20a | ||
|
|
3b7a3c94d4 | ||
|
|
7b97e28cff | ||
|
|
81bf1b41e9 | ||
|
|
ea86f136b7 | ||
|
|
fc0c580fe1 | ||
|
|
42a7bcb9ac | ||
|
|
9669f2bbba | ||
|
|
2563408872 | ||
|
|
dbea244f49 | ||
|
|
0f9d8cdd2c | ||
|
|
5105dbb342 | ||
|
|
b26e767a10 | ||
|
|
940f85fde2 | ||
|
|
adee80529e | ||
|
|
295dfcfdd5 | ||
|
|
aa18abd842 | ||
|
|
feb398d59c | ||
|
|
19b404de45 | ||
|
|
d1a384e539 | ||
|
|
e7f38f940e | ||
|
|
f7ba5d2346 | ||
|
|
eeddf43a78 | ||
|
|
eabe829236 | ||
|
|
762b841249 | ||
|
|
3090448fcb | ||
|
|
a3e1d4813a | ||
|
|
046a645119 | ||
|
|
07d4b2bae2 | ||
|
|
343f2d8bfe | ||
|
|
65276f7dc0 | ||
|
|
24663682d6 | ||
|
|
57cd315f2a | ||
|
|
29fcfda118 | ||
|
|
ada90677e1 | ||
|
|
4c9c07e358 | ||
|
|
b71180b006 | ||
|
|
1ed41e2831 | ||
|
|
948553dce3 | ||
|
|
74adf78446 | ||
|
|
ee0ae8a1c0 | ||
|
|
38c649751c | ||
|
|
645c718dfa | ||
|
|
02992a7018 | ||
|
|
0ffa0649c5 | ||
|
|
7c7cabe432 | ||
|
|
bb9c4cf039 | ||
|
|
c252f5b7a8 | ||
|
|
2e44ac0f9b | ||
|
|
2a9ccf8122 | ||
|
|
f74066c9a6 | ||
|
|
ee49836f2e | ||
|
|
bf798061d3 | ||
|
|
834e05bab1 | ||
|
|
e8438a6235 | ||
|
|
68dafdfdeb | ||
|
|
e5bc46710c | ||
|
|
7355eae1dc | ||
|
|
1d9febb511 | ||
|
|
e21b30d768 | ||
|
|
ae200360ba | ||
|
|
e217ffb6c4 | ||
|
|
a4a3a735b4 | ||
|
|
13721b961b | ||
|
|
689a1e94e0 | ||
|
|
afcd92fb71 | ||
|
|
7260c07628 | ||
|
|
a24d809e40 | ||
|
|
ed97407578 | ||
|
|
ca541d7299 | ||
|
|
2d683ffc77 | ||
|
|
d603a8672e | ||
|
|
d51e1da57f | ||
|
|
80fd439dea | ||
|
|
a0d7f184fe | ||
|
|
fe2826ca76 | ||
|
|
ff9ea3b779 | ||
|
|
e70793e7ae | ||
|
|
0fdea48ce8 | ||
|
|
2b53705d44 | ||
|
|
b716331d8e | ||
|
|
586d66b113 | ||
|
|
5756defbf1 | ||
|
|
7130cec4d1 | ||
|
|
009cfccb2c | ||
|
|
09e14df79b | ||
|
|
ba29e7620d | ||
|
|
32516b162e | ||
|
|
a8e780516b | ||
|
|
bd7ad5be16 | ||
|
|
bed57af015 | ||
|
|
5f369f201d | ||
|
|
dc21c723f6 | ||
|
|
1f7994d1bf | ||
|
|
7369a82bab | ||
|
|
1a900b05d9 | ||
|
|
a8e3418a4c | ||
|
|
59ce12a51b | ||
|
|
a1bec0e995 | ||
|
|
08ab36244c | ||
|
|
9ea880e80b | ||
|
|
7d0a9aa1b7 | ||
|
|
2fa654fadb | ||
|
|
4a98e5b521 | ||
|
|
e5103faed4 | ||
|
|
f9ad9ea815 | ||
|
|
cfbd53e374 | ||
|
|
f2beabec88 | ||
|
|
eaa0fb3cf1 | ||
|
|
db56d1fa6c | ||
|
|
37de8c6141 | ||
|
|
b0eb34f6b7 | ||
|
|
1cf696f57c | ||
|
|
2114a48222 | ||
|
|
384d998c47 | ||
|
|
2211f6d168 | ||
|
|
32ba01315f | ||
|
|
682ed767d9 | ||
|
|
5536f8967e | ||
|
|
df3e9033f3 | ||
|
|
f167475c91 | ||
|
|
e4aedbac08 | ||
|
|
2cf66e037d | ||
|
|
6587f4f193 | ||
|
|
c8a4ea5548 | ||
|
|
148fd4936c | ||
|
|
a7fef39448 | ||
|
|
5a3d0d27e0 | ||
|
|
eb9111b5fa | ||
|
|
eb7d1f08bc | ||
|
|
854fed529c | ||
|
|
3c29e0724d | ||
|
|
cebaed9059 | ||
|
|
aae26602b0 | ||
|
|
05233d9c53 | ||
|
|
e862194b32 | ||
|
|
884fbfdb73 | ||
|
|
c05cf00db7 | ||
|
|
198db855f6 | ||
|
|
1c439c866e | ||
|
|
616ee7c6e4 | ||
|
|
37d3234b60 | ||
|
|
449d838dc2 | ||
|
|
6a9bcfda68 | ||
|
|
d0b09ebe35 | ||
|
|
0361b7dfdb | ||
|
|
38b350382a | ||
|
|
73141a645e | ||
|
|
f07526423f | ||
|
|
ba35a4b003 | ||
|
|
47c4ad5807 | ||
|
|
0f3e31ebf1 | ||
|
|
87261f3280 | ||
|
|
bd2759ecdf | ||
|
|
be1bcf3c9b | ||
|
|
053b090aff | ||
|
|
189f2218a8 | ||
|
|
656869a4a2 | ||
|
|
16f62e2393 | ||
|
|
9289615996 | ||
|
|
fdea04c08c | ||
|
|
edca3638ec | ||
|
|
05990e9a14 | ||
|
|
3cce9b2012 | ||
|
|
7dc65af300 | ||
|
|
84e999229b | ||
|
|
3dbfb0ed2d | ||
|
|
d1f3417c3a | ||
|
|
7c7031333e | ||
|
|
1e48481426 | ||
|
|
8ae1624604 | ||
|
|
7166f5a597 | ||
|
|
55052ea36f | ||
|
|
99d38417cc | ||
|
|
29eed182a7 | ||
|
|
744610dbe1 | ||
|
|
d2b739d261 | ||
|
|
2ba8254ecc | ||
|
|
28e600a4e6 | ||
|
|
ab6e4841ba | ||
|
|
91f1ab6a60 | ||
|
|
32a534919d | ||
|
|
5b77c2b724 | ||
|
|
70086e5ee6 | ||
|
|
7ddc1b9e2d | ||
|
|
6d93db96e4 | ||
|
|
27445d3b85 | ||
|
|
60d6abe542 | ||
|
|
baacf8516d | ||
|
|
46a48faf23 | ||
|
|
193720cfbb | ||
|
|
f40580d632 | ||
|
|
ca4d89fb08 | ||
|
|
906985c1f3 | ||
|
|
de8bf64c70 | ||
|
|
0c38a9e555 | ||
|
|
3c6c90d434 | ||
|
|
72a4b075d6 | ||
|
|
24c0fb1cc4 | ||
|
|
7241e3e30e | ||
|
|
1d705dc00b | ||
|
|
df42ab2a46 | ||
|
|
53f9d0d7f5 | ||
|
|
f59c77a950 | ||
|
|
cd4abe4b5b | ||
|
|
69b0f9fcbf | ||
|
|
dceead3997 | ||
|
|
573c2ec114 | ||
|
|
6a68c255bd | ||
|
|
e9d8b729b6 | ||
|
|
1e7dfc0934 | ||
|
|
d7e6648396 | ||
|
|
65603201f7 | ||
|
|
9fd6f75c4e | ||
|
|
b96f25f99f | ||
|
|
d7851999da | ||
|
|
e6ab0a590a | ||
|
|
be531100c6 | ||
|
|
e946a67ddf | ||
|
|
2fe87f14fd | ||
|
|
b2f012cae2 | ||
|
|
33659aa947 | ||
|
|
df1ab29872 | ||
|
|
61e59b864e | ||
|
|
0a590ba388 | ||
|
|
ab92516dd0 | ||
|
|
7b90b892fc | ||
|
|
b654ffb806 | ||
|
|
6de689bbe2 | ||
|
|
7eb8b9c2c3 | ||
|
|
3877f3001f | ||
|
|
4d2c734781 | ||
|
|
e57d875e0a | ||
|
|
b1df03adc7 | ||
|
|
c4bc215a47 | ||
|
|
bd776152db | ||
|
|
c6374b52ec | ||
|
|
734c164ae0 | ||
|
|
c9936d7ecf | ||
|
|
9f381e768d | ||
|
|
b531b6160c | ||
|
|
885e59a2af | ||
|
|
8a041860a0 | ||
|
|
d5f76ac832 | ||
|
|
12b7fea825 | ||
|
|
1c82af8842 | ||
|
|
6cef5245e1 | ||
|
|
0069a4200b | ||
|
|
e24c20c48a | ||
|
|
256b679798 | ||
|
|
b85ed0db1c | ||
|
|
048bae2fc5 | ||
|
|
19e542396b | ||
|
|
249a1fcf14 | ||
|
|
7dad5ad84e | ||
|
|
16105d37b8 | ||
|
|
e08ebd2390 | ||
|
|
03553980fd | ||
|
|
33fd60efb3 | ||
|
|
b8e2255a07 | ||
|
|
e687dbf155 | ||
|
|
bf398889bf | ||
|
|
f42d52743d | ||
|
|
70cd64a626 | ||
|
|
4359b05da8 | ||
|
|
e26e3d7307 | ||
|
|
25dbd4849d | ||
|
|
045b275b27 | ||
|
|
a2a89e8720 | ||
|
|
7ec1973e0f | ||
|
|
2581f6c568 | ||
|
|
20369631c9 | ||
|
|
1221da2443 | ||
|
|
f27b8b6a54 | ||
|
|
a79a9c4eff | ||
|
|
a6b393c2c1 | ||
|
|
faf228022a | ||
|
|
3e87ba92db | ||
|
|
0a87ff97b6 | ||
|
|
031cd210f7 | ||
|
|
9d9a434fdc | ||
|
|
41ed498d65 | ||
|
|
d28482557f | ||
|
|
4c97d54939 | ||
|
|
c08263d1c3 | ||
|
|
dc96466462 | ||
|
|
1734b387a3 | ||
|
|
871115e349 | ||
|
|
a764286879 | ||
|
|
5304461e4c | ||
|
|
6b25f08943 | ||
|
|
a0022e06f7 | ||
|
|
f24e65b6d8 | ||
|
|
0fb006c19f | ||
|
|
47a3f1a19d | ||
|
|
f25344182d | ||
|
|
f24e3a0a31 | ||
|
|
afb7bc309c | ||
|
|
cfee5aa3f4 | ||
|
|
2a51f6f385 | ||
|
|
4cffea43eb | ||
|
|
cafce5753d | ||
|
|
5d6a5f5d5e | ||
|
|
8e5a26dfb1 | ||
|
|
4cb0facd72 | ||
|
|
854bce28fb | ||
|
|
49e964c529 | ||
|
|
3281cea2a2 | ||
|
|
82253e91d2 | ||
|
|
1d1ed9a031 | ||
|
|
2bd8a2935f | ||
|
|
8a25e38827 | ||
|
|
4ec19d46fa | ||
|
|
d46a39e252 | ||
|
|
23e10d30be | ||
|
|
f049e2430a | ||
|
|
a53c66e8a4 | ||
|
|
4fb3492ea8 | ||
|
|
353f40ac3e | ||
|
|
96c831f726 | ||
|
|
59b3219f2d | ||
|
|
d7fdfc6cb2 | ||
|
|
d02f58b3cd | ||
|
|
62fee93d86 | ||
|
|
139c14d9e1 | ||
|
|
8ee15c6f77 | ||
|
|
5d17414018 | ||
|
|
3cd91846a6 | ||
|
|
e9eb8bdc86 | ||
|
|
3739cb1536 | ||
|
|
30f10ee8f0 | ||
|
|
dfb8788270 | ||
|
|
3810833e1b | ||
|
|
29e05c7c81 | ||
|
|
0a08285fac | ||
|
|
01f20a42ad | ||
|
|
3a61a2566b | ||
|
|
d2dda86529 | ||
|
|
cc125d2192 | ||
|
|
4da1e41d93 | ||
|
|
e24eb10c4f | ||
|
|
dd9e51fd16 | ||
|
|
9932d1413b | ||
|
|
ff13c49540 | ||
|
|
1e33b4bf26 | ||
|
|
e23a7df125 | ||
|
|
4ca476db9e | ||
|
|
33840c71cd | ||
|
|
1b983ef691 | ||
|
|
eec8c07d4f | ||
|
|
84ba93fc0a | ||
|
|
37a6f82659 | ||
|
|
b4aaa68d85 | ||
|
|
5487f34b9e | ||
|
|
e07734fa5f | ||
|
|
6a8e6cd762 | ||
|
|
663351029a | ||
|
|
c26e5fa7fe | ||
|
|
74c01dc448 | ||
|
|
a009c71034 | ||
|
|
b4ebc90dd0 | ||
|
|
95dc134ca6 | ||
|
|
9c4b7d8481 | ||
|
|
9fb9f2cae6 | ||
|
|
15f9b7d22e | ||
|
|
5f179ed6b0 | ||
|
|
93f9a7273e | ||
|
|
15e082896c | ||
|
|
63ff9751d7 | ||
|
|
d12c651d59 | ||
|
|
41a6c02aa3 | ||
|
|
a026e75c0e | ||
|
|
46815042c9 | ||
|
|
c79af52b67 | ||
|
|
e882dedac9 | ||
|
|
13277bbdb9 | ||
|
|
7e8a83aefb | ||
|
|
f1846191d5 | ||
|
|
a7c3f33447 | ||
|
|
a8d67edb44 | ||
|
|
89766b2e7e | ||
|
|
7d65d808f6 | ||
|
|
fa5e99d58d | ||
|
|
67c2d508ea | ||
|
|
19923d10db | ||
|
|
e57b6835e6 | ||
|
|
bcab7e7dc9 | ||
|
|
2572eedd89 | ||
|
|
efb45bfba6 | ||
|
|
4f38b5cf3f | ||
|
|
71b9772546 | ||
|
|
c13c389ae5 | ||
|
|
caf6f0ec6c | ||
|
|
4952ff7914 | ||
|
|
8981dcd645 | ||
|
|
470a53a548 | ||
|
|
7b65b7400e | ||
|
|
90c61abdb6 | ||
|
|
f8387b90ff | ||
|
|
feb02c54b9 | ||
|
|
49a2299414 | ||
|
|
43044bf88f | ||
|
|
0532d331a3 | ||
|
|
70fc05091f | ||
|
|
469e5c647e | ||
|
|
4bfb43a4ad | ||
|
|
5e0c7ae4f2 | ||
|
|
3daa7e55b7 | ||
|
|
6913502810 | ||
|
|
24971070f6 | ||
|
|
3d90e3a539 | ||
|
|
b5fdaa78cd | ||
|
|
f94adb5473 | ||
|
|
e34ba5689c | ||
|
|
7b5da8a2c9 | ||
|
|
451c82c815 | ||
|
|
488a76c5e3 | ||
|
|
a4bd966cc0 | ||
|
|
ecc36c9025 | ||
|
|
716daf027d | ||
|
|
0b7c32510b | ||
|
|
547dfa0d90 | ||
|
|
225a28258f | ||
|
|
e01b190e57 | ||
|
|
cd7d410262 | ||
|
|
4bcf90c693 | ||
|
|
0408415c61 | ||
|
|
c1c0c1ab44 | ||
|
|
3ea94940c2 | ||
|
|
321675ba99 | ||
|
|
9eb1418e36 | ||
|
|
d8804c699d | ||
|
|
4e9db74e29 | ||
|
|
7150ebde6b | ||
|
|
6fbd975e00 | ||
|
|
e0a1a47953 | ||
|
|
da757a19c6 | ||
|
|
ea13fd14c9 | ||
|
|
902a5d8f70 | ||
|
|
be0090be06 | ||
|
|
2d455bf0ca | ||
|
|
1d8e72646c | ||
|
|
c066136a06 | ||
|
|
a59fff785b | ||
|
|
40facab9a7 | ||
|
|
94eec4678e | ||
|
|
292ed9cfc8 | ||
|
|
663346e8ec | ||
|
|
8f33197c59 | ||
|
|
46b53b31fd | ||
|
|
6093c4dd2e | ||
|
|
61ded01171 | ||
|
|
9ed53cbab3 | ||
|
|
dfe49ea3b4 | ||
|
|
147d7f4cf0 | ||
|
|
794ca2ae8a | ||
|
|
036e535b33 | ||
|
|
a1b623b325 | ||
|
|
0965fd837a | ||
|
|
95b193391e | ||
|
|
9e38c5060a | ||
|
|
cfa7402dec | ||
|
|
1e4f737a7d | ||
|
|
8d9cfdb3b4 | ||
|
|
884dd7448c | ||
|
|
3cd7beb93d | ||
|
|
790a0536bc | ||
|
|
9dded7c86c | ||
|
|
d85ada6750 | ||
|
|
5b4dd4ecb1 | ||
|
|
721472d38e | ||
|
|
d737b2fd9a | ||
|
|
ac5c2b611a | ||
|
|
502f10cfd4 | ||
|
|
5bbb5df2a8 | ||
|
|
ddc9a1b3f5 | ||
|
|
d835921062 | ||
|
|
5c3dc34440 | ||
|
|
be459fa946 | ||
|
|
a78d7007d7 | ||
|
|
7e001a05a4 | ||
|
|
e6e4616a69 | ||
|
|
58dc0343bb | ||
|
|
814e2c0556 | ||
|
|
d357936c31 | ||
|
|
e279db6431 | ||
|
|
9897d003be | ||
|
|
113bae4638 | ||
|
|
e9b18d4521 | ||
|
|
f85cc4c186 | ||
|
|
775a8421d5 | ||
|
|
6c3ec9836c | ||
|
|
8ce4b89656 | ||
|
|
4f2183ec07 | ||
|
|
2370ecb089 | ||
|
|
0216658674 | ||
|
|
9ac8e9f0e1 | ||
|
|
8fc53ea1d7 | ||
|
|
55ccd0e83f | ||
|
|
219dfc61c9 | ||
|
|
d26df456e5 | ||
|
|
bc1edef448 | ||
|
|
2993c3a226 | ||
|
|
0e5a4901db | ||
|
|
ec0cc29f38 | ||
|
|
0211a26aba | ||
|
|
c34cca6a16 | ||
|
|
630c69d82d | ||
|
|
d761a864eb | ||
|
|
4b18fc108b | ||
|
|
9d4f4c3a9c | ||
|
|
0e0b7728fd | ||
|
|
c7fbcb0fc4 | ||
|
|
5667bb1b11 | ||
|
|
ea904f2e05 | ||
|
|
a75c797553 | ||
|
|
6f8d8394df | ||
|
|
b838734756 | ||
|
|
cd0244883d | ||
|
|
39632239f9 | ||
|
|
1382fe25fc | ||
|
|
126cd5fdfe | ||
|
|
ea26e0cc0a | ||
|
|
4971e8d05a | ||
|
|
7d24ece7d6 | ||
|
|
e253a7429c | ||
|
|
8db5e6d224 | ||
|
|
0124191329 | ||
|
|
d7d6a31837 | ||
|
|
bdc5ce7cd9 | ||
|
|
a0aef043a8 | ||
|
|
b4822f6c4e | ||
|
|
4804337a01 | ||
|
|
e2d2212524 | ||
|
|
6a70db80e6 | ||
|
|
01e42dce7c | ||
|
|
e533eb91a9 |
No files matched your search
@@ -9,3 +9,5 @@ tags
|
||||
*.swp
|
||||
SoObjects/SOGo/SOGo.framework/
|
||||
SoObjects/SOGo/derived_src/
|
||||
Tests/*/config.py
|
||||
*.pyc
|
||||
+21
-1
@@ -1,9 +1,10 @@
|
||||
[main]
|
||||
host = https://www.transifex.net
|
||||
host = https://www.transifex.com
|
||||
|
||||
[sogo.ui-mailerui]
|
||||
source_file = UI/MailerUI/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = UI/MailerUI/Arabic.lproj/Localizable.strings
|
||||
trans.ca = UI/MailerUI/Catalan.lproj/Localizable.strings
|
||||
trans.cs = UI/MailerUI/Czech.lproj/Localizable.strings
|
||||
trans.cy = UI/MailerUI/Welsh.lproj/Localizable.strings
|
||||
@@ -11,6 +12,7 @@ trans.da_DK = UI/MailerUI/Danish.lproj/Localizable.strings
|
||||
trans.de = UI/MailerUI/German.lproj/Localizable.strings
|
||||
trans.es_AR = UI/MailerUI/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = UI/MailerUI/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = UI/MailerUI/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/MailerUI/French.lproj/Localizable.strings
|
||||
trans.hu = UI/MailerUI/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/MailerUI/Icelandic.lproj/Localizable.strings
|
||||
@@ -28,6 +30,7 @@ trans.uk = UI/MailerUI/Ukrainian.lproj/Localizable.strings
|
||||
[sogo.ui-preferencesui]
|
||||
source_file = UI/PreferencesUI/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = UI/PreferencesUI/Arabic.lproj/Localizable.strings
|
||||
trans.ca = UI/PreferencesUI/Catalan.lproj/Localizable.strings
|
||||
trans.cs = UI/PreferencesUI/Czech.lproj/Localizable.strings
|
||||
trans.cy = UI/PreferencesUI/Welsh.lproj/Localizable.strings
|
||||
@@ -35,6 +38,7 @@ trans.da_DK = UI/PreferencesUI/Danish.lproj/Localizable.strings
|
||||
trans.de = UI/PreferencesUI/German.lproj/Localizable.strings
|
||||
trans.es_AR = UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = UI/PreferencesUI/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/PreferencesUI/French.lproj/Localizable.strings
|
||||
trans.hu = UI/PreferencesUI/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/PreferencesUI/Icelandic.lproj/Localizable.strings
|
||||
@@ -52,6 +56,7 @@ trans.uk = UI/PreferencesUI/Ukrainian.lproj/Localizable.strings
|
||||
[sogo.ui-scheduler]
|
||||
source_file = UI/Scheduler/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = UI/Scheduler/Arabic.lproj/Localizable.strings
|
||||
trans.ca = UI/Scheduler/Catalan.lproj/Localizable.strings
|
||||
trans.cs = UI/Scheduler/Czech.lproj/Localizable.strings
|
||||
trans.cy = UI/Scheduler/Welsh.lproj/Localizable.strings
|
||||
@@ -59,6 +64,7 @@ trans.da_DK = UI/Scheduler/Danish.lproj/Localizable.strings
|
||||
trans.de = UI/Scheduler/German.lproj/Localizable.strings
|
||||
trans.es_AR = UI/Scheduler/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = UI/Scheduler/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = UI/Scheduler/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/Scheduler/French.lproj/Localizable.strings
|
||||
trans.hu = UI/Scheduler/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/Scheduler/Icelandic.lproj/Localizable.strings
|
||||
@@ -76,6 +82,7 @@ trans.uk = UI/Scheduler/Ukrainian.lproj/Localizable.strings
|
||||
[sogo.ui-contacts]
|
||||
source_file = UI/Contacts/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = UI/Contacts/Arabic.lproj/Localizable.strings
|
||||
trans.ca = UI/Contacts/Catalan.lproj/Localizable.strings
|
||||
trans.cs = UI/Contacts/Czech.lproj/Localizable.strings
|
||||
trans.cy = UI/Contacts/Welsh.lproj/Localizable.strings
|
||||
@@ -83,6 +90,7 @@ trans.da_DK = UI/Contacts/Danish.lproj/Localizable.strings
|
||||
trans.de = UI/Contacts/German.lproj/Localizable.strings
|
||||
trans.es_AR = UI/Contacts/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = UI/Contacts/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = UI/Contacts/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/Contacts/French.lproj/Localizable.strings
|
||||
trans.hu = UI/Contacts/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/Contacts/Icelandic.lproj/Localizable.strings
|
||||
@@ -100,6 +108,7 @@ trans.uk = UI/Contacts/Ukrainian.lproj/Localizable.strings
|
||||
[sogo.ui-mainui]
|
||||
source_file = UI/MainUI/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = UI/MainUI/Arabic.lproj/Localizable.strings
|
||||
trans.ca = UI/MainUI/Catalan.lproj/Localizable.strings
|
||||
trans.cs = UI/MainUI/Czech.lproj/Localizable.strings
|
||||
trans.cy = UI/MainUI/Welsh.lproj/Localizable.strings
|
||||
@@ -107,6 +116,7 @@ trans.da_DK = UI/MainUI/Danish.lproj/Localizable.strings
|
||||
trans.de = UI/MainUI/German.lproj/Localizable.strings
|
||||
trans.es_AR = UI/MainUI/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = UI/MainUI/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = UI/MainUI/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/MainUI/French.lproj/Localizable.strings
|
||||
trans.hu = UI/MainUI/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/MainUI/Icelandic.lproj/Localizable.strings
|
||||
@@ -124,6 +134,7 @@ trans.uk = UI/MainUI/Ukrainian.lproj/Localizable.strings
|
||||
[sogo.ui-common]
|
||||
source_file = UI/Common/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = UI/Common/Arabic.lproj/Localizable.strings
|
||||
trans.ca = UI/Common/Catalan.lproj/Localizable.strings
|
||||
trans.cs = UI/Common/Czech.lproj/Localizable.strings
|
||||
trans.cy = UI/Common/Welsh.lproj/Localizable.strings
|
||||
@@ -131,6 +142,7 @@ trans.da_DK = UI/Common/Danish.lproj/Localizable.strings
|
||||
trans.de = UI/Common/German.lproj/Localizable.strings
|
||||
trans.es_AR = UI/Common/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = UI/Common/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = UI/Common/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/Common/French.lproj/Localizable.strings
|
||||
trans.hu = UI/Common/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/Common/Icelandic.lproj/Localizable.strings
|
||||
@@ -148,6 +160,7 @@ trans.uk = UI/Common/Ukrainian.lproj/Localizable.strings
|
||||
[sogo.ui-administrationui]
|
||||
source_file = UI/AdministrationUI/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = UI/AdministrationUI/Arabic.lproj/Localizable.strings
|
||||
trans.ca = UI/AdministrationUI/Catalan.lproj/Localizable.strings
|
||||
trans.cs = UI/AdministrationUI/Czech.lproj/Localizable.strings
|
||||
trans.cy = UI/AdministrationUI/Welsh.lproj/Localizable.strings
|
||||
@@ -155,6 +168,7 @@ trans.da_DK = UI/AdministrationUI/Danish.lproj/Localizable.strings
|
||||
trans.de = UI/AdministrationUI/German.lproj/Localizable.strings
|
||||
trans.es_AR = UI/AdministrationUI/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = UI/AdministrationUI/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = UI/AdministrationUI/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/AdministrationUI/French.lproj/Localizable.strings
|
||||
trans.hu = UI/AdministrationUI/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/AdministrationUI/Icelandic.lproj/Localizable.strings
|
||||
@@ -172,6 +186,7 @@ trans.uk = UI/AdministrationUI/Ukrainian.lproj/Localizable.strings
|
||||
[sogo.soobjects-appointments]
|
||||
source_file = SoObjects/Appointments/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = SoObjects/Appointments/Arabic.lproj/Localizable.strings
|
||||
trans.ca = SoObjects/Appointments/Catalan.lproj/Localizable.strings
|
||||
trans.cs = SoObjects/Appointments/Czech.lproj/Localizable.strings
|
||||
trans.cy = SoObjects/Appointments/Welsh.lproj/Localizable.strings
|
||||
@@ -179,6 +194,7 @@ trans.da_DK = SoObjects/Appointments/Danish.lproj/Localizable.strings
|
||||
trans.de = SoObjects/Appointments/German.lproj/Localizable.strings
|
||||
trans.es_AR = SoObjects/Appointments/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = SoObjects/Appointments/Finnish.lproj/Localizable.strings
|
||||
trans.fr = SoObjects/Appointments/French.lproj/Localizable.strings
|
||||
trans.hu = SoObjects/Appointments/Hungarian.lproj/Localizable.strings
|
||||
trans.is = SoObjects/Appointments/Icelandic.lproj/Localizable.strings
|
||||
@@ -196,6 +212,7 @@ trans.uk = SoObjects/Appointments/Ukrainian.lproj/Localizable.strings
|
||||
[sogo.soobjects-contacts]
|
||||
source_file = SoObjects/Contacts/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = SoObjects/Contacts/Arabic.lproj/Localizable.strings
|
||||
trans.ca = SoObjects/Contacts/Catalan.lproj/Localizable.strings
|
||||
trans.cs = SoObjects/Contacts/Czech.lproj/Localizable.strings
|
||||
trans.cy = SoObjects/Contacts/Welsh.lproj/Localizable.strings
|
||||
@@ -203,6 +220,7 @@ trans.da_DK = SoObjects/Contacts/Danish.lproj/Localizable.strings
|
||||
trans.de = SoObjects/Contacts/German.lproj/Localizable.strings
|
||||
trans.es_AR = SoObjects/Contacts/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = SoObjects/Contacts/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = SoObjects/Contacts/Finnish.lproj/Localizable.strings
|
||||
trans.fr = SoObjects/Contacts/French.lproj/Localizable.strings
|
||||
trans.hu = SoObjects/Contacts/Hungarian.lproj/Localizable.strings
|
||||
trans.is = SoObjects/Contacts/Icelandic.lproj/Localizable.strings
|
||||
@@ -220,6 +238,7 @@ trans.uk = SoObjects/Contacts/Ukrainian.lproj/Localizable.strings
|
||||
[sogo.ui-mailpartviewers]
|
||||
source_file = UI/MailPartViewers/English.lproj/Localizable.strings
|
||||
source_lang = en
|
||||
trans.ar = UI/MailPartViewers/Arabic.lproj/Localizable.strings
|
||||
trans.ca = UI/MailPartViewers/Catalan.lproj/Localizable.strings
|
||||
trans.cs = UI/MailPartViewers/Czech.lproj/Localizable.strings
|
||||
trans.cy = UI/MailPartViewers/Welsh.lproj/Localizable.strings
|
||||
@@ -227,6 +246,7 @@ trans.da_DK = UI/MailPartViewers/Danish.lproj/Localizable.strings
|
||||
trans.de = UI/MailPartViewers/German.lproj/Localizable.strings
|
||||
trans.es_AR = UI/MailPartViewers/SpanishArgentina.lproj/Localizable.strings
|
||||
trans.es_ES = UI/MailPartViewers/SpanishSpain.lproj/Localizable.strings
|
||||
trans.fi = UI/MailPartViewers/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/MailPartViewers/French.lproj/Localizable.strings
|
||||
trans.hu = UI/MailPartViewers/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/MailPartViewers/Icelandic.lproj/Localizable.strings
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
@interface ActiveSyncProduct : NSObject
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ActiveSyncProduct
|
||||
@end /* ActiveSyncProduct */
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
# GNUstep makefile
|
||||
|
||||
include common.make
|
||||
|
||||
BUNDLE_NAME = ActiveSync
|
||||
|
||||
ActiveSync_PRINCIPAL_CLASS = ActiveSyncProduct
|
||||
|
||||
ActiveSync_OBJC_FILES = \
|
||||
ActiveSyncProduct.m \
|
||||
iCalEvent+ActiveSync.m \
|
||||
iCalRecurrenceRule+ActiveSync.m \
|
||||
iCalTimeZone+ActiveSync.m \
|
||||
iCalToDo+ActiveSync.m \
|
||||
NSCalendarDate+ActiveSync.m \
|
||||
NSData+ActiveSync.m \
|
||||
NSDate+ActiveSync.m \
|
||||
NGDOMElement+ActiveSync.m \
|
||||
NGMimeMessage+ActiveSync.m \
|
||||
NGVCard+ActiveSync.m \
|
||||
NSString+ActiveSync.m \
|
||||
SOGoActiveSyncDispatcher.m \
|
||||
SOGoActiveSyncDispatcher+Sync.m \
|
||||
SOGoMailObject+ActiveSync.m \
|
||||
SoObjectWebDAVDispatcher+ActiveSync.m
|
||||
|
||||
ActiveSync_RESOURCE_FILES += \
|
||||
product.plist
|
||||
|
||||
ADDITIONAL_OBJCFLAGS += -Wno-deprecated-declarations
|
||||
ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/ -I../SoObjects/
|
||||
ADDITIONAL_LIB_DIRS += -L../../SOPE/GDLContentStore/obj/
|
||||
ADDITIONAL_INCLUDE_DIRS += -I/usr/include/libwbxml-1.0/
|
||||
ADDITIONAL_LDFLAGS += -Wl,--no-as-needed -lwbxml2
|
||||
|
||||
-include GNUmakefile.preamble
|
||||
include $(GNUSTEP_MAKEFILES)/bundle.make
|
||||
-include GNUmakefile.postamble
|
||||
@@ -0,0 +1 @@
|
||||
# compilation settings
|
||||
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __NGDOMELEMENTACTIVESYNC_H__
|
||||
#define __NGDOMELEMENTACTIVESYNC_H__
|
||||
|
||||
#import <DOM/DOMElement.h>
|
||||
#import <DOM/DOMProtocols.h>
|
||||
|
||||
@class NSDictionary;
|
||||
|
||||
@interface NGDOMElement (ActiveSync)
|
||||
|
||||
- (NSDictionary *) applicationData;
|
||||
|
||||
@end
|
||||
|
||||
#endif // NGDOMELEMENTACTIVESYNC
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#include "NGDOMElement+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
static NSArray *asElementArray = nil;
|
||||
|
||||
@implementation NGDOMElement (ActiveSync)
|
||||
|
||||
//
|
||||
// We must handle "inner data" like this:
|
||||
//
|
||||
// <ApplicationData>
|
||||
// <Flag xmlns="Email:">
|
||||
// <FlagStatus>2</FlagStatus>
|
||||
// <FlagType>Flag for follow up</FlagType>
|
||||
// </Flag>
|
||||
// </ApplicationData>
|
||||
//
|
||||
// and stuff like that:
|
||||
//
|
||||
// <Attendees xmlns="Calendar:">
|
||||
// <Attendee>
|
||||
// <Attendee_Email>sogo1@example.com</Attendee_Email>
|
||||
// <Attendee_Name>John Doe</Attendee_Name>
|
||||
// <Attendee_Status>5</Attendee_Status>
|
||||
// <Attendee_Type>1</Attendee_Type>
|
||||
// </Attendee>
|
||||
// <Attendee>
|
||||
// <Attendee_Email>sogo2@example.com</Attendee_Email>
|
||||
// <Attendee_Name>Balthazar César</Attendee_Name>
|
||||
// <Attendee_Status>5</Attendee_Status>
|
||||
// <Attendee_Type>1</Attendee_Type>
|
||||
// </Attendee>
|
||||
// <Attendee>
|
||||
// <Attendee_Email>sogo3@example.com</Attendee_Email>
|
||||
// <Attendee_Name>Wolfgang Fritz</Attendee_Name>
|
||||
// <Attendee_Status>5</Attendee_Status>
|
||||
// <Attendee_Type>1</Attendee_Type>
|
||||
// </Attendee>
|
||||
// </Attendees>
|
||||
//
|
||||
|
||||
- (NSDictionary *) applicationData
|
||||
{
|
||||
NSMutableDictionary *data;
|
||||
id <DOMNodeList> children;
|
||||
id <DOMElement> element;
|
||||
int i, count;
|
||||
|
||||
if (!asElementArray)
|
||||
asElementArray = [[NSArray alloc] initWithObjects: @"Attendee", nil];
|
||||
|
||||
data = [NSMutableDictionary dictionary];
|
||||
|
||||
children = [self childNodes];
|
||||
|
||||
for (i = 0; i < [children length]; i++)
|
||||
{
|
||||
element = [children objectAtIndex: i];
|
||||
|
||||
if ([element nodeType] == DOM_ELEMENT_NODE)
|
||||
{
|
||||
NSString *tag;
|
||||
id value;
|
||||
|
||||
tag = [element tagName];
|
||||
count = [(NSArray *)[element childNodes] count];
|
||||
|
||||
// Handle inner data - see above for samples
|
||||
if (count > 2)
|
||||
{
|
||||
NSMutableArray *innerElements;
|
||||
id <DOMElement> innerElement;
|
||||
NSArray *childNodes;
|
||||
NSString *innerTag;
|
||||
BOOL same;
|
||||
int j;
|
||||
|
||||
childNodes = (NSArray *)[element childNodes];
|
||||
innerElements = [NSMutableArray array];
|
||||
innerTag = nil;
|
||||
same = YES;
|
||||
|
||||
for (j = 1; j < count; j++)
|
||||
{
|
||||
innerElement = [childNodes objectAtIndex: j];
|
||||
|
||||
if ([innerElement nodeType] == DOM_ELEMENT_NODE)
|
||||
{
|
||||
if (!innerTag)
|
||||
innerTag = [innerElement tagName];
|
||||
|
||||
if ([innerTag isEqualToString: [innerElement tagName]])
|
||||
{
|
||||
[innerElements addObject: [(NGDOMElement *)innerElement applicationData]];
|
||||
}
|
||||
else
|
||||
{
|
||||
same = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (same && [asElementArray containsObject: innerTag])
|
||||
value = innerElements;
|
||||
else
|
||||
{
|
||||
value = [(NGDOMElement *)element applicationData];
|
||||
|
||||
// Don't set empty values like Foo = {}
|
||||
if (![value count])
|
||||
value = nil;
|
||||
}
|
||||
}
|
||||
else
|
||||
value = [[element firstChild] textValue];
|
||||
|
||||
if (value && tag)
|
||||
[data setObject: value forKey: tag];
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __NGMIMEMESSAGEACTIVESYNC_H__
|
||||
#define __NGMIMEMESSAGEACTIVESYNC_H__
|
||||
|
||||
#import <NGMail/NGMimeMessage.h>
|
||||
|
||||
@class NSArray;
|
||||
|
||||
@interface NGMimeMessage (ActiveSync)
|
||||
|
||||
- (NSArray *) allRecipients;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#import "NGMimeMessage+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSEnumerator.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
|
||||
@implementation NGMimeMessage (ActiveSync)
|
||||
|
||||
- (NSArray *) allRecipients
|
||||
{
|
||||
NSMutableArray *recipients;
|
||||
NSEnumerator *enumerator;
|
||||
NSString *s;
|
||||
|
||||
recipients = [NSMutableArray array];
|
||||
|
||||
enumerator = [[self headersForKey: @"to"] objectEnumerator];
|
||||
while ((s = [enumerator nextObject]))
|
||||
{
|
||||
[recipients addObject: [s pureEMailAddress]];
|
||||
}
|
||||
|
||||
enumerator = [[self headersForKey: @"cc"] objectEnumerator];
|
||||
while ((s = [enumerator nextObject]))
|
||||
{
|
||||
[recipients addObject: [s pureEMailAddress]];
|
||||
}
|
||||
|
||||
return recipients;
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __NGVCARDACTIVESYNC_H__
|
||||
#define __NGVCARDACTIVESYNC_H__
|
||||
|
||||
#import <NGCards/NGVCard.h>
|
||||
|
||||
@class NSDictionary;
|
||||
@class NSString;
|
||||
@class WOContext;
|
||||
|
||||
@interface NGVCard (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) context;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#import "NGVCard+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
|
||||
#import <NGCards/CardElement.h>
|
||||
|
||||
#import <Contacts/NGVCard+SOGo.h>
|
||||
|
||||
#include "NSDate+ActiveSync.h"
|
||||
#include "NSString+ActiveSync.h"
|
||||
|
||||
@implementation NGVCard (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
|
||||
{
|
||||
CardElement *n, *homeAdr, *workAdr;
|
||||
NSArray *emails, *addresses;
|
||||
NSMutableString *s;
|
||||
id o;
|
||||
|
||||
int i;
|
||||
|
||||
s = [NSMutableString string];
|
||||
n = [self n];
|
||||
|
||||
if ((o = [n flattenedValueAtIndex: 0 forKey: @""]))
|
||||
[s appendFormat: @"<LastName xmlns=\"Contacts:\">%@</LastName>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [n flattenedValueAtIndex: 1 forKey: @""]))
|
||||
[s appendFormat: @"<FirstName xmlns=\"Contacts:\">%@</FirstName>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [self workCompany]))
|
||||
[s appendFormat: @"<CompanyName xmlns=\"Contacts:\">%@</CompanyName>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [self title]))
|
||||
[s appendFormat: @"<JobTitle xmlns=\"Contacts:\">%@</JobTitle>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [self preferredEMail]))
|
||||
[s appendFormat: @"<Email1Address xmlns=\"Contacts:\">%@</Email1Address>", o];
|
||||
|
||||
|
||||
// Secondary email addresses (2 and 3)
|
||||
emails = [self secondaryEmails];
|
||||
|
||||
for (i = 0; i < [emails count]; i++)
|
||||
{
|
||||
o = [[emails objectAtIndex: i] flattenedValuesForKey: @""];
|
||||
|
||||
[s appendFormat: @"<Email%dAddress xmlns=\"Contacts:\">%@</Email%dAddress>", i+2, o, i+2];
|
||||
|
||||
if (i == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
// Telephone numbers
|
||||
if ((o = [self workPhone]) && [o length])
|
||||
[s appendFormat: @"<BusinessPhoneNumber xmlns=\"Contacts:\">%@</BusinessPhoneNumber>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [self homePhone]) && [o length])
|
||||
[s appendFormat: @"<HomePhoneNumber xmlns=\"Contacts:\">%@</HomePhoneNumber>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [self fax]) && [o length])
|
||||
[s appendFormat: @"<BusinessFaxNumber xmlns=\"Contacts:\">%@</BusinessFaxNumber>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [self mobile]) && [o length])
|
||||
[s appendFormat: @"<MobilePhoneNumber xmlns=\"Contacts:\">%@</MobilePhoneNumber>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [self pager]) && [o length])
|
||||
[s appendFormat: @"<PagerNumber xmlns=\"Contacts:\">%@</PagerNumber>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
// Home Address
|
||||
addresses = [self childrenWithTag: @"adr"
|
||||
andAttribute: @"type"
|
||||
havingValue: @"home"];
|
||||
|
||||
if ([addresses count])
|
||||
{
|
||||
homeAdr = [addresses objectAtIndex: 0];
|
||||
|
||||
if ((o = [homeAdr flattenedValueAtIndex: 2 forKey: @""]))
|
||||
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [homeAdr flattenedValueAtIndex: 3 forKey: @""]))
|
||||
[s appendFormat: @"<HomeCity xmlns=\"Contacts:\">%@</HomeCity>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [homeAdr flattenedValueAtIndex: 4 forKey: @""]))
|
||||
[s appendFormat: @"<HomeState xmlns=\"Contacts:\">%@</HomeState>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [homeAdr flattenedValueAtIndex: 5 forKey: @""]))
|
||||
[s appendFormat: @"<HomePostalCode xmlns=\"Contacts:\">%@</HomePostalCode>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [homeAdr flattenedValueAtIndex: 6 forKey: @""]))
|
||||
[s appendFormat: @"<HomeCountry xmlns=\"Contacts:\">%@</HomeCountry>", [o activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
|
||||
// Work Address
|
||||
addresses = [self childrenWithTag: @"adr"
|
||||
andAttribute: @"type"
|
||||
havingValue: @"work"];
|
||||
|
||||
if ([addresses count])
|
||||
{
|
||||
workAdr = [addresses objectAtIndex: 0];
|
||||
|
||||
if ((o = [workAdr flattenedValueAtIndex: 2 forKey: @""]))
|
||||
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [workAdr flattenedValueAtIndex: 3 forKey: @""]))
|
||||
[s appendFormat: @"<BusinessCity xmlns=\"Contacts:\">%@</BusinessCity>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [workAdr flattenedValueAtIndex: 4 forKey: @""]))
|
||||
[s appendFormat: @"<BusinessState xmlns=\"Contacts:\">%@</BusinessState>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [workAdr flattenedValueAtIndex: 5 forKey: @""]))
|
||||
[s appendFormat: @"<BusinessPostalCode xmlns=\"Contacts:\">%@</BusinessPostalCode>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [workAdr flattenedValueAtIndex: 6 forKey: @""]))
|
||||
[s appendFormat: @"<BusinessCountry xmlns=\"Contacts:\">%@</BusinessCountry>", [o activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
|
||||
// Other, less important fields
|
||||
if ((o = [self birthday]))
|
||||
[s appendFormat: @"<Birthday xmlns=\"Contacts:\">%@</Birthday>", [o activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
|
||||
if ((o = [self note]))
|
||||
{
|
||||
o = [o activeSyncRepresentationInContext: context];
|
||||
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
|
||||
[s appendFormat: @"<Type>%d</Type>", 1];
|
||||
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
|
||||
[s appendFormat: @"<Truncated>%d</Truncated>", 0];
|
||||
[s appendFormat: @"<Data>%@</Data>", o];
|
||||
[s appendString: @"</Body>"];
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) context
|
||||
{
|
||||
CardElement *element;
|
||||
id o;
|
||||
|
||||
// Contact's note
|
||||
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
|
||||
[self setNote: o];
|
||||
|
||||
// Birthday
|
||||
if ((o = [theValues objectForKey: @"Birthday"]))
|
||||
{
|
||||
o = [o calendarDate];
|
||||
[self setBday: [o descriptionWithCalendarFormat: @"%Y-%m-%d"]];
|
||||
}
|
||||
|
||||
//
|
||||
// Business address information
|
||||
//
|
||||
// BusinessStreet
|
||||
// BusinessCity
|
||||
// BusinessPostalCode
|
||||
// BusinessState
|
||||
// BusinessCountry
|
||||
//
|
||||
element = [self elementWithTag: @"adr" ofType: @"work"];
|
||||
[element setSingleValue: @""
|
||||
atIndex: 1 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"BusinessStreet"]
|
||||
atIndex: 2 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"BusinessCity"]
|
||||
atIndex: 3 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"BusinessState"]
|
||||
atIndex: 4 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"BusinessPostalCode"]
|
||||
atIndex: 5 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"BusinessCountry"]
|
||||
atIndex: 6 forKey: @""];
|
||||
|
||||
//
|
||||
// Home address information
|
||||
//
|
||||
// HomeStreet
|
||||
// HomeCity
|
||||
// HomePostalCode
|
||||
// HomeState
|
||||
// HomeCountry
|
||||
//
|
||||
element = [self elementWithTag: @"adr" ofType: @"home"];
|
||||
[element setSingleValue: @""
|
||||
atIndex: 1 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"HomeStreet"]
|
||||
atIndex: 2 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"HomeCity"]
|
||||
atIndex: 3 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"HomeState"]
|
||||
atIndex: 4 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"HomePostalCode"]
|
||||
atIndex: 5 forKey: @""];
|
||||
[element setSingleValue: [theValues objectForKey: @"HomeCountry"]
|
||||
atIndex: 6 forKey: @""];
|
||||
|
||||
// Company's name
|
||||
if ((o = [theValues objectForKey: @"CompanyName"]))
|
||||
{
|
||||
[self setOrg: o units: nil];
|
||||
}
|
||||
|
||||
// Email addresses
|
||||
if ((o = [theValues objectForKey: @"Email1Address"]))
|
||||
{
|
||||
[self addEmail: o types: [NSArray arrayWithObject: @"pref"]];
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"Email2Address"]))
|
||||
{
|
||||
[self addEmail: o types: nil];
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"Email3Address"]))
|
||||
{
|
||||
[self addEmail: o types: nil];
|
||||
}
|
||||
|
||||
// Formatted name
|
||||
// MiddleName
|
||||
// Suffix (II)
|
||||
// Title (Mr.)
|
||||
[self setFn: [theValues objectForKey: @"FileAs"]];
|
||||
|
||||
[self setNWithFamily: [theValues objectForKey: @"LastName"]
|
||||
given: [theValues objectForKey: @"FirstName"]
|
||||
additional: nil prefixes: nil suffixes: nil];
|
||||
|
||||
// IM information
|
||||
[[self uniqueChildWithTag: @"x-aim"]
|
||||
setSingleValue: [theValues objectForKey: @"IMAddress"]
|
||||
forKey: @""];
|
||||
|
||||
//
|
||||
// Phone numbrrs
|
||||
//
|
||||
element = [self elementWithTag: @"tel" ofType: @"work"];
|
||||
[element setSingleValue: [theValues objectForKey: @"BusinessPhoneNumber"] forKey: @""];
|
||||
|
||||
element = [self elementWithTag: @"tel" ofType: @"home"];
|
||||
[element setSingleValue: [theValues objectForKey: @"HomePhoneNumber"] forKey: @""];
|
||||
|
||||
element = [self elementWithTag: @"tel" ofType: @"cell"];
|
||||
[element setSingleValue: [theValues objectForKey: @"MobilePhoneNumber"] forKey: @""];
|
||||
|
||||
element = [self elementWithTag: @"tel" ofType: @"fax"];
|
||||
[element setSingleValue: [theValues objectForKey: @"BusinessFaxNumber"] forKey: @""];
|
||||
|
||||
element = [self elementWithTag: @"tel" ofType: @"pager"];
|
||||
[element setSingleValue: [theValues objectForKey: @"PagerNumber"] forKey: @""];
|
||||
|
||||
// Job's title
|
||||
if ((o = [theValues objectForKey: @"JobTitle"]))
|
||||
{
|
||||
[self setTitle: o];
|
||||
}
|
||||
|
||||
// WebPage (work)
|
||||
if ((o = [theValues objectForKey: @"WebPage"]))
|
||||
{
|
||||
[[self elementWithTag: @"url" ofType: @"work"]
|
||||
setSingleValue: o forKey: @""];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __NSCALENDARDATEACTIVESYNC_H__
|
||||
#define __NSCALENDARDATEACTIVESYNC_H__
|
||||
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
|
||||
@class NSString;
|
||||
|
||||
@interface NSCalendarDate (ActiveSync)
|
||||
|
||||
+ (NSCalendarDate *) dateFromFilterType: (NSString *) theFilterType;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#import "NSCalendarDate+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
|
||||
#define ONE_DAY 86400
|
||||
|
||||
@implementation NSCalendarDate (ActiveSync)
|
||||
|
||||
//
|
||||
// See http://msdn.microsoft.com/en-us/library/gg709713(v=exchg.80).aspx for available types
|
||||
//
|
||||
+ (NSCalendarDate *) dateFromFilterType: (NSString *) theFilterType
|
||||
{
|
||||
NSCalendarDate *d;
|
||||
|
||||
d = [NSCalendarDate calendarDate];
|
||||
|
||||
if (d)
|
||||
{
|
||||
int value;
|
||||
|
||||
switch ([theFilterType intValue])
|
||||
{
|
||||
case 1:
|
||||
value = ONE_DAY;
|
||||
break;
|
||||
case 2:
|
||||
value = 3 * ONE_DAY;
|
||||
break;
|
||||
case 3:
|
||||
value = 7 * ONE_DAY;
|
||||
break;
|
||||
case 4:
|
||||
value = 14 * ONE_DAY;
|
||||
break;
|
||||
case 5:
|
||||
value = 30 * ONE_DAY;
|
||||
break;
|
||||
case 6:
|
||||
value = 90 * ONE_DAY;
|
||||
break;
|
||||
case 7:
|
||||
value = 180 * ONE_DAY;
|
||||
break;
|
||||
case 0:
|
||||
case 8:
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [d initWithTimeIntervalSinceNow: -value];
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __NSDATAACTIVESYNC_H__
|
||||
#define __NSDATAACTIVESYNC_H__
|
||||
|
||||
#import <Foundation/NSData.h>
|
||||
|
||||
@class NSString;
|
||||
@class WOContext;
|
||||
|
||||
@interface NSData (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
|
||||
- (NSData *) wbxml2xml;
|
||||
- (NSData *) xml2wbxml;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#import "NSData+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSProcessInfo.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGExtensions/NGBase64Coding.h>
|
||||
|
||||
#include <wbxml/wbxml.h>
|
||||
#include <wbxml/wbxml_conv.h>
|
||||
#include <wbxml/wbxml_errors.h>
|
||||
|
||||
#define WBXMLDEBUG 0
|
||||
|
||||
@implementation NSData (ActiveSync)
|
||||
|
||||
- (void) _dumpToFile
|
||||
{
|
||||
NSString *path;
|
||||
|
||||
path = [NSString stringWithFormat: @"/tmp/%@.data", [[NSProcessInfo processInfo] globallyUniqueString]];
|
||||
[self writeToFile: path atomically: YES];
|
||||
NSLog(@"Original data written to: %@", path);
|
||||
}
|
||||
|
||||
//
|
||||
// Encodes the data in base64 and strip newline characters
|
||||
//
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
|
||||
{
|
||||
return [[self stringByEncodingBase64] stringByReplacingString: @"\n" withString: @""];
|
||||
}
|
||||
|
||||
- (NSData *) wbxml2xml
|
||||
{
|
||||
WBXMLGenXMLParams params;
|
||||
NSData *data;
|
||||
|
||||
unsigned int wbxml_len, xml_len, ret;
|
||||
unsigned char *wbxml, *xml;
|
||||
|
||||
wbxml = (unsigned char*)[self bytes];
|
||||
wbxml_len = [self length];
|
||||
xml = NULL;
|
||||
xml_len = 0;
|
||||
|
||||
params.lang = WBXML_LANG_ACTIVESYNC;
|
||||
params.gen_type = WBXML_GEN_XML_INDENT;
|
||||
params.indent = 1;
|
||||
params.keep_ignorable_ws = FALSE;
|
||||
|
||||
ret = wbxml_conv_wbxml2xml_withlen(wbxml, wbxml_len, &xml, &xml_len, ¶ms);
|
||||
|
||||
if (ret != WBXML_OK)
|
||||
{
|
||||
NSLog(@"wbxml2xmlFromContent: failed: %s\n", wbxml_errors_string(ret));
|
||||
[self _dumpToFile];
|
||||
return nil;
|
||||
}
|
||||
|
||||
data = [[NSData alloc] initWithBytes: xml length: xml_len];
|
||||
|
||||
#if WBXMLDEBUG
|
||||
[data writeToFile: @"/tmp/protocol.decoded" atomically: YES];
|
||||
#endif
|
||||
|
||||
free(xml);
|
||||
|
||||
return AUTORELEASE(data);
|
||||
}
|
||||
|
||||
|
||||
- (NSData *) xml2wbxml
|
||||
{
|
||||
WBXMLConvXML2WBXML *conv;
|
||||
NSData *data;
|
||||
|
||||
unsigned int wbxml_len, xml_len, ret;
|
||||
unsigned char *wbxml, *xml;
|
||||
|
||||
xml = (unsigned char*)[self bytes];
|
||||
xml_len = [self length];
|
||||
wbxml = NULL;
|
||||
wbxml_len = 0;
|
||||
conv = NULL;
|
||||
|
||||
ret = wbxml_conv_xml2wbxml_create(&conv);
|
||||
|
||||
if (ret != WBXML_OK)
|
||||
{
|
||||
NSLog(@"xml2wbxmlFromContent: failed: %s\n", wbxml_errors_string(ret));
|
||||
[self _dumpToFile];
|
||||
return nil;
|
||||
}
|
||||
|
||||
wbxml_conv_xml2wbxml_enable_preserve_whitespaces(conv);
|
||||
|
||||
// From libwbxml's changelog in v0.11.0: "The public ID is set to unknown and the DTD is not included. This is required for Microsoft ActiveSync."
|
||||
wbxml_conv_xml2wbxml_disable_public_id(conv);
|
||||
wbxml_conv_xml2wbxml_disable_string_table(conv);
|
||||
|
||||
ret = wbxml_conv_xml2wbxml_run(conv, xml, xml_len, &wbxml, &wbxml_len);
|
||||
|
||||
if (ret != WBXML_OK)
|
||||
{
|
||||
NSLog(@"xml2wbxmlFromContent: failed: %s\n", wbxml_errors_string(ret));
|
||||
[self _dumpToFile];
|
||||
free(wbxml);
|
||||
wbxml_conv_xml2wbxml_destroy(conv);
|
||||
return nil;
|
||||
}
|
||||
|
||||
data = [[NSData alloc] initWithBytes: wbxml length: wbxml_len];
|
||||
|
||||
#if WBXMLDEBUG
|
||||
[data writeToFile: @"/tmp/protocol.encoded" atomically: YES];
|
||||
#endif
|
||||
|
||||
free(wbxml);
|
||||
wbxml_conv_xml2wbxml_destroy(conv);
|
||||
|
||||
return AUTORELEASE(data);
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __NSDATEACTIVESYNC_H__
|
||||
#define __NSDATEACTIVESYNC_H__
|
||||
|
||||
#import <Foundation/NSDate.h>
|
||||
|
||||
@class NSString;
|
||||
@class WOContext;
|
||||
|
||||
@interface NSDate (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
|
||||
- (NSString *) activeSyncRepresentationWithoutSeparatorsInContext: (WOContext *) context;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#import "NSDate+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
|
||||
@implementation NSDate (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
|
||||
{
|
||||
return [self descriptionWithCalendarFormat: @"%Y-%m-%dT%H:%M:%S.%FZ" timeZone: [NSTimeZone timeZoneWithName: @"GMT"] locale: nil];
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// From [MS-ASDTYPE].pdf - section 2.3 "Dates and times in calendar items MUST NOT include punctuation separators."
|
||||
//
|
||||
- (NSString *) activeSyncRepresentationWithoutSeparatorsInContext: (WOContext *) context
|
||||
{
|
||||
return [self descriptionWithCalendarFormat: @"%Y%m%dT%H%M%SZ" timeZone: [NSTimeZone timeZoneWithName: @"GMT"] locale: nil];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __NSSTRINGACTIVESYNC_H__
|
||||
#define __NSSTRINGACTIVESYNC_H__
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#include "SOGoActiveSyncConstants.h"
|
||||
|
||||
@class NSCalendarDate;
|
||||
@class NSData;
|
||||
@class WOContext;
|
||||
|
||||
@interface NSString (ActiveSync)
|
||||
|
||||
- (NSString *) sanitizedServerIdWithType: (SOGoMicrosoftActiveSyncFolderType) folderType;
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
|
||||
- (int) activeSyncFolderType;
|
||||
- (NSString *) realCollectionIdWithFolderType: (SOGoMicrosoftActiveSyncFolderType *) folderType;
|
||||
- (NSCalendarDate *) calendarDate;
|
||||
- (NSString *) deviceId;
|
||||
- (NSString *) command;
|
||||
- (NSData *) convertHexStringToBytes;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#include "NSString+ActiveSync.h"
|
||||
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSCalendarDate.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSDate.h>
|
||||
|
||||
#include <SOGo/NSString+Utilities.h>
|
||||
|
||||
#include <NGExtensions/NSString+misc.h>
|
||||
|
||||
@implementation NSString (ActiveSync)
|
||||
|
||||
- (NSString *) sanitizedServerIdWithType: (SOGoMicrosoftActiveSyncFolderType) folderType
|
||||
{
|
||||
if (folderType == ActiveSyncEventFolder)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = [self length];
|
||||
|
||||
if (len > 4 && [self hasSuffix: @".ics"])
|
||||
return [self substringToIndex: len-4];
|
||||
else
|
||||
return [NSString stringWithFormat: @"%@.ics", self];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
s = [self stringByEscapingHTMLString];
|
||||
|
||||
return [[s componentsSeparatedByCharactersInSet: [self safeCharacterSet]]
|
||||
componentsJoinedByString: @""];
|
||||
}
|
||||
|
||||
- (int) activeSyncFolderType
|
||||
{
|
||||
if ([self isEqualToString: @"inbox"])
|
||||
return 2;
|
||||
else if ([self isEqualToString: @"draft"])
|
||||
return 3;
|
||||
else if ([self isEqualToString: @"sent"])
|
||||
return 5;
|
||||
else if ([self isEqualToString: @"trash"])
|
||||
return 4;
|
||||
|
||||
return 12;
|
||||
}
|
||||
|
||||
- (NSString *) realCollectionIdWithFolderType: (SOGoMicrosoftActiveSyncFolderType *) folderType;
|
||||
{
|
||||
NSString *realCollectionId, *v;
|
||||
|
||||
*folderType = ActiveSyncGenericFolder;
|
||||
v = [self stringByUnescapingURL];
|
||||
|
||||
if ([v hasPrefix: @"vevent/"])
|
||||
{
|
||||
realCollectionId = [v substringFromIndex: 7];
|
||||
*folderType = ActiveSyncEventFolder;
|
||||
}
|
||||
else if ([v hasPrefix: @"vtodo/"])
|
||||
{
|
||||
realCollectionId = [v substringFromIndex: 6];
|
||||
*folderType = ActiveSyncTaskFolder;
|
||||
}
|
||||
else if ([v hasPrefix: @"vcard/"])
|
||||
{
|
||||
realCollectionId = [v substringFromIndex: 6];
|
||||
*folderType = ActiveSyncContactFolder;
|
||||
}
|
||||
else if ([v hasPrefix: @"mail/"])
|
||||
{
|
||||
realCollectionId = [[v stringByUnescapingURL] substringFromIndex: 5];
|
||||
*folderType = ActiveSyncMailFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
realCollectionId = nil;
|
||||
}
|
||||
|
||||
return realCollectionId;
|
||||
}
|
||||
|
||||
//
|
||||
// 2014-01-16T05:00:00.000Z
|
||||
//
|
||||
// See http://www.gnustep.org/resources/documentation/Developer/Base/Reference/NSCalendarDate.html#method$NSCalendarDate-initWithString$calendarFormat$ for the format details.
|
||||
//
|
||||
- (NSCalendarDate *) calendarDate
|
||||
{
|
||||
id o;
|
||||
|
||||
o = [NSCalendarDate dateWithString: self calendarFormat: @"%Y%m%dT%H%M%SZ"];
|
||||
|
||||
if (!o)
|
||||
o = [NSCalendarDate dateWithString: self calendarFormat: @"%Y-%m-%dT%H:%M:%S.%FZ"];
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
- (NSString *) _valueForParameter: (NSString *) theParameter
|
||||
{
|
||||
NSArray *components;
|
||||
NSString *s;
|
||||
int i;
|
||||
|
||||
components = [[[self componentsSeparatedByString: @"/"] lastObject] componentsSeparatedByString: @"&"];
|
||||
|
||||
for (i = 0; i < [components count]; i++)
|
||||
{
|
||||
s = [components objectAtIndex: i];
|
||||
|
||||
if ([[s uppercaseString] hasPrefix: theParameter])
|
||||
return [s substringFromIndex: [theParameter length]];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
//
|
||||
// This method extracts the "DeviceId" from a URI:
|
||||
//
|
||||
// /SOGo/Microsoft-Server-ActiveSync?Cmd=FolderSync&User=sogo10&DeviceId=SEC17CD1A3E9E3F2&DeviceType=SAMSUNGSGHI317M
|
||||
//
|
||||
- (NSString *) deviceId
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
s = [self _valueForParameter: @"DEVICEID="];
|
||||
|
||||
if (!s)
|
||||
s = @"Unknown";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (NSString *) command
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
s = [self _valueForParameter: @"CMD="];
|
||||
|
||||
if (!s)
|
||||
s = @"Unknown";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
// FIXME: combine with our OpenChange code.
|
||||
//
|
||||
- (char) _decodeHexByte: (char) byteChar
|
||||
{
|
||||
char newByte;
|
||||
|
||||
if (byteChar >= 48 && byteChar <= 57)
|
||||
newByte = (uint8_t) byteChar - 48;
|
||||
else if (byteChar >= 65 && byteChar <= 70)
|
||||
newByte = (uint8_t) byteChar - 55;
|
||||
else if (byteChar >= 97 && byteChar <= 102)
|
||||
newByte = (uint8_t) byteChar - 87;
|
||||
else
|
||||
newByte = -1;
|
||||
|
||||
return newByte;
|
||||
}
|
||||
|
||||
//
|
||||
// FIXME: combine with our OpenChange code.
|
||||
//
|
||||
- (BOOL) _decodeHexByte: (uint8_t *) byte
|
||||
atPos: (NSUInteger) pos
|
||||
{
|
||||
BOOL error = NO;
|
||||
char newByte;
|
||||
unichar byteChar;
|
||||
|
||||
byteChar = [self characterAtIndex: pos];
|
||||
if (byteChar < 256)
|
||||
{
|
||||
newByte = [self _decodeHexByte: (char) byteChar];
|
||||
if (newByte == -1)
|
||||
error = YES;
|
||||
else
|
||||
*byte = newByte;
|
||||
}
|
||||
else
|
||||
error = YES;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
//
|
||||
// FIXME: combine with our OpenChange code.
|
||||
//
|
||||
- (BOOL) _decodeHexPair: (uint8_t *) byte
|
||||
atPos: (NSUInteger) pos
|
||||
{
|
||||
BOOL error;
|
||||
uint8_t lowValue, highValue;
|
||||
|
||||
error = [self _decodeHexByte: &highValue atPos: pos];
|
||||
if (!error)
|
||||
{
|
||||
error = [self _decodeHexByte: &lowValue atPos: pos + 1];
|
||||
if (!error)
|
||||
*byte = highValue << 4 | lowValue;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
//
|
||||
// FIXME: combine with our OpenChange code.
|
||||
//
|
||||
- (NSData *) convertHexStringToBytes
|
||||
{
|
||||
NSUInteger count, strLen, bytesLen;
|
||||
uint8_t *bytes, *currentByte;
|
||||
NSData *decoded = nil;
|
||||
BOOL error = NO;
|
||||
|
||||
strLen = [self length];
|
||||
if ((strLen % 2) == 0)
|
||||
{
|
||||
bytesLen = strLen / 2;
|
||||
bytes = NSZoneCalloc (NULL, bytesLen, sizeof (uint8_t));
|
||||
currentByte = bytes;
|
||||
for (count = 0; !error && count < strLen; count += 2)
|
||||
{
|
||||
error = [self _decodeHexPair: currentByte atPos: count];
|
||||
currentByte++;
|
||||
}
|
||||
if (error)
|
||||
NSZoneFree (NULL, bytes);
|
||||
else
|
||||
decoded = [NSData dataWithBytesNoCopy: bytes
|
||||
length: bytesLen
|
||||
freeWhenDone: YES];
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,12 @@
|
||||
In order to use this software in production environments, you need to
|
||||
get a proper usage license from Microsoft. Please contact them directly
|
||||
to negotiate the fees associated to your user base.
|
||||
|
||||
To contact Microsoft, please visit:
|
||||
|
||||
http://www.microsoft.com/en-us/legal/intellectualproperty/IPLicensing/Programs/exchangeactivesyncprotocol.aspx
|
||||
|
||||
and send an email to iplicreq@microsoft.com
|
||||
|
||||
Inverse inc. provides this software for free, but is not responsible
|
||||
for anything related to its usage.
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __SOGOACTIVESYNCCONSTANTS_H__
|
||||
#define __SOGOACTIVESYNCCONSTANTS_H__
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ActiveSyncGenericFolder = 0,
|
||||
ActiveSyncMailFolder = 1,
|
||||
ActiveSyncContactFolder = 2,
|
||||
ActiveSyncEventFolder = 3,
|
||||
ActiveSyncTaskFolder = 4,
|
||||
} SOGoMicrosoftActiveSyncFolderType;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __SOGOACTIVESYNCDISPATCHERSYNC_H__
|
||||
#define __SOGOACTIVESYNCDISPATCHERSYNC_H__
|
||||
|
||||
#import "SOGoActiveSyncDispatcher.h"
|
||||
|
||||
#import <DOM/DOMElement.h>
|
||||
#import <DOM/DOMProtocols.h>
|
||||
|
||||
@class WOResponse;
|
||||
|
||||
@interface SOGoActiveSyncDispatcher (Sync)
|
||||
|
||||
- (void) processSync: (id <DOMElement>) theDocumentElement
|
||||
inResponse: (WOResponse *) theResponse;
|
||||
|
||||
@end
|
||||
|
||||
#endif // SOGOACTIVESYNCDISPATCHERSYNC
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
#include "SOGoActiveSyncConstants.h"
|
||||
|
||||
@class NSException;
|
||||
|
||||
@interface SOGoActiveSyncDispatcher : NSObject
|
||||
{
|
||||
id context;
|
||||
}
|
||||
|
||||
- (id) collectionFromId: (NSString *) theCollectionId
|
||||
type: (SOGoMicrosoftActiveSyncFolderType) theFolderType;
|
||||
|
||||
- (NSException *) dispatchRequest: (id) theRequest
|
||||
inResponse: (id) theResponse
|
||||
context: (id) theContext;
|
||||
|
||||
@end
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __SOGOMAILOBJECTACTIVESYNC_H__
|
||||
#define __SOGOMAILOBJECTACTIVESYNC_H__
|
||||
|
||||
#import <Mailer/SOGoMailObject.h>
|
||||
|
||||
@class iCalCalendar;
|
||||
@class NSDictionary;
|
||||
@class WOContext;
|
||||
|
||||
@interface SOGoMailObject (ActiveSync)
|
||||
|
||||
- (iCalCalendar *) calendarFromIMIPMessage;
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) context;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,639 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#include "SOGoMailObject+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSException.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <NGCards/iCalDateTime.h>
|
||||
#import <NGCards/iCalEvent.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
|
||||
#import <NGExtensions/NGBase64Coding.h>
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGExtensions/NSString+Encoding.h>
|
||||
#import <NGImap4/NGImap4Envelope.h>
|
||||
#import <NGImap4/NGImap4EnvelopeAddress.h>
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
|
||||
#include "iCalTimeZone+ActiveSync.h"
|
||||
#include "NSData+ActiveSync.h"
|
||||
#include "NSDate+ActiveSync.h"
|
||||
#include "NSString+ActiveSync.h"
|
||||
|
||||
#include <Appointments/iCalEntityObject+SOGo.h>
|
||||
#include <Appointments/iCalPerson+SOGo.h>
|
||||
#include <Mailer/NSString+Mail.h>
|
||||
#include <Mailer/SOGoMailBodyPart.h>
|
||||
|
||||
#include <SOGo/SOGoUser.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t dwLowDateTime;
|
||||
uint32_t dwHighDateTime;
|
||||
} FILETIME;
|
||||
|
||||
struct GlobalObjectId {
|
||||
uint8_t ByteArrayID[16];
|
||||
uint8_t YH;
|
||||
uint8_t YL;
|
||||
uint8_t Month;
|
||||
uint8_t D;
|
||||
FILETIME CreationTime;
|
||||
uint8_t X[8];
|
||||
uint32_t Size;
|
||||
uint8_t* Data;
|
||||
};
|
||||
|
||||
@implementation SOGoMailObject (ActiveSync)
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) _setInstanceDate: (struct GlobalObjectId *) newGlobalId
|
||||
fromDate: (NSCalendarDate *) instanceDate
|
||||
{
|
||||
uint16_t year;
|
||||
|
||||
if (instanceDate)
|
||||
{
|
||||
//[instanceDate setTimeZone: timeZone];
|
||||
year = [instanceDate yearOfCommonEra];
|
||||
newGlobalId->YH = year >> 8;
|
||||
newGlobalId->YL = year & 0xff;
|
||||
newGlobalId->Month = [instanceDate monthOfYear];
|
||||
newGlobalId->D = [instanceDate dayOfMonth];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The GlobalObjId is documented here: http://msdn.microsoft.com/en-us/library/ee160198(v=EXCHG.80).aspx
|
||||
//
|
||||
- (NSData *) _computeGlobalObjectIdFromEvent: (iCalEvent *) event
|
||||
{
|
||||
NSData *binPrefix, *globalObjectId, *uidAsASCII;
|
||||
NSString *prefix, *uid;
|
||||
|
||||
struct GlobalObjectId newGlobalId;
|
||||
const char *bytes;
|
||||
|
||||
prefix = @"040000008200e00074c5b7101a82e008";
|
||||
|
||||
// dataPrefix is "vCal-Uid %x01 %x00 %x00 %x00"
|
||||
uint8_t dataPrefix[] = { 0x76, 0x43, 0x61, 0x6c, 0x2d, 0x55, 0x69, 0x64, 0x01, 0x00, 0x00, 0x00 };
|
||||
uid = [event uid];
|
||||
|
||||
binPrefix = [prefix convertHexStringToBytes];
|
||||
[binPrefix getBytes: &newGlobalId.ByteArrayID];
|
||||
[self _setInstanceDate: &newGlobalId
|
||||
fromDate: [event recurrenceId]];
|
||||
uidAsASCII = [uid dataUsingEncoding: NSASCIIStringEncoding];
|
||||
bytes = [uidAsASCII bytes];
|
||||
|
||||
// 0x0c is the size of our dataPrefix
|
||||
newGlobalId.Size = 0x0c + [uidAsASCII length];
|
||||
newGlobalId.Data = malloc(newGlobalId.Size * sizeof(uint8_t));
|
||||
memcpy(newGlobalId.Data, dataPrefix, 0x0c);
|
||||
memcpy(newGlobalId.Data + 0x0c, bytes, newGlobalId.Size - 0x0c);
|
||||
|
||||
globalObjectId = [[NSData alloc] initWithBytes: &newGlobalId length: 40 + newGlobalId.Size*sizeof(uint8_t)];
|
||||
free(newGlobalId.Data);
|
||||
|
||||
return [globalObjectId autorelease];
|
||||
}
|
||||
|
||||
//
|
||||
// For debugging purposes...
|
||||
//
|
||||
- (NSString *) _uidFromGlobalObjectId: (NSData *) objectId
|
||||
{
|
||||
NSString *uid;
|
||||
|
||||
struct GlobalObjectId *newGlobalId;
|
||||
NSUInteger length;
|
||||
uint8_t *bytes;
|
||||
|
||||
length = [objectId length];
|
||||
uid = nil;
|
||||
|
||||
bytes = malloc(length*sizeof(uint8_t));
|
||||
[objectId getBytes: bytes length: length];
|
||||
|
||||
newGlobalId = (struct GlobalObjectId *)bytes;
|
||||
|
||||
// We must take the offset (dataPrefix) into account
|
||||
uid = [[NSString alloc] initWithBytes: newGlobalId->Data+12 length: newGlobalId->Size-12 encoding: NSASCIIStringEncoding];
|
||||
free(bytes);
|
||||
|
||||
return AUTORELEASE(uid);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (NSString *) _emailAddressesFrom: (NSArray *) enveloppeAddresses
|
||||
{
|
||||
NGImap4EnvelopeAddress *address;
|
||||
NSString *email, *rc, *name;
|
||||
NSMutableArray *addresses;
|
||||
int i, max;
|
||||
|
||||
rc = nil;
|
||||
max = [enveloppeAddresses count];
|
||||
|
||||
if (max > 0)
|
||||
{
|
||||
addresses = [NSMutableArray array];
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
address = [enveloppeAddresses objectAtIndex: i];
|
||||
name = [address personalName];
|
||||
email = [NSString stringWithFormat: @"\"%@\" <%@>", (name ? name : [address baseEMail]), [address baseEMail]];
|
||||
|
||||
if (email)
|
||||
[addresses addObject: email];
|
||||
}
|
||||
rc = [addresses componentsJoinedByString: @", "];
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (NSData *) _preferredBodyDataInMultipartUsingType: (int) theType
|
||||
{
|
||||
NSString *key, *plainKey, *htmlKey, *type, *subtype;
|
||||
NSDictionary *textParts, *part;
|
||||
NSEnumerator *e;
|
||||
NSData *d;
|
||||
|
||||
textParts = [self fetchPlainTextParts];
|
||||
e = [textParts keyEnumerator];
|
||||
plainKey = nil;
|
||||
htmlKey = nil;
|
||||
d = nil;
|
||||
|
||||
while ((key = [e nextObject]))
|
||||
{
|
||||
part = [self lookupInfoForBodyPart: key];
|
||||
type = [part valueForKey: @"type"];
|
||||
subtype = [part valueForKey: @"subtype"];
|
||||
|
||||
if ([type isEqualToString: @"text"] && [subtype isEqualToString: @"html"])
|
||||
htmlKey = key;
|
||||
else if ([type isEqualToString: @"text"] && [subtype isEqualToString: @"plain"])
|
||||
plainKey = key;
|
||||
}
|
||||
|
||||
if (theType == 2)
|
||||
{
|
||||
d = [[self fetchPlainTextParts] objectForKey: htmlKey];
|
||||
}
|
||||
else if (theType == 1)
|
||||
{
|
||||
d = [[self fetchPlainTextParts] objectForKey: plainKey];
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (NSData *) _preferredBodyDataUsingType: (int) theType
|
||||
nativeType: (int *) theNativeType
|
||||
{
|
||||
NSString *type, *subtype, *encoding;
|
||||
NSData *d;
|
||||
|
||||
type = [[[self bodyStructure] valueForKey: @"type"] lowercaseString];
|
||||
subtype = [[[self bodyStructure] valueForKey: @"subtype"] lowercaseString];
|
||||
|
||||
d = nil;
|
||||
|
||||
// We determine the native type
|
||||
if ([type isEqualToString: @"text"] && [subtype isEqualToString: @"plain"])
|
||||
*theNativeType = 1;
|
||||
else if ([type isEqualToString: @"text"] && [subtype isEqualToString: @"html"])
|
||||
*theNativeType = 2;
|
||||
else if ([type isEqualToString: @"multipart"])
|
||||
*theNativeType = 4;
|
||||
|
||||
// We get the right part based on the preference
|
||||
if (theType == 1 || theType == 2)
|
||||
{
|
||||
if ([type isEqualToString: @"text"])
|
||||
{
|
||||
d = [[self fetchPlainTextParts] objectForKey: @""];
|
||||
|
||||
// We check if we have base64 encoded parts. If so, we just
|
||||
// un-encode them before using them
|
||||
encoding = [[self lookupInfoForBodyPart: @""] objectForKey: @"encoding"];
|
||||
|
||||
if ([encoding caseInsensitiveCompare: @"base64"] == NSOrderedSame)
|
||||
d = [d dataByDecodingBase64];
|
||||
|
||||
// Check if we must convert html->plain
|
||||
if (theType == 1 && [subtype isEqualToString: @"html"])
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
s = [[NSString alloc] initWithData: d encoding: NSUTF8StringEncoding];
|
||||
AUTORELEASE(s);
|
||||
|
||||
s = [s htmlToText];
|
||||
d = [s dataUsingEncoding: NSUTF8StringEncoding];
|
||||
}
|
||||
}
|
||||
else if ([type isEqualToString: @"multipart"])
|
||||
{
|
||||
d = [self _preferredBodyDataInMultipartUsingType: theType];
|
||||
}
|
||||
}
|
||||
else if (theType == 4)
|
||||
{
|
||||
d = [self content];
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (iCalCalendar *) calendarFromIMIPMessage
|
||||
{
|
||||
NSDictionary *part;
|
||||
NSArray *parts;
|
||||
int i;
|
||||
|
||||
// We check if we have at least 2 parts and if one of them is a text/calendar
|
||||
parts = [[self bodyStructure] objectForKey: @"parts"];
|
||||
|
||||
if ([parts count] > 1)
|
||||
{
|
||||
for (i = 0; i < [parts count]; i++)
|
||||
{
|
||||
part = [parts objectAtIndex: i];
|
||||
|
||||
if ([[part objectForKey: @"type"] isEqualToString: @"text"] &&
|
||||
[[part objectForKey: @"subtype"] isEqualToString: @"calendar"])
|
||||
{
|
||||
id bodyPart;
|
||||
|
||||
bodyPart = [self lookupImap4BodyPartKey: [NSString stringWithFormat: @"%d", i+1]
|
||||
inContext: self->context];
|
||||
|
||||
if (bodyPart)
|
||||
{
|
||||
iCalCalendar *calendar;
|
||||
NSData *calendarData;
|
||||
|
||||
calendarData = [bodyPart fetchBLOB];
|
||||
calendar = nil;
|
||||
|
||||
NS_DURING
|
||||
calendar = [iCalCalendar parseSingleFromSource: calendarData];
|
||||
NS_HANDLER
|
||||
calendar = nil;
|
||||
NS_ENDHANDLER
|
||||
|
||||
return calendar;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) _context
|
||||
{
|
||||
NSData *d, *globalObjId;
|
||||
NSMutableString *s;
|
||||
id value;
|
||||
|
||||
iCalCalendar *calendar;
|
||||
|
||||
int preferredBodyType, nativeBodyType;
|
||||
|
||||
s = [NSMutableString string];
|
||||
|
||||
// To - "The value of this element contains one or more e-mail addresses.
|
||||
// If there are multiple e-mail addresses, they are separated by commas."
|
||||
value = [self _emailAddressesFrom: [[self envelope] to]];
|
||||
if (value)
|
||||
[s appendFormat: @"<To xmlns=\"Email:\">%@</To>", [value activeSyncRepresentationInContext: context]];
|
||||
|
||||
// From
|
||||
value = [self _emailAddressesFrom: [[self envelope] from]];
|
||||
if (value)
|
||||
[s appendFormat: @"<From xmlns=\"Email:\">%@</From>", [value activeSyncRepresentationInContext: context]];
|
||||
|
||||
// Subject
|
||||
value = [self decodedSubject];
|
||||
if (value)
|
||||
{
|
||||
[s appendFormat: @"<Subject xmlns=\"Email:\">%@</Subject>", [value activeSyncRepresentationInContext: context]];
|
||||
[s appendFormat: @"<ThreadTopic xmlns=\"Email:\">%@</ThreadTopic>", [value activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
|
||||
// DateReceived
|
||||
value = [self date];
|
||||
if (value)
|
||||
[s appendFormat: @"<DateReceived xmlns=\"Email:\">%@</DateReceived>", [value activeSyncRepresentationInContext: context]];
|
||||
|
||||
// DisplayTo
|
||||
[s appendFormat: @"<DisplayTo xmlns=\"Email:\">%@</DisplayTo>", [[context activeUser] login]];
|
||||
|
||||
// Cc - same syntax as the To field
|
||||
value = [self _emailAddressesFrom: [[self envelope] cc]];
|
||||
if (value)
|
||||
[s appendFormat: @"<Cc xmlns=\"Email:\">%@</Cc>", [value activeSyncRepresentationInContext: context]];
|
||||
|
||||
// Importance - FIXME
|
||||
[s appendFormat: @"<Importance xmlns=\"Email:\">%@</Importance>", @"1"];
|
||||
|
||||
// Read
|
||||
[s appendFormat: @"<Read xmlns=\"Email:\">%d</Read>", ([self read] ? 1 : 0)];
|
||||
|
||||
// We handle MeetingRequest
|
||||
calendar = [self calendarFromIMIPMessage];
|
||||
|
||||
if (calendar)
|
||||
{
|
||||
NSString *method, *className;
|
||||
iCalPerson *attendee;
|
||||
iCalTimeZone *tz;
|
||||
iCalEvent *event;
|
||||
|
||||
iCalPersonPartStat partstat;
|
||||
int v;
|
||||
|
||||
event = [[calendar events] lastObject];
|
||||
method = [[event parent] method];
|
||||
|
||||
// If we are the organizer, let's pick the attendee based on the From address
|
||||
if ([event userIsOrganizer: [context activeUser]])
|
||||
attendee = [event findAttendeeWithEmail: [[[[self envelope] from] lastObject] baseEMail]];
|
||||
else
|
||||
attendee = [event findAttendeeWithEmail: [[[context activeUser] allEmails] objectAtIndex: 0]];
|
||||
|
||||
partstat = [attendee participationStatus];
|
||||
|
||||
// We generate the correct MessageClass
|
||||
if ([method isEqualToString: @"REQUEST"])
|
||||
className = @"IPM.Schedule.Meeting.Request";
|
||||
else if ([method isEqualToString: @"REPLY"])
|
||||
{
|
||||
switch (partstat)
|
||||
{
|
||||
case iCalPersonPartStatAccepted:
|
||||
className = @"IPM.Schedule.Meeting.Resp.Pos";
|
||||
break;
|
||||
case iCalPersonPartStatDeclined:
|
||||
className = @"IPM.Schedule.Meeting.Resp.Neg";
|
||||
break;
|
||||
case iCalPersonPartStatTentative:
|
||||
case iCalPersonPartStatNeedsAction:
|
||||
className = @"IPM.Schedule.Meeting.Resp.Tent";
|
||||
break;
|
||||
default:
|
||||
className = @"IPM.Appointment";
|
||||
NSLog(@"unhandled part stat");
|
||||
}
|
||||
}
|
||||
else if ([method isEqualToString: @"COUNTER"])
|
||||
className = @"IPM.Schedule.Meeting.Resp.Tent";
|
||||
else if ([method isEqualToString: @"CANCEL"])
|
||||
className = @"IPM.Schedule.Meeting.Cancelled";
|
||||
else
|
||||
className = @"IPM.Appointment";
|
||||
|
||||
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", className];
|
||||
|
||||
[s appendString: @"<MeetingRequest xmlns=\"Email:\">"];
|
||||
|
||||
[s appendFormat: @"<AllDayEvent xmlns=\"Email:\">%d</AllDayEvent>", ([event isAllDay] ? 1 : 0)];
|
||||
|
||||
// StartTime -- http://msdn.microsoft.com/en-us/library/ee157132(v=exchg.80).aspx
|
||||
if ([event startDate])
|
||||
[s appendFormat: @"<StartTime xmlns=\"Email:\">%@</StartTime>", [[event startDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
|
||||
if ([event timeStampAsDate])
|
||||
[s appendFormat: @"<DTStamp xmlns=\"Email:\">%@</DTStamp>", [[event timeStampAsDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
else if ([event created])
|
||||
[s appendFormat: @"<DTStamp xmlns=\"Email:\">%@</DTStamp>", [[event created] activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
|
||||
// EndTime -- http://msdn.microsoft.com/en-us/library/ee157945(v=exchg.80).aspx
|
||||
if ([event endDate])
|
||||
[s appendFormat: @"<EndTime xmlns=\"Email:\">%@</EndTime>", [[event endDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
|
||||
// FIXME: Single appointment - others are not supported right now
|
||||
[s appendFormat: @"<InstanceType xmlns=\"Email:\">%d</InstanceType>", 0];
|
||||
|
||||
// Location
|
||||
if ([[event location] length])
|
||||
[s appendFormat: @"<Location xmlns=\"Email:\">%@</Location>", [[event location] activeSyncRepresentationInContext: context]];
|
||||
|
||||
[s appendFormat: @"<Organizer xmlns=\"Email:\">%@</Organizer>", [[[event organizer] mailAddress] activeSyncRepresentationInContext: context]];
|
||||
|
||||
// This will trigger the SendMail command. We set it to no for email invitations as
|
||||
// SOGo will send emails when MeetingResponse is called.
|
||||
[s appendFormat: @"<ResponseRequested xmlns=\"Email:\">%d</ResponseRequested>", 0];
|
||||
|
||||
// Sensitivity
|
||||
if ([[event accessClass] isEqualToString: @"PRIVATE"])
|
||||
v = 2;
|
||||
if ([[event accessClass] isEqualToString: @"CONFIDENTIAL"])
|
||||
v = 3;
|
||||
else
|
||||
v = 0;
|
||||
|
||||
[s appendFormat: @"<Sensitivity xmlns=\"Email:\">%d</Sensitivity>", v];
|
||||
|
||||
[s appendFormat: @"<BusyStatus xmlns=\"Email:\">%d</BusyStatus>", 2];
|
||||
|
||||
// Timezone
|
||||
tz = [(iCalDateTime *)[event firstChildWithTag: @"dtstart"] timeZone];
|
||||
|
||||
if (!tz)
|
||||
tz = [iCalTimeZone timeZoneForName: @"Europe/London"];
|
||||
|
||||
[s appendFormat: @"<TimeZone xmlns=\"Email:\">%@</TimeZone>", [tz activeSyncRepresentationInContext: context]];
|
||||
|
||||
|
||||
// We disallow new time proposals
|
||||
[s appendFormat: @"<DisallowNewTimeProposal xmlns=\"Email:\">%d</DisallowNewTimeProposal>", 1];
|
||||
|
||||
// From http://blogs.msdn.com/b/exchangedev/archive/2011/07/22/working-with-meeting-requests-in-exchange-activesync.aspx:
|
||||
//
|
||||
// "Clients that need to determine whether the GlobalObjId element for a meeting request corresponds to an existing Calendar
|
||||
// object in the Calendar folder have to convert the GlobalObjId element value to a UID element value to make the comparison."
|
||||
//
|
||||
globalObjId = [self _computeGlobalObjectIdFromEvent: event];
|
||||
[s appendFormat: @"<GlobalObjId xmlns=\"Email:\">%@</GlobalObjId>", [globalObjId activeSyncRepresentationInContext: context]];
|
||||
|
||||
// We set the right message type - we must set AS version to 14.1 for this
|
||||
[s appendFormat: @"<MeetingMessageType xmlns=\"Email2:\">%d</MeetingMessageType>", 1];
|
||||
[s appendString: @"</MeetingRequest>"];
|
||||
|
||||
// ContentClass
|
||||
[s appendFormat: @"<ContentClass xmlns=\"Email:\">%@</ContentClass>", @"urn:content-classes:calendarmessage"];
|
||||
}
|
||||
else
|
||||
{
|
||||
// MesssageClass and ContentClass
|
||||
[s appendFormat: @"<MessageClass xmlns=\"Email:\">%@</MessageClass>", @"IPM.Note"];
|
||||
[s appendFormat: @"<ContentClass xmlns=\"Email:\">%@</ContentClass>", @"urn:content-classes:message"];
|
||||
}
|
||||
|
||||
// Reply-To - FIXME
|
||||
//NSArray *replyTo = [[message objectForKey: @"envelope"] replyTo];
|
||||
//if ([replyTo count])
|
||||
// [s appendFormat: @"<Reply-To xmlns=\"Email:\">%@</Reply-To>", [addressFormatter stringForArray: replyTo]];
|
||||
|
||||
// InternetCPID - 65001 == UTF-8, we use this all the time for now.
|
||||
[s appendFormat: @"<InternetCPID xmlns=\"Email:\">%@</InternetCPID>", @"65001"];
|
||||
|
||||
// Body - namespace 17
|
||||
preferredBodyType = [[context objectForKey: @"BodyPreferenceType"] intValue];
|
||||
|
||||
nativeBodyType = 1;
|
||||
d = [self _preferredBodyDataUsingType: preferredBodyType nativeType: &nativeBodyType];
|
||||
|
||||
if (d)
|
||||
{
|
||||
NSString *content;
|
||||
int len, truncated;
|
||||
|
||||
content = [[NSString alloc] initWithData: d encoding: NSUTF8StringEncoding];
|
||||
|
||||
// FIXME: This is a hack. We should normally avoid doing this as we might get
|
||||
// broken encodings. We should rather tell that the data was truncated and expect
|
||||
// a ItemOperations call to download the whole base64 encoding multipart.
|
||||
if (!content)
|
||||
content = [[NSString alloc] initWithData: d encoding: NSISOLatin1StringEncoding];
|
||||
|
||||
AUTORELEASE(content);
|
||||
|
||||
content = [content activeSyncRepresentationInContext: context];
|
||||
truncated = 0;
|
||||
|
||||
len = [content length];
|
||||
|
||||
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
|
||||
[s appendFormat: @"<Type>%d</Type>", preferredBodyType];
|
||||
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", len];
|
||||
[s appendFormat: @"<Truncated>%d</Truncated>", 0];
|
||||
if (!truncated)
|
||||
[s appendFormat: @"<Data>%@</Data>", content];
|
||||
[s appendString: @"</Body>"];
|
||||
}
|
||||
|
||||
// Attachments -namespace 16
|
||||
NSArray *attachmentKeys = [self fetchFileAttachmentKeys];
|
||||
if ([attachmentKeys count])
|
||||
{
|
||||
int i;
|
||||
|
||||
[s appendString: @"<Attachments xmlns=\"AirSyncBase:\">"];
|
||||
|
||||
for (i = 0; i < [attachmentKeys count]; i++)
|
||||
{
|
||||
value = [attachmentKeys objectAtIndex: i];
|
||||
|
||||
[s appendString: @"<Attachment>"];
|
||||
[s appendFormat: @"<DisplayName>%@</DisplayName>", [[value objectForKey: @"filename"] activeSyncRepresentationInContext: context]];
|
||||
|
||||
// FileReference must be a unique identifier across the whole store. We use the following structure:
|
||||
// mail/<foldername>/<message UID/<pathofpart>
|
||||
// mail/INBOX/2
|
||||
[s appendFormat: @"<FileReference>mail/%@/%@/%@</FileReference>", [[[self container] relativeImap4Name] stringByEscapingURL], [self nameInContainer], [value objectForKey: @"path"]];
|
||||
|
||||
[s appendFormat: @"<Method>%d</Method>", 1]; // See: http://msdn.microsoft.com/en-us/library/ee160322(v=exchg.80).aspx
|
||||
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [[value objectForKey: @"size"] intValue]];
|
||||
//[s appendFormat: @"<IsInline>%d</IsInline>", 1];
|
||||
[s appendString: @"</Attachment>"];
|
||||
}
|
||||
|
||||
[s appendString: @"</Attachments>"];
|
||||
}
|
||||
|
||||
// Flags
|
||||
[s appendString: @"<Flag xmlns=\"Email:\">"];
|
||||
[s appendFormat: @"<FlagStatus>%d</FlagStatus>", 0];
|
||||
[s appendString: @"</Flag>"];
|
||||
|
||||
// FIXME - support these in the future
|
||||
//[s appendString: @"<ConversationId xmlns=\"Email2:\">foobar</ConversationId>"];
|
||||
//[s appendString: @"<ConversationIndex xmlns=\"Email2:\">zot=</ConversationIndex>"];
|
||||
|
||||
// NativeBodyType -- http://msdn.microsoft.com/en-us/library/ee218276(v=exchg.80).aspx
|
||||
// This is a required child element.
|
||||
// 1 -> plain/text, 2 -> HTML and 3 -> RTF
|
||||
if (nativeBodyType == 4)
|
||||
nativeBodyType = 1;
|
||||
|
||||
[s appendFormat: @"<NativeBodyType xmlns=\"AirSyncBase:\">%d</NativeBodyType>", nativeBodyType];
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) _context
|
||||
{
|
||||
id o;
|
||||
|
||||
if ((o = [theValues objectForKey: @"Flag"]))
|
||||
{
|
||||
o = [o objectForKey: @"FlagStatus"];
|
||||
|
||||
if ([o intValue])
|
||||
[self addFlags: @"\\Flagged"];
|
||||
else
|
||||
[self removeFlags: @"\\Flagged"];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#import <NGObjWeb/SoObjectWebDAVDispatcher.h>
|
||||
|
||||
#include <NGObjWeb/SoObject+SoDAV.h>
|
||||
#include <NGObjWeb/WEClientCapabilities.h>
|
||||
#include <NGObjWeb/WOContext.h>
|
||||
#include <NGObjWeb/WORequest.h>
|
||||
#include <NGObjWeb/WOResponse.h>
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
|
||||
@interface SoObjectWebDAVDispatcher (ActiveSync)
|
||||
|
||||
- (id)_callObjectMethod:(NSString *)_method inContext:(WOContext *)_ctx;
|
||||
- (id) doOPTIONS:(WOContext *)_ctx;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SoObjectWebDAVDispatcher (ActiveSync)
|
||||
|
||||
- (id) doOPTIONS:(WOContext *)_ctx
|
||||
{
|
||||
WOResponse *response;
|
||||
|
||||
/*
|
||||
See example: http://msdn.microsoft.com/en-us/library/ee204257(v=exchg.80).aspx
|
||||
*/
|
||||
if ([[[_ctx request] requestHandlerKey] isEqualToString: @"Microsoft-Server-ActiveSync"])
|
||||
{
|
||||
response = [_ctx response];
|
||||
[response setStatus: 200];
|
||||
|
||||
[response setHeader: @"private" forKey: @"Cache-Control"];
|
||||
[response setHeader: @"OPTIONS, POST" forKey: @"Allow"];
|
||||
[response setHeader: @"14.1" forKey: @"MS-Server-ActiveSync"];
|
||||
[response setHeader: @"2.0,2.1,2.5,12.0,12.1,14.0,14.1" forKey: @"MS-ASProtocolVersions"];
|
||||
[response setHeader: @"Sync,SendMail,SmartForward,SmartReply,GetAttachment,GetHierarchy,CreateCollection,DeleteCollection,MoveCollection,FolderSync,FolderCreate,FolderDelete,FolderUpdate,MoveItems,GetItemEstimate,MeetingResponse,Search,Settings,Ping,ItemOperations,Provision,ResolveRecipients,ValidateCert" forKey: @"MS-ASProtocolCommands"];
|
||||
[response setHeader: @"OPTIONS, POST" forKey: @"Public"];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSArray *tmp;
|
||||
id result;
|
||||
|
||||
/* this checks whether the object provides a specific OPTIONS method */
|
||||
if ((result = [self _callObjectMethod:@"OPTIONS" inContext:_ctx]) != nil)
|
||||
return result;
|
||||
|
||||
response = [_ctx response];
|
||||
[response setStatus:200 /* OK */];
|
||||
|
||||
if ((tmp = [self->object davAllowedMethodsInContext:_ctx]) != nil)
|
||||
[response setHeader:[tmp componentsJoinedByString:@", "] forKey:@"allow"];
|
||||
|
||||
if ([[[_ctx request] clientCapabilities] isWebFolder]) {
|
||||
/*
|
||||
As described over here:
|
||||
http://teyc.editthispage.com/2005/06/02
|
||||
|
||||
This page also says that: "MS-Auth-Via header is not required to work
|
||||
with Web Folders".
|
||||
*/
|
||||
[response setHeader:[tmp componentsJoinedByString:@", "] forKey:@"public"];
|
||||
}
|
||||
|
||||
if ((tmp = [self->object davComplianceClassesInContext:_ctx]) != nil)
|
||||
[response setHeader:[tmp componentsJoinedByString:@", "] forKey:@"dav"];
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,36 @@
|
||||
# common make file for SoObject bundles
|
||||
|
||||
include ../config.make
|
||||
include $(GNUSTEP_MAKEFILES)/common.make
|
||||
include ../Version
|
||||
|
||||
NEEDS_GUI=no
|
||||
BUNDLE_EXTENSION = .SOGo
|
||||
BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR)
|
||||
WOBUNDLE_EXTENSION = $(BUNDLE_EXTENSION)
|
||||
WOBUNDLE_INSTALL_DIR = $(BUNDLE_INSTALL_DIR)
|
||||
|
||||
# SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
|
||||
|
||||
ADDITIONAL_INCLUDE_DIRS += \
|
||||
-I.. \
|
||||
-I../.. \
|
||||
-I../../SOPE
|
||||
|
||||
ADDITIONAL_LIB_DIRS += \
|
||||
-L../SOGo/SOGo.framework/ \
|
||||
-L../../SOGo/$(GNUSTEP_OBJ_DIR)/ \
|
||||
-L../../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ \
|
||||
-L../../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
|
||||
-L/usr/local/lib
|
||||
|
||||
BUNDLE_LIBS += \
|
||||
-lSOGo \
|
||||
-lGDLContentStore \
|
||||
-lGDLAccess \
|
||||
-lNGObjWeb \
|
||||
-lNGCards -lNGMime -lNGLdap \
|
||||
-lNGStreams -lNGExtensions -lEOControl \
|
||||
-lDOM -lSaxObjC -lSBJson
|
||||
|
||||
ADDITIONAL_BUNDLE_LIBS += $(BUNDLE_LIBS)
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ICALEVENTACTIVESYNC_H__
|
||||
#define __ICALEVENTACTIVESYNC_H__
|
||||
|
||||
#import <NGCards/iCalEvent.h>
|
||||
|
||||
@class NSString;
|
||||
@class WOContext;
|
||||
|
||||
@interface iCalEvent (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) context;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#import "iCalEvent+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSDate.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGObjWeb/WOContext.h>
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <NGCards/iCalDateTime.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserDefaults.h>
|
||||
|
||||
#import <Appointments/iCalEntityObject+SOGo.h>
|
||||
|
||||
#include "iCalRecurrenceRule+ActiveSync.h"
|
||||
#include "iCalTimeZone+ActiveSync.h"
|
||||
#include "NSDate+ActiveSync.h"
|
||||
#include "NSString+ActiveSync.h"
|
||||
|
||||
@implementation iCalEvent (ActiveSync)
|
||||
|
||||
- (int) _attendeeStatus: (iCalPerson *) attendee
|
||||
{
|
||||
int attendee_status;
|
||||
|
||||
attendee_status = 5;
|
||||
if ([[attendee partStat] caseInsensitiveCompare: @"ACCEPTED"] == NSOrderedSame)
|
||||
attendee_status = 3;
|
||||
else if ([[attendee partStat] caseInsensitiveCompare: @"DECLINED"] == NSOrderedSame)
|
||||
attendee_status = 4;
|
||||
else if ([[attendee partStat] caseInsensitiveCompare: @"TENTATIVE"] == NSOrderedSame)
|
||||
attendee_status = 2;
|
||||
|
||||
return attendee_status;
|
||||
}
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
|
||||
{
|
||||
NSMutableString *s;
|
||||
NSArray *attendees;
|
||||
|
||||
iCalPerson *organizer, *attendee;
|
||||
iCalTimeZone *tz;
|
||||
id o;
|
||||
|
||||
int v;
|
||||
|
||||
s = [NSMutableString string];
|
||||
|
||||
[s appendFormat: @"<AllDayEvent xmlns=\"Calendar:\">%d</AllDayEvent>", ([self isAllDay] ? 1 : 0)];
|
||||
|
||||
// DTStamp -- http://msdn.microsoft.com/en-us/library/ee219470(v=exchg.80).aspx
|
||||
if ([self timeStampAsDate])
|
||||
[s appendFormat: @"<DTStamp xmlns=\"Calendar:\">%@</DTStamp>", [[self timeStampAsDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
else if ([self created])
|
||||
[s appendFormat: @"<DTStamp xmlns=\"Calendar:\">%@</DTStamp>", [[self created] activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
|
||||
// StartTime -- http://msdn.microsoft.com/en-us/library/ee157132(v=exchg.80).aspx
|
||||
if ([self startDate])
|
||||
[s appendFormat: @"<StartTime xmlns=\"Calendar:\">%@</StartTime>", [[self startDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
|
||||
// EndTime -- http://msdn.microsoft.com/en-us/library/ee157945(v=exchg.80).aspx
|
||||
if ([self endDate])
|
||||
[s appendFormat: @"<EndTime xmlns=\"Calendar:\">%@</EndTime>", [[self endDate] activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
|
||||
// Timezone
|
||||
tz = [(iCalDateTime *)[self firstChildWithTag: @"dtstart"] timeZone];
|
||||
|
||||
if (!tz)
|
||||
tz = [iCalTimeZone timeZoneForName: @"Europe/London"];
|
||||
|
||||
[s appendFormat: @"<TimeZone xmlns=\"Calendar:\">%@</TimeZone>", [tz activeSyncRepresentationInContext: context]];
|
||||
|
||||
// Organizer and other invitations related properties
|
||||
if ((organizer = [self organizer]))
|
||||
{
|
||||
o = [organizer rfc822Email];
|
||||
if ([o length])
|
||||
{
|
||||
[s appendFormat: @"<Organizer_Email xmlns=\"Calendar:\">%@</Organizer_Email>", o];
|
||||
|
||||
o = [organizer cn];
|
||||
if ([o length])
|
||||
[s appendFormat: @"<Organizer_Name xmlns=\"Calendar:\">%@</Organizer_Name>", o];
|
||||
}
|
||||
}
|
||||
|
||||
// Attendees
|
||||
attendees = [self attendees];
|
||||
|
||||
if ([attendees count])
|
||||
{
|
||||
int i, attendee_status, attendee_type;
|
||||
|
||||
[s appendString: @"<Attendees xmlns=\"Calendar:\">"];
|
||||
|
||||
for (i = 0; i < [attendees count]; i++)
|
||||
{
|
||||
[s appendString: @"<Attendee xmlns=\"Calendar:\">"];
|
||||
|
||||
attendee = [attendees objectAtIndex: i];
|
||||
[s appendFormat: @"<Attendee_Email xmlns=\"Calendar:\">%@</Attendee_Email>", [attendee rfc822Email]];
|
||||
[s appendFormat: @"<Attendee_Name xmlns=\"Calendar:\">%@</Attendee_Name>", [attendee cn]];
|
||||
|
||||
attendee_status = [self _attendeeStatus: attendee];
|
||||
|
||||
[s appendFormat: @"<Attendee_Status xmlns=\"Calendar:\">%d</Attendee_Status>", attendee_status];
|
||||
|
||||
// FIXME: handle resource
|
||||
if ([[attendee role] caseInsensitiveCompare: @"REQ-PARTICIPANT"] == NSOrderedSame)
|
||||
attendee_type = 1;
|
||||
else
|
||||
attendee_type = 2;
|
||||
|
||||
[s appendFormat: @"<Attendee_Type xmlns=\"Calendar:\">%d</Attendee_Type>", attendee_type];
|
||||
[s appendString: @"</Attendee>"];
|
||||
}
|
||||
[s appendString: @"</Attendees>"];
|
||||
}
|
||||
|
||||
// This depends on the 'NEEDS-ACTION' parameter.
|
||||
// This will trigger the SendMail command
|
||||
if ([self userIsAttendee: [context activeUser]])
|
||||
{
|
||||
iCalPerson *attendee;
|
||||
|
||||
int attendee_status;
|
||||
|
||||
attendee = [self userAsAttendee: [context activeUser]];
|
||||
attendee_status = [self _attendeeStatus: attendee];
|
||||
|
||||
[s appendFormat: @"<ResponseRequested xmlns=\"Calendar:\">%d</ResponseRequested>", 1];
|
||||
[s appendFormat: @"<ResponseType xmlns=\"Calendar:\">%d</ResponseType>", attendee_status];
|
||||
[s appendFormat: @"<MeetingStatus xmlns=\"Calendar:\">%d</MeetingStatus>", 3];
|
||||
[s appendFormat: @"<DisallowNewTimeProposal xmlns=\"Calendar:\">%d</DisallowNewTimeProposal>", 1];
|
||||
|
||||
// BusyStatus -- http://msdn.microsoft.com/en-us/library/ee202290(v=exchg.80).aspx
|
||||
[s appendFormat: @"<BusyStatus xmlns=\"Calendar:\">%d</BusyStatus>", 2];
|
||||
}
|
||||
|
||||
// Subject -- http://msdn.microsoft.com/en-us/library/ee157192(v=exchg.80).aspx
|
||||
if ([[self summary] length])
|
||||
[s appendFormat: @"<Subject xmlns=\"Calendar:\">%@</Subject>", [[self summary] activeSyncRepresentationInContext: context]];
|
||||
|
||||
// Location
|
||||
if ([[self location] length])
|
||||
[s appendFormat: @"<Location xmlns=\"Calendar:\">%@</Location>", [[self location] activeSyncRepresentationInContext: context]];
|
||||
|
||||
// Importance - NOT SUPPORTED - DO NOT ENABLE
|
||||
//o = [self priority];
|
||||
//if ([o isEqualToString: @"9"])
|
||||
// v = 0;
|
||||
//else if ([o isEqualToString: @"1"])
|
||||
// v = 2;
|
||||
//else
|
||||
// v = 1;
|
||||
//[s appendFormat: @"<Importance xmlns=\"Calendar:\">%d</Importance>", v];
|
||||
|
||||
// UID -- http://msdn.microsoft.com/en-us/library/ee159919(v=exchg.80).aspx
|
||||
if ([[self uid] length])
|
||||
[s appendFormat: @"<UID xmlns=\"Calendar:\">%@</UID>", [self uid]];
|
||||
|
||||
// Sensitivity
|
||||
if ([[self accessClass] isEqualToString: @"PRIVATE"])
|
||||
v = 2;
|
||||
if ([[self accessClass] isEqualToString: @"CONFIDENTIAL"])
|
||||
v = 3;
|
||||
else
|
||||
v = 0;
|
||||
|
||||
[s appendFormat: @"<Sensitivity xmlns=\"Calendar:\">%d</Sensitivity>", v];
|
||||
|
||||
// Reminder -- http://msdn.microsoft.com/en-us/library/ee219691(v=exchg.80).aspx
|
||||
// TODO
|
||||
|
||||
// Recurrence rules
|
||||
if ([self isRecurrent])
|
||||
{
|
||||
[s appendString: [[[self recurrenceRules] lastObject] activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
|
||||
// Comment
|
||||
o = [self comment];
|
||||
if ([o length])
|
||||
{
|
||||
o = [o activeSyncRepresentationInContext: context];
|
||||
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
|
||||
[s appendFormat: @"<Type>%d</Type>", 1];
|
||||
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
|
||||
[s appendFormat: @"<Truncated>%d</Truncated>", 0];
|
||||
[s appendFormat: @"<Data>%@</Data>", o];
|
||||
[s appendString: @"</Body>"];
|
||||
}
|
||||
|
||||
[s appendFormat: @"<NativeBodyType xmlns=\"AirSyncBase:\">%d</NativeBodyType>", 1];
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
// To understand meeting requests/responses, see:
|
||||
//
|
||||
// http://blogs.msdn.com/b/exchangedev/archive/2011/07/22/working-with-meeting-requests-in-exchange-activesync.aspx
|
||||
// http://blogs.msdn.com/b/exchangedev/archive/2011/07/29/working-with-meeting-responses-in-exchange-activesync.aspx
|
||||
//
|
||||
//
|
||||
// Here is an example of a Sync call when sogo10 accepts an invitation from sogo3:
|
||||
//
|
||||
// <Change>
|
||||
// <ServerId>2978-52EA9D00-1-A253E70.ics</ServerId>
|
||||
// <ApplicationData>
|
||||
// <TimeZone xmlns="Calendar:">LAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAAAAxP///w==</TimeZone>
|
||||
// <AllDayEvent xmlns="Calendar:">0</AllDayEvent>
|
||||
// <StartTime xmlns="Calendar:">20140207T130000Z</StartTime>
|
||||
// <EndTime xmlns="Calendar:">20140207T140000Z</EndTime>
|
||||
// <DTStamp xmlns="Calendar:">20140130T185245Z</DTStamp>
|
||||
// <Subject xmlns="Calendar:">test 8</Subject>
|
||||
// <Sensitivity xmlns="Calendar:">0</Sensitivity>
|
||||
// <Body xmlns="AirSyncBase:">
|
||||
// <Type>1</Type>
|
||||
// <Data/>
|
||||
// </Body>
|
||||
// <Organizer_Email xmlns="Calendar:">sogo3@example.com</Organizer_Email>
|
||||
// <UID xmlns="Calendar:">2978-52EA9D00-1-A253E70</UID>
|
||||
// <Attendees xmlns="Calendar:">
|
||||
// <Attendee>
|
||||
// <Attendee_Name>sogo10</Attendee_Name>
|
||||
// <Attendee_Email>sogo10@example.com</Attendee_Email>
|
||||
// <Attendee_Type>1</Attendee_Type>
|
||||
// </Attendee>
|
||||
// </Attendees>
|
||||
// <BusyStatus xmlns="Calendar:">2</BusyStatus>
|
||||
// <MeetingStatus xmlns="Calendar:">3</MeetingStatus>
|
||||
// <Organizer_Name xmlns="Calendar:">Wolfgang Fritz</Organizer_Name>
|
||||
// </ApplicationData>
|
||||
// </Change>
|
||||
//
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) context
|
||||
{
|
||||
iCalDateTime *start, *end;
|
||||
NSTimeZone *userTimeZone;
|
||||
iCalTimeZone *tz;
|
||||
id o;
|
||||
|
||||
NSInteger tzOffset;
|
||||
BOOL isAllDay;
|
||||
|
||||
if ((o = [theValues objectForKey: @"UID"]))
|
||||
[self setUid: o];
|
||||
|
||||
// FIXME: merge with iCalToDo
|
||||
if ((o = [theValues objectForKey: @"Subject"]))
|
||||
[self setSummary: o];
|
||||
|
||||
isAllDay = NO;
|
||||
if ([[theValues objectForKey: @"AllDayEvent"] intValue])
|
||||
{
|
||||
isAllDay = YES;
|
||||
}
|
||||
|
||||
//
|
||||
// 0- free, 1- tentative, 2- busy and 3- out of office
|
||||
//
|
||||
if ((o = [theValues objectForKey: @"BusyStatus"]))
|
||||
{
|
||||
[o intValue];
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
if ((o = [theValues objectForKey: @"MeetingStatus"]))
|
||||
{
|
||||
[o intValue];
|
||||
}
|
||||
|
||||
//
|
||||
// 0- normal, 1- personal, 2- private and 3-confidential
|
||||
//
|
||||
if ((o = [theValues objectForKey: @"Sensitivy"]))
|
||||
{
|
||||
switch ([o intValue])
|
||||
{
|
||||
case 2:
|
||||
[self setAccessClass: @"PRIVATE"];
|
||||
break;
|
||||
case 3:
|
||||
[self setAccessClass: @"CONFIDENTIAL"];
|
||||
break;
|
||||
case 0:
|
||||
case 1:
|
||||
default:
|
||||
[self setAccessClass: @"PUBLIC"];
|
||||
}
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"TimeZone"]))
|
||||
{
|
||||
// Ugh, we ignore it for now.
|
||||
userTimeZone = [[[context activeUser] userDefaults] timeZone];
|
||||
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
|
||||
[(iCalCalendar *) parent addTimeZone: tz];
|
||||
}
|
||||
|
||||
// FIXME: merge with iCalToDo
|
||||
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
|
||||
[self setComment: o];
|
||||
|
||||
if ((o = [theValues objectForKey: @"Location"]))
|
||||
[self setLocation: o];
|
||||
|
||||
if ((o = [theValues objectForKey: @"StartTime"]))
|
||||
{
|
||||
o = [o calendarDate];
|
||||
start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"];
|
||||
[start setTimeZone: tz];
|
||||
|
||||
if (isAllDay)
|
||||
{
|
||||
[start setDate: o];
|
||||
[start setTimeZone: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
tzOffset = [userTimeZone secondsFromGMTForDate: o];
|
||||
o = [o dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: tzOffset];
|
||||
[start setDateTime: o];
|
||||
}
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"EndTime"]))
|
||||
{
|
||||
o = [o calendarDate];
|
||||
end = (iCalDateTime *) [self uniqueChildWithTag: @"dtend"];
|
||||
[end setTimeZone: tz];
|
||||
|
||||
if (isAllDay)
|
||||
{
|
||||
[end setDate: o];
|
||||
[end setTimeZone: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
tzOffset = [userTimeZone secondsFromGMTForDate: o];
|
||||
o = [o dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: tzOffset];
|
||||
[end setDateTime: o];
|
||||
}
|
||||
}
|
||||
|
||||
// Recurrence
|
||||
if ((o = [theValues objectForKey: @"Recurrence"]))
|
||||
{
|
||||
iCalRecurrenceRule *rule;
|
||||
|
||||
rule = [[iCalRecurrenceRule alloc] init];
|
||||
[self setRecurrenceRules: [NSArray arrayWithObject: rule]];
|
||||
RELEASE(rule);
|
||||
|
||||
[rule takeActiveSyncValues: o inContext: context];
|
||||
}
|
||||
|
||||
// Organizer - we don't touch the value unless we're the organizer
|
||||
if ((o = [theValues objectForKey: @"Organizer_Email"]) &&
|
||||
([self userIsOrganizer: [context activeUser]] || [[context activeUser] hasEmail: o]))
|
||||
{
|
||||
iCalPerson *person;
|
||||
|
||||
person = [iCalPerson elementWithTag: @"organizer"];
|
||||
[person setEmail: o];
|
||||
[person setCn: [theValues objectForKey: @"Organizer_Name"]];
|
||||
[person setPartStat: @"ACCEPTED"];
|
||||
[self setOrganizer: person];
|
||||
}
|
||||
|
||||
// Attendees - we don't touch the values if we're an attendee. This is gonna
|
||||
// be done automatically by the ActiveSync client when invoking MeetingResponse.
|
||||
if (![self userIsAttendee: [context activeUser]])
|
||||
{
|
||||
if ((o = [theValues objectForKey: @"Attendees"]))
|
||||
{
|
||||
NSMutableArray *attendees;
|
||||
NSDictionary *attendee;
|
||||
iCalPerson *person;
|
||||
int status, i;
|
||||
|
||||
attendees = [NSMutableArray array];
|
||||
|
||||
for (i = 0; i < [o count]; i++)
|
||||
{
|
||||
// Each attendee has is a dictionary similar to this:
|
||||
// { "Attendee_Email" = "sogo3@example.com"; "Attendee_Name" = "Wolfgang Fritz"; "Attendee_Status" = 5; "Attendee_Type" = 1; }
|
||||
attendee = [o objectAtIndex: i];
|
||||
|
||||
person = [iCalPerson elementWithTag: @"attendee"];
|
||||
[person setCn: [attendee objectForKey: @"Attendee_Name"]];
|
||||
[person setEmail: [attendee objectForKey: @"Attendee_Email"]];
|
||||
|
||||
status = [[attendee objectForKey: @"Attendee_Status"] intValue];
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case 2:
|
||||
[person setPartStat: @"TENTATIVE"];
|
||||
break;
|
||||
case 3:
|
||||
[person setPartStat: @"ACCEPTED"];
|
||||
break;
|
||||
case 4:
|
||||
[person setPartStat: @"DECLINED"];
|
||||
break;
|
||||
case 0:
|
||||
case 5:
|
||||
default:
|
||||
[person setPartStat: @"NEEDS-ACTION"];
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: handle Attendee_Type
|
||||
|
||||
[attendees addObject: person];
|
||||
}
|
||||
|
||||
[self setAttendees: attendees];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ICALRECURRENCERULEACTIVESYNC_H__
|
||||
#define __ICALRECURRENCERULEACTIVESYNC_H__
|
||||
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
|
||||
@class NSDictionary;
|
||||
@class NSString;
|
||||
@class WOContext;
|
||||
|
||||
@interface iCalRecurrenceRule (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext:(WOContext *) context;
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) context;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#import "iCalRecurrenceRule+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGCards/iCalByDayMask.h>
|
||||
|
||||
#import "NSCalendarDate+ActiveSync.h"
|
||||
#import "NSDate+ActiveSync.h"
|
||||
|
||||
@implementation iCalRecurrenceRule (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
|
||||
{
|
||||
NSMutableString *s;
|
||||
int type;
|
||||
|
||||
s = [NSMutableString string];
|
||||
|
||||
[s appendString: @"<Recurrence xmlns=\"Calendar:\">"];
|
||||
|
||||
// 0 -> daily, 1 -> weekly, 2 -> montly, 5 -> yearly
|
||||
type = 0;
|
||||
|
||||
if ([self frequency] == iCalRecurrenceFrequenceDaily)
|
||||
{
|
||||
type = 0;
|
||||
|
||||
// 1 -> sunday, 2 -> monday, 4 -> tuesday, 8 -> wednesday, 16 -> thursday, 32 -> friday, 64 -> saturday, 127 -> last day of month (montly or yearl recurrences only)
|
||||
if ([[self byDayMask] isWeekDays])
|
||||
{
|
||||
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", (2|4|8|16|32)];
|
||||
}
|
||||
else
|
||||
{
|
||||
[s appendFormat: @"<Recurrence_Interval xmlns=\"Calendar:\">%d</Recurrence_Interval>", [self repeatInterval]];
|
||||
}
|
||||
}
|
||||
else if ([self frequency] == iCalRecurrenceFrequenceWeekly)
|
||||
{
|
||||
iCalWeekOccurrences *occurrences;
|
||||
int i, v;
|
||||
|
||||
type = 1;
|
||||
|
||||
occurrences = [[self byDayMask] weekDayOccurrences];
|
||||
v = 0;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
if (occurrences[i])
|
||||
v += (1 << i);
|
||||
}
|
||||
|
||||
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", v];
|
||||
[s appendFormat: @"<Recurrence_Interval xmlns=\"Calendar:\">%d</Recurrence_Interval>", [self repeatInterval]];
|
||||
}
|
||||
else if ([self frequency] == iCalRecurrenceFrequenceMonthly)
|
||||
{
|
||||
if ([[self byDay] length])
|
||||
{
|
||||
int firstOccurrence;
|
||||
iCalByDayMask *dm;
|
||||
|
||||
type = 3; // recurs monthly on the nth day
|
||||
dm = [self byDayMask];
|
||||
firstOccurrence = [dayMask firstOccurrence];
|
||||
|
||||
// Handle the case for "Last day of the month"
|
||||
if (firstOccurrence < 0)
|
||||
firstOccurrence = 5;
|
||||
|
||||
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", (1 << [dm firstDay])];
|
||||
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"Calendar:\">%d</Recurrence_WeekOfMonth>", firstOccurrence];
|
||||
}
|
||||
else if ([[self byMonthDay] count])
|
||||
{
|
||||
NSArray *days;
|
||||
|
||||
type = 2; // recurs monthly
|
||||
days = [self byMonthDay];
|
||||
if ([days count] > 0 && [[days objectAtIndex: 0] intValue] < 0)
|
||||
{
|
||||
// Last day of the month
|
||||
iCalByDayMask *dm;
|
||||
|
||||
dm = [self byDayMask];
|
||||
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", (1 << [dm firstDay])];
|
||||
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"Calendar:\">%d</Recurrence_WeekOfMonth>", 5];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unsupported rule in ActiveSync/Outlook. Rule that says "Repeat on the 7th and 8th of each month".
|
||||
// FIXME
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ([self frequency] == iCalRecurrenceFrequenceYearly)
|
||||
{
|
||||
type = 6; // Yearly on the nth day
|
||||
|
||||
if ([[self flattenedValuesForKey: @"bymonth"] length])
|
||||
{
|
||||
if ([[self byDay] length])
|
||||
{
|
||||
int firstOccurrence;
|
||||
iCalByDayMask *dm;
|
||||
|
||||
dm = [self byDayMask];
|
||||
firstOccurrence = [dm firstOccurrence];
|
||||
if (firstOccurrence < 0)
|
||||
firstOccurrence = 5;
|
||||
|
||||
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", (1 << [dm firstDay])];
|
||||
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"Calendar:\">%d</Recurrence_WeekOfMonth>", firstOccurrence];
|
||||
[s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"Calendar:\">%@</Recurrence_MonthOfYear>",
|
||||
[self flattenedValuesForKey: @"bymonth"]];
|
||||
}
|
||||
else
|
||||
{
|
||||
type = 5; // Yearly
|
||||
|
||||
[s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%@</Recurrence_DayOfMonth>",
|
||||
[self flattenedValuesForKey: @"bymonthday"]];
|
||||
|
||||
[s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"Calendar:\">%@</Recurrence_MonthOfYear>",
|
||||
[self flattenedValuesForKey: @"bymonth"]];
|
||||
}
|
||||
}
|
||||
else
|
||||
type = 5;
|
||||
}
|
||||
|
||||
[s appendFormat: @"<Recurrence_Type xmlns=\"Calendar:\">%d</Recurrence_Type>", type];
|
||||
|
||||
// Occurrences / Until
|
||||
//[s appendFormat: @"<Recurrence_Occurrences xmlns=\"Calendar:\">%d</Recurrence_Occurrences>", 5];
|
||||
if ([self repeatCount])
|
||||
{
|
||||
[s appendFormat: @"<Recurrence_Occurrences xmlns=\"Calendar:\">%@</Recurrence_Occurrences>",
|
||||
[self flattenedValuesForKey: @"count"]];
|
||||
}
|
||||
else if ([self untilDate])
|
||||
{
|
||||
NSCalendarDate *date;
|
||||
|
||||
date = [self untilDate];
|
||||
//ud = [[context activeUser] userDefaults];
|
||||
//[date setTimeZone: [ud timeZone]];
|
||||
|
||||
[s appendFormat: @"<Recurrence_Until xmlns=\"Calendar:\">%@</Recurrence_Until>",
|
||||
[date activeSyncRepresentationWithoutSeparatorsInContext: context]];
|
||||
}
|
||||
|
||||
|
||||
[s appendString: @"</Recurrence>"];
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) _setByDayFromValues: (NSDictionary *) theValues
|
||||
{
|
||||
NSString *day;
|
||||
id o;
|
||||
|
||||
unsigned int day_of_week;
|
||||
int i, week_of_month;
|
||||
|
||||
o = [theValues objectForKey: @"Recurrence_DayOfWeek"];
|
||||
|
||||
// The documentation says WeekOfMonth must be between 1 and 5. The value
|
||||
// 5 means "last week of month"
|
||||
week_of_month = [[theValues objectForKey: @"Recurrence_WeekOfMonth"] intValue];
|
||||
|
||||
if (week_of_month > 4)
|
||||
week_of_month = -1;
|
||||
|
||||
// We find the correct day of the week
|
||||
day_of_week = [o intValue];
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
if ((1<<i) == day_of_week)
|
||||
{
|
||||
day_of_week = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
day = [self iCalRepresentationForWeekDay: i];
|
||||
|
||||
[self setSingleValue: [NSString stringWithFormat: @"%d%@",
|
||||
week_of_month, day]
|
||||
forKey: @"byday"];
|
||||
}
|
||||
|
||||
- (void) _setByMonthFromValues: (NSDictionary *) theValues
|
||||
{
|
||||
unsigned int month_of_year;
|
||||
|
||||
month_of_year = [[theValues objectForKey: @"Recurrence_MonthOfYear"] intValue];
|
||||
|
||||
[self setSingleValue: [NSString stringWithFormat: @"%d", month_of_year]
|
||||
forKey: @"bymonth"];
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) context
|
||||
{
|
||||
id o;
|
||||
|
||||
int recurrenceType;
|
||||
|
||||
recurrenceType = [[theValues objectForKey: @"Recurrence_Type"] intValue];
|
||||
|
||||
if ((o = [theValues objectForKey: @"Recurrence_Interval"]))
|
||||
{
|
||||
[self setRepeatInterval: [o intValue]];
|
||||
}
|
||||
else
|
||||
[self setRepeatInterval: 1];
|
||||
|
||||
switch (recurrenceType)
|
||||
{
|
||||
//
|
||||
// Daily
|
||||
//
|
||||
case 0:
|
||||
[self setFrequency: iCalRecurrenceFrequenceDaily];
|
||||
|
||||
|
||||
// Every weekday
|
||||
if ((o = [theValues objectForKey: @"Recurrence_DayOfWeek"]))
|
||||
{
|
||||
[self setByDayMask: [iCalByDayMask byDayMaskWithWeekDays]];
|
||||
}
|
||||
break;
|
||||
//
|
||||
// Weekly
|
||||
//
|
||||
case 1:
|
||||
[self setFrequency: iCalRecurrenceFrequenceWeekly];
|
||||
|
||||
// 42 == Every Monday, Wednesday and Friday, for example
|
||||
if ((o = [theValues objectForKey: @"Recurrence_DayOfWeek"]))
|
||||
{
|
||||
iCalWeekOccurrences days;
|
||||
unsigned int i, v;
|
||||
|
||||
memset(days, 0, 7 * sizeof(iCalWeekOccurrence));
|
||||
v = [o intValue];
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
if (v & (1<<i))
|
||||
days[i] = iCalWeekOccurrenceAll;
|
||||
}
|
||||
|
||||
[self setByDayMask: [iCalByDayMask byDayMaskWithDays: days]];
|
||||
}
|
||||
break;
|
||||
//
|
||||
// Montly
|
||||
//
|
||||
case 2:
|
||||
case 3:
|
||||
[self setFrequency: iCalRecurrenceFrequenceMonthly];
|
||||
|
||||
// The 5th of every X month(s)
|
||||
if ((o = [theValues objectForKey: @"Recurrence_DayOfMonth"]))
|
||||
{
|
||||
[self setValues: [NSArray arrayWithObject: o]
|
||||
atIndex: 0 forKey: @"bymonthday"];
|
||||
}
|
||||
// The 3rd Thursay every X month(s)
|
||||
else if ((o = [theValues objectForKey: @"Recurrence_DayOfWeek"]))
|
||||
{
|
||||
[self _setByDayFromValues: theValues];
|
||||
}
|
||||
|
||||
break;
|
||||
//
|
||||
// Yearly
|
||||
//
|
||||
case 5:
|
||||
case 6:
|
||||
default:
|
||||
[self setFrequency: iCalRecurrenceFrequenceYearly];
|
||||
|
||||
// On April 19th
|
||||
if ((o = [theValues objectForKey: @"Recurrence_DayOfMonth"]))
|
||||
{
|
||||
[self setValues: [NSArray arrayWithObject: o] atIndex: 0
|
||||
forKey: @"bymonthday"];
|
||||
|
||||
[self _setByMonthFromValues: theValues];
|
||||
}
|
||||
else
|
||||
{
|
||||
// On the Second Wednesday of April
|
||||
[self _setByDayFromValues: theValues];
|
||||
[self _setByMonthFromValues: theValues];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"Recurrence_Occurrences"]))
|
||||
{
|
||||
[self setRepeatCount: [o intValue]];
|
||||
}
|
||||
else if ((o = [theValues objectForKey: @"Recurrence_Until"]))
|
||||
{
|
||||
[self setUntilDate: [o calendarDate]];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __ICALTIMEZONEACTIVESYNC_H__
|
||||
#define __ICALTIMEZONEACTIVESYNC_H__
|
||||
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
|
||||
@class NSString;
|
||||
@class WOContext;
|
||||
|
||||
@interface iCalTimeZone (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#import "iCalTimeZone+ActiveSync.h"
|
||||
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSCalendarDate.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSDate.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
#import <NGCards/iCalByDayMask.h>
|
||||
#import <NGCards/iCalTimeZonePeriod.h>
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
|
||||
#import <NGExtensions/NGBase64Coding.h>
|
||||
|
||||
#include "NSData+ActiveSync.h"
|
||||
|
||||
struct SYSTEMTIME {
|
||||
uint16_t wYear;
|
||||
uint16_t wMonth;
|
||||
uint16_t wDayOfWeek;
|
||||
uint16_t wDay;
|
||||
uint16_t wHour;
|
||||
uint16_t wMinute;
|
||||
uint16_t wSecond;
|
||||
uint16_t wMilliseconds;
|
||||
};
|
||||
|
||||
@interface iCalTimeZonePeriod (ActiveSync)
|
||||
|
||||
- (void) _fillTZDate: (struct SYSTEMTIME *) tzData;
|
||||
|
||||
@end
|
||||
|
||||
@implementation iCalTimeZonePeriod (ActiveSync)
|
||||
|
||||
//
|
||||
// FIXME - combine with iCalTimeZone+MAPIStore.m
|
||||
//
|
||||
- (void) _fillTZDate: (struct SYSTEMTIME *) tzData
|
||||
{
|
||||
iCalRecurrenceRule *rrule;
|
||||
NSArray *byMonth;
|
||||
iCalByDayMask *mask;
|
||||
NSCalendarDate *dateValue;
|
||||
|
||||
rrule = [self recurrenceRule];
|
||||
byMonth = [rrule byMonth];
|
||||
if ([byMonth count] > 0)
|
||||
{
|
||||
tzData->wMonth = [[byMonth objectAtIndex: 0] intValue];
|
||||
mask = [rrule byDayMask];
|
||||
tzData->wDayOfWeek = [mask firstDay];
|
||||
tzData->wDay = [mask firstOccurrence];
|
||||
|
||||
dateValue = [self startDate];
|
||||
tzData->wHour = [dateValue hourOfDay];
|
||||
tzData->wMinute = [dateValue minuteOfHour];
|
||||
tzData->wSecond = [dateValue secondOfMinute];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation iCalTimeZone (ActiveSync)
|
||||
|
||||
//
|
||||
// FIXME - combine with iCalTimeZone+MAPIStore.m
|
||||
//
|
||||
- (iCalTimeZonePeriod *) _mostRecentPeriodWithName: (NSString *) periodName
|
||||
{
|
||||
NSArray *periods;
|
||||
iCalTimeZonePeriod *period;
|
||||
NSUInteger max;
|
||||
|
||||
periods = [self childrenWithTag: periodName];
|
||||
max = [periods count];
|
||||
if (max > 0)
|
||||
{
|
||||
periods = [periods sortedArrayUsingSelector: @selector (compare:)];
|
||||
period = (iCalTimeZonePeriod *) [periods objectAtIndex: (max - 1)];
|
||||
}
|
||||
else
|
||||
period = nil;
|
||||
|
||||
return period;
|
||||
}
|
||||
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
|
||||
{
|
||||
iCalTimeZonePeriod *period;
|
||||
NSMutableData *bytes;
|
||||
|
||||
uint32_t lBias;
|
||||
uint32_t lStandardBias;
|
||||
uint32_t lDaylightBias;
|
||||
//uint16_t wStandardYear;
|
||||
struct SYSTEMTIME stStandardDate;
|
||||
//uint16_t wDaylightYear;
|
||||
struct SYSTEMTIME stDaylightDate;
|
||||
|
||||
char standardName[64], daylightName[64];
|
||||
|
||||
bytes = [NSMutableData data];
|
||||
|
||||
memset(standardName, 0, 64);
|
||||
memset(daylightName, 0, 64);
|
||||
lStandardBias = 0;
|
||||
|
||||
period = [self _mostRecentPeriodWithName: @"STANDARD"];
|
||||
lBias = -[period secondsOffsetFromGMT] / 60;
|
||||
[period _fillTZDate: &stStandardDate];
|
||||
|
||||
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
|
||||
if (!period)
|
||||
stStandardDate.wMonth = 0;
|
||||
|
||||
lDaylightBias = (uint32_t) -([period secondsOffsetFromGMT] / 60) - lBias;
|
||||
[period _fillTZDate: &stDaylightDate];
|
||||
//wStandardYear = stStandardDate.wYear;
|
||||
//wDaylightYear = stDaylightDate.wYear;
|
||||
|
||||
|
||||
// We build the timezone
|
||||
[bytes appendBytes: &lBias length: 4];
|
||||
[bytes appendBytes: standardName length: 64];
|
||||
[bytes appendBytes: &stStandardDate length: 16];
|
||||
[bytes appendBytes: &lStandardBias length: 4];
|
||||
[bytes appendBytes: daylightName length: 64];
|
||||
[bytes appendBytes: &stDaylightDate length: 16];
|
||||
[bytes appendBytes: &lDaylightBias length: 4];
|
||||
|
||||
return [bytes activeSyncRepresentationInContext: context];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef __ICALTODOACTIVESYNC_H__
|
||||
#define __ICALTODOACTIVESYNC_H__
|
||||
|
||||
#import <NGCards/iCalToDo.h>
|
||||
|
||||
@class NSString;
|
||||
@class WOContext;
|
||||
|
||||
@interface iCalToDo (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context;
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) context;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Inverse inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Inverse inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#import "iCalToDo+ActiveSync.h"
|
||||
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSDate.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGObjWeb/WOContext.h>
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserDefaults.h>
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <NGCards/iCalDateTime.h>
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
|
||||
#include "NSDate+ActiveSync.h"
|
||||
#include "NSString+ActiveSync.h"
|
||||
|
||||
@implementation iCalToDo (ActiveSync)
|
||||
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
|
||||
{
|
||||
NSMutableString *s;
|
||||
id o;
|
||||
|
||||
int v;
|
||||
|
||||
s = [NSMutableString string];
|
||||
|
||||
// Complete
|
||||
o = [self completed];
|
||||
[s appendFormat: @"<Complete xmlns=\"Tasks:\">%d</Complete>", (o ? 1 : 0)];
|
||||
|
||||
// DateCompleted
|
||||
if (o)
|
||||
[s appendFormat: @"<DateCompleted xmlns=\"Tasks:\">%@</DateCompleted>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
// Start date
|
||||
if ((o = [self startDate]))
|
||||
{
|
||||
[s appendFormat: @"<StartDate xmlns=\"Tasks:\">%@</StartDate>", [o activeSyncRepresentationInContext: context]];
|
||||
[s appendFormat: @"<UTCStartDate xmlns=\"Tasks:\">%@</UTCStartDate>", [o activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
|
||||
|
||||
// Due date
|
||||
if ((o = [self due]))
|
||||
{
|
||||
[s appendFormat: @"<DueDate xmlns=\"Tasks:\">%@</DueDate>", [o activeSyncRepresentationInContext: context]];
|
||||
[s appendFormat: @"<UTCDueDate xmlns=\"Tasks:\">%@</UTCDueDate>", [o activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
|
||||
// Importance
|
||||
o = [self priority];
|
||||
if ([o isEqualToString: @"9"])
|
||||
v = 0;
|
||||
else if ([o isEqualToString: @"1"])
|
||||
v = 2;
|
||||
else
|
||||
v = 1;
|
||||
[s appendFormat: @"<Importance xmlns=\"Tasks:\">%d</Importance>", v];
|
||||
|
||||
// Reminder - FIXME
|
||||
[s appendFormat: @"<ReminderSet xmlns=\"Tasks:\">%d</ReminderSet>", 0];
|
||||
|
||||
// Sensitivity - FIXME
|
||||
[s appendFormat: @"<Sensitivity xmlns=\"Tasks:\">%d</Sensitivity>", 0];
|
||||
|
||||
// Subject
|
||||
o = [self summary];
|
||||
if ([o length])
|
||||
[s appendFormat: @"<Subject xmlns=\"Tasks:\">%@</Subject>", [[self summary] activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [self comment]))
|
||||
{
|
||||
o = [o activeSyncRepresentationInContext: context];
|
||||
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
|
||||
[s appendFormat: @"<Type>%d</Type>", 1];
|
||||
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
|
||||
[s appendFormat: @"<Truncated>%d</Truncated>", 0];
|
||||
[s appendFormat: @"<Data>%@</Data>", o];
|
||||
[s appendString: @"</Body>"];
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
||||
inContext: (WOContext *) context
|
||||
{
|
||||
NSTimeZone *userTimeZone;
|
||||
iCalTimeZone *tz;
|
||||
id o;
|
||||
|
||||
NSInteger tzOffset;
|
||||
|
||||
userTimeZone = [[[context activeUser] userDefaults] timeZone];
|
||||
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
|
||||
[(iCalCalendar *) parent addTimeZone: tz];
|
||||
|
||||
// FIXME: merge with iCalEvent
|
||||
if ((o = [theValues objectForKey: @"Subject"]))
|
||||
[self setSummary: o];
|
||||
|
||||
// FIXME: merge with iCalEvent
|
||||
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
|
||||
[self setComment: o];
|
||||
|
||||
|
||||
if ([[theValues objectForKey: @"Complete"] intValue] &&
|
||||
((o = [theValues objectForKey: @"DateCompleted"])) )
|
||||
{
|
||||
iCalDateTime *completed;
|
||||
|
||||
o = [o calendarDate];
|
||||
completed = (iCalDateTime *) [self uniqueChildWithTag: @"completed"];
|
||||
//tzOffset = [[o timeZone] secondsFromGMTForDate: o];
|
||||
//o = [o dateByAddingYears: 0 months: 0 days: 0
|
||||
// hours: 0 minutes: 0
|
||||
// seconds: -tzOffset];
|
||||
[completed setDate: o];
|
||||
[self setStatus: @"COMPLETED"];
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"DueDate"]))
|
||||
{
|
||||
iCalDateTime *due;
|
||||
|
||||
|
||||
o = [o calendarDate];
|
||||
due = (iCalDateTime *) [self uniqueChildWithTag: @"due"];
|
||||
[due setTimeZone: tz];
|
||||
|
||||
tzOffset = [userTimeZone secondsFromGMTForDate: o];
|
||||
o = [o dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: tzOffset];
|
||||
[due setDateTime: o];
|
||||
}
|
||||
|
||||
// 2 == high, 1 == normal, 0 == low
|
||||
if ((o = [theValues objectForKey: @"Importance"]))
|
||||
{
|
||||
if ([o intValue] == 2)
|
||||
[self setPriority: @"1"];
|
||||
else if ([o intValue] == 1)
|
||||
[self setPriority: @"5"];
|
||||
else
|
||||
[self setPriority: @"9"];
|
||||
}
|
||||
|
||||
|
||||
if ((o = [theValues objectForKey: @"ReminderTime"]))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
requires = ( MAIN, Appointments, Contacts, Mailer );
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#
|
||||
#
|
||||
# Keep only one of those vhost definition, comment out the other one
|
||||
#
|
||||
#
|
||||
|
||||
# for https
|
||||
# don't forget to add a Listen parameter for port 8843:
|
||||
# Listen 8843
|
||||
<VirtualHost *:8843>
|
||||
ServerName YOUR.SERVER.NAME
|
||||
|
||||
SSLEngine on
|
||||
|
||||
SSLProtocol -ALL +SSLv3 +TLSv1
|
||||
SSLHonorCipherOrder On
|
||||
SSLCipherSuite HIGH:MEDIUM:!ADH:!aNULL:!eNULL:!NULL
|
||||
SSLCertificateFile /path/to/your/cert/cert.pem
|
||||
SSLCertificateChainFile /path/to/your/cert/cert-chain-file.pem
|
||||
SSLCertificateKeyFile /path/to/your/key/file.key
|
||||
|
||||
RewriteEngine Off
|
||||
ProxyRequests Off
|
||||
SetEnv proxy-nokeepalive 1
|
||||
ProxyPreserveHost On
|
||||
ProxyPassInterpolateEnv On
|
||||
ProxyPass /principals http://127.0.0.1:20000/SOGo/dav/ interpolate
|
||||
ProxyPass /SOGo http://127.0.0.1:20000/SOGo interpolate
|
||||
ProxyPass / http://127.0.0.1:20000/SOGo/dav/ interpolate
|
||||
<Location />
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Location>
|
||||
|
||||
<Proxy http://127.0.0.1:20000>
|
||||
RequestHeader set "x-webobjects-server-port" "8843"
|
||||
RequestHeader set "x-webobjects-server-name" "CHANGETHIS:8843"
|
||||
RequestHeader set "x-webobjects-server-url" "http://CHANGETHIS:8843"
|
||||
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
|
||||
AddDefaultCharset UTF-8
|
||||
</Proxy>
|
||||
|
||||
ErrorLog /var/log/apache2/ab-error.log
|
||||
CustomLog /var/log/apache2/ab-access.log combined
|
||||
</VirtualHost>
|
||||
|
||||
# plain http
|
||||
# Same here, don't forget to add a Listen parameter for port 8800:
|
||||
# Listen 8800
|
||||
<VirtualHost *:8800>
|
||||
RewriteEngine Off
|
||||
ProxyRequests Off
|
||||
SetEnv proxy-nokeepalive 1
|
||||
ProxyPreserveHost On
|
||||
ProxyPassInterpolateEnv On
|
||||
ProxyPass /principals http://127.0.0.1:20000/SOGo/dav/ interpolate
|
||||
ProxyPass /SOGo http://127.0.0.1:20000/SOGo interpolate
|
||||
ProxyPass / http://127.0.0.1:20000/SOGo/dav/ interpolate
|
||||
<Location />
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Location>
|
||||
|
||||
<Proxy http://127.0.0.1:20000>
|
||||
RequestHeader set "x-webobjects-server-port" "8800"
|
||||
RequestHeader set "x-webobjects-server-name" "changethis:8800"
|
||||
RequestHeader set "x-webobjects-server-url" "http://changethis:8800"
|
||||
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
|
||||
AddDefaultCharset UTF-8
|
||||
</Proxy>
|
||||
|
||||
ErrorLog /var/log/apache2/ab-error.log
|
||||
CustomLog /var/log/apache2/ab-access.log combined
|
||||
</VirtualHost>
|
||||
+14
-12
@@ -2,8 +2,6 @@ Alias /SOGo.woa/WebServerResources/ \
|
||||
/usr/lib/GNUstep/SOGo/WebServerResources/
|
||||
Alias /SOGo/WebServerResources/ \
|
||||
/usr/lib/GNUstep/SOGo/WebServerResources/
|
||||
AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \
|
||||
/usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2
|
||||
|
||||
<Directory /usr/lib/GNUstep/SOGo/>
|
||||
AllowOverride None
|
||||
@@ -18,10 +16,6 @@ AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \
|
||||
</IfModule>
|
||||
</Directory>
|
||||
|
||||
<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*\.(jpg|png|gif|css|js)">
|
||||
SetHandler default-handler
|
||||
</LocationMatch>
|
||||
|
||||
## Uncomment the following to enable proxy-side authentication, you will then
|
||||
## need to set the "SOGoTrustProxyAuthentication" SOGo user default to YES and
|
||||
## adjust the "x-webobjects-remote-user" proxy header in the "Proxy" section
|
||||
@@ -48,6 +42,14 @@ ProxyPreserveHost On
|
||||
|
||||
ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
|
||||
|
||||
# Enable to use Microsoft ActiveSync support
|
||||
# Note that you MUST have many sogod workers to use ActiveSync.
|
||||
# See the SOGo Installation and Configuration guide for more details.
|
||||
#
|
||||
#ProxyPass /Microsoft-Server-ActiveSync \
|
||||
# http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync \
|
||||
# retry=60 connectiontimeout=5 timeout=360
|
||||
|
||||
<Proxy http://127.0.0.1:20000/SOGo>
|
||||
## adjust the following to your configuration
|
||||
RequestHeader set "x-webobjects-server-port" "443"
|
||||
@@ -59,7 +61,6 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
|
||||
# RequestHeader set "x-webobjects-remote-user" "%{REMOTE_USER}e"
|
||||
|
||||
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
|
||||
RequestHeader set "x-webobjects-remote-host" %{REMOTE_HOST}e env=REMOTE_HOST
|
||||
|
||||
AddDefaultCharset UTF-8
|
||||
|
||||
@@ -67,8 +68,9 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
|
||||
Allow from all
|
||||
</Proxy>
|
||||
|
||||
## We use mod_rewrite to pass remote address to the SOGo proxy.
|
||||
# The remote address will appear in SOGo's log files and in the X-Forward
|
||||
# header of emails.
|
||||
RewriteEngine On
|
||||
RewriteRule ^/SOGo/(.*)$ /SOGo/$1 [env=REMOTE_HOST:%{REMOTE_ADDR},PT]
|
||||
# For Apple autoconfiguration
|
||||
<IfModule rewrite_module>
|
||||
RewriteEngine On
|
||||
RewriteRule ^/.well-known/caldav/?$ /SOGo/dav [R=301]
|
||||
</IfModule>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 433 KiB After Width: | Height: | Size: 401 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 768 KiB After Width: | Height: | Size: 311 KiB |
+1
-3
@@ -1,8 +1,6 @@
|
||||
/* SOGo+DAV.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2010 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
* Copyright (C) 2010-2013 Inverse inc.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2005-2011 Inverse inc.
|
||||
Copyright (C) 2005-2014 Inverse inc.
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOGo
|
||||
|
||||
@@ -1,3 +1,324 @@
|
||||
2.2.1 (2014-03-07)
|
||||
------------------
|
||||
|
||||
Enhancements
|
||||
- updated Czech, Dutch, Finnish, and Hungarian translations
|
||||
- show current folder name in prompt dialog when renaming a mail folder
|
||||
|
||||
Bug fixes
|
||||
- fixed an issue with ActiveSync when the number of messages in the mailbox was greater than the window-size specified by the client
|
||||
- fixed sogo-tool operations on Sieve script (#2617)
|
||||
- fixed unsubscription when renaming an IMAP folder (#2630)
|
||||
- fixed sorting of events list by calendar name (#2629)
|
||||
- fixed wrong date format leading to Android email syncing issues (#2609)
|
||||
- fixed possible exception when retrieving the default event reminder value (#2624)
|
||||
- fixed encoding of mail folder name when creating a subfolder (#2637)
|
||||
- fixed returned date format for email messages in Active Sync
|
||||
- fixed missing 'name part' in address for email messages in Active Sync
|
||||
- fixed race condition when syncing huge amount of deleted messages over Active Sync
|
||||
- fixed encoding of string as CSS identifier when the string starts with a digit
|
||||
- fixed auto-completion popupmenu when UID is a digit
|
||||
|
||||
2.2.0 (2014-02-24)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- initial implementation of Microsoft ActiveSync protocol
|
||||
- it's now possible to set a default reminder for calendar components
|
||||
using SOGoCalendarDefaultReminder
|
||||
- select multiple files to attach to a message or drag'n'drop files onto the
|
||||
mail editor; will also now display progress of uploads
|
||||
- new popup menu to download all attachments of a mail
|
||||
- move & copy messages between different accounts
|
||||
- support for the Sieve 'body' extension (mail filter based on the body content)
|
||||
|
||||
Enhancements
|
||||
- we now automatically convert <img src=data...> into file attachments
|
||||
using CIDs to prevent Outlook issues
|
||||
- updated French, Finnish, Polish, German, Russian, and Spanish (Spain) translations
|
||||
- XMLHttpRequest.js is now loaded conditionaly (< IE9)
|
||||
- format time in attendees invitation window according to the user's locale
|
||||
- improved IE11 support
|
||||
- respect signature placement when forwarding a message
|
||||
- respect Sieve server capabilities
|
||||
- encode messages in quoted-printable when content is bigger than 72 bytes
|
||||
- we now use binary encoding in memcached (#2587)
|
||||
- warn user when overbooking a resource by creating an event in its calendar (#2541)
|
||||
- converted JavaScript alerts to inline CSS dialogs in appointment editor
|
||||
- visually identify users with no freebusy information in autocompletion widget of attendees editor (#2565)
|
||||
- respect occurences of recurrent events when deleting selected events (#1950)
|
||||
- improved confirmation dialog box when deleting events and tasks
|
||||
- moved the DN cache to SOGoCache - avoiding sogod restarts after RDN operations
|
||||
- don't use the HTML editor with Internet Explorer 7
|
||||
- add message-id header to appointment notifications (#2535)
|
||||
- detect URLs in popup of events
|
||||
- improved display of a contact (#2350)
|
||||
|
||||
Bug fixes
|
||||
- don't load 'background' attribute (#2437)
|
||||
- fixed validation of subscribed folders (#2583)
|
||||
- fixed display of folder names in messages filter editor (#2569)
|
||||
- fixed contextual menu of the current calendar view (#2557)
|
||||
- fixed handling of the '=' character in cards/events/tasks (#2505)
|
||||
- simplify searches in the address book (#2187)
|
||||
- warn user when dnd failed because of a resource conflict (#1613)
|
||||
- respect the maximum number of bookings when viewing the freebusy information of a resource (#2560)
|
||||
- encode HTML entities when forwarding an HTML message inline in plain text composition mode (#2411)
|
||||
- encode HTML entities in JSON data (#2598)
|
||||
- fixed handling of ACLs on shared calendars with multiple groups (#1854)
|
||||
- fixed HTML formatting of appointment notifications for Outlook (#2233)
|
||||
- replace slashes by dashes in filenames of attachments to avoid a 404 return code (#2537)
|
||||
- avoid over-using LDAP connections when decomposing groups
|
||||
- fixed display of a contact's birthday when not defined (#2503)
|
||||
- fixed JavaScript error when switching views in calendar module (#2613)
|
||||
|
||||
2.1.1b (2013-12-04)
|
||||
-------------------
|
||||
|
||||
Enhancements
|
||||
- updated CKEditor to version 4.3.0 and added tab module
|
||||
|
||||
Bug fixes
|
||||
- HTML formatting is now retained when forwarding/replying to a mail using the HTML editor
|
||||
- put the text part before the HTML part when composing mail to fix a display issue with Thunderbird (#2512)
|
||||
|
||||
2.1.1a (2013-11-22)
|
||||
-------------------
|
||||
|
||||
Bug fixes
|
||||
- fixed Sieve filters editor (#2504)
|
||||
- moved missing translation to UI/Common (#2499)
|
||||
- fixed potential crasher in OpenChange
|
||||
|
||||
2.1.1 (2013-11-19)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- creation and modification of mail labels
|
||||
|
||||
Enhancements
|
||||
- the color picker is no longer a popup window
|
||||
|
||||
Bug fixes
|
||||
- fixed utf8 character handling in special folder names
|
||||
Special folder names can now be set as UTF8 or modified UTF7 in sogo.conf
|
||||
- fixed reply-to header not being set for auxiliary IMAP accounts
|
||||
- fixed handling of broken/invalid email addresses
|
||||
|
||||
2.1.0 (2013-11-07)
|
||||
------------------
|
||||
|
||||
Enhancements
|
||||
- improved order of user rights in calendar module (#1431)
|
||||
- increased height of alarm editor when email alarms are enabled
|
||||
- added SMTP AUTH support for sogo-ealarms-notify
|
||||
- added support for LDAP password change against AD/Samba4
|
||||
- added Apache configuration for Apple autoconfiguration (#2248)
|
||||
- the init scripts now start 3 sogod processes by default instead of 1
|
||||
- SOGo now also sends a plain/text parts when sending HTML mails (#2217)
|
||||
- SOGo now listens on 127.0.0.1:20000 by default (instead of *:20000)
|
||||
- SOGo new uses the latest WebDAV sync response type (#1275)
|
||||
- updated CKEditor to version 4.2.2 and added the tables-related modules (#2410)
|
||||
- improved display of vEvents in messages
|
||||
|
||||
Bug fixes
|
||||
- fixed handling of an incomplete attachment filename (#2385)
|
||||
- fixed Finnish mail reply/forward templates (#2401)
|
||||
- fixed position of red line of current time (#2373)
|
||||
- fixed crontab error (#2372)
|
||||
- avoid using too many LDAP connections while looping through LDAP results
|
||||
- don't encode HTML entities in mail subject of notification (#2402)
|
||||
- fixed crash of Samba when sending an invitation (#2398)
|
||||
- fixed selection of destination calendar when saving a task or an event (#2353)
|
||||
- fixed "display remote images" preference for message in a popup (#2417)
|
||||
- avoid crash when handling malformed or non-ASCII HTTP credentials (#2358)
|
||||
- fixed crash in DAV free-busy lookups when using SQL addressbooks (#2418)
|
||||
- disabled verbose logging of SMTP sessions by default
|
||||
- fixed high CPU usage when there are no available child processes and added logging when such a condition occurs
|
||||
- fixed memory consumption issues when doing dav lookups with huge result set
|
||||
- fixed S/MIME verification issues with certain OpenSSL versions
|
||||
- worked around an issue with chunked encoding of CAS replies (#2408)
|
||||
- fixed OpenChange corruption issue regarding predecessors change list (#2405)
|
||||
- avoid unnecessary UTF-7 conversions (#2318)
|
||||
- improved RTF parser to fix vCards (#2354)
|
||||
- fixed definition of the COMPLETED attribute of vTODO (#2240)
|
||||
- fixed DAV:resource-id property when sharing calendars (#2399)
|
||||
- fixed reload of multiple external web calendars (#2221)
|
||||
- fixed display of PDF files sent from Thunderbird (#2270)
|
||||
- fixed TLS support for IMAP (#2386)
|
||||
- fixed creation of web calendar when added using sogo-tool (#2007)
|
||||
- avoid crash when parsing HTML tags of a message (#2434)
|
||||
- fixed handling of LDAP groups with no email address (#1328)
|
||||
- fixed encoding of messages with non-ASCII characters (#2459)
|
||||
- fixed compilation with clang 3.2 (#2235)
|
||||
- truncated long fields of quick records to avoid an SQL error (#2461)
|
||||
- fixed IMAP ACLs (#2433)
|
||||
- removed inline JavaScript when viewing HTML messages (#2468)
|
||||
|
||||
2.0.7 (2013-07-19)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- print gridlines of calendar in 15-minute intervals
|
||||
- allow the events/tasks lists to be collapsable
|
||||
|
||||
Enhancements
|
||||
- bubble box of events no longer overlaps the current event
|
||||
- now pass the x-originating-ip using the IMAP ID extension (#2366)
|
||||
- updated BrazilianPortuguese, Czech, Dutch, German, Polish and Russian translations
|
||||
|
||||
Bug fixes
|
||||
- properly handle RFC2231 everywhere
|
||||
- fixed minor XSS issues
|
||||
- fixed jquery-ui not bluring the active element when clicking on a draggable
|
||||
|
||||
2.0.6b (2013-06-27)
|
||||
------------------
|
||||
|
||||
Bug fixes
|
||||
- properly escape the foldername to avoid XSS issues
|
||||
- fixed loading of MSExchangeFreeBusySOAPResponseMap
|
||||
|
||||
2.0.6a (2013-06-25)
|
||||
------------------
|
||||
|
||||
Bug fixes
|
||||
- documentation fixes
|
||||
- added missing file for CAS single logout
|
||||
|
||||
2.0.6 (2013-06-21)
|
||||
------------------
|
||||
|
||||
Enhancements
|
||||
- updated CKEditor to version 4.1.1 (#2333)
|
||||
- new failed login attemps rate-limiting options. See the new
|
||||
SOGoMaximumFailedLoginCount, SOGoMaximumFailedLoginInterval and
|
||||
SOGoFailedLoginBlockInterval defaults
|
||||
- new message submissions rate-limiting options. See the new
|
||||
SOGoMaximumMessageSubmissionCount, SOGoMaximumRecipientCount,
|
||||
SOGoMaximumSubmissionInterval and SOGoMessageSubmissionBlockInterval defaults
|
||||
- now possible to send or not event notifications on a per-event basis
|
||||
- now possible to see who created an event/task in a delegated calendar
|
||||
- multi-domain support in OpenChange (implemented using a trick)
|
||||
|
||||
Bug fixes
|
||||
- fixed decoding of the charset parameter when using single quotes (#2306)
|
||||
- fixed potential crash when sending MDN from Sent folder (#2209)
|
||||
- fixed handling of unicode separators (#2309)
|
||||
- fixed public access when SOGoTrustProxyAuthentication is used (#2237)
|
||||
- fixed access right issues with import feature (#2294)
|
||||
- fixed IMAP ACL issue when SOGoForceExternalLoginWithEmail is used (#2313)
|
||||
- fixed handling of CAS logoutRequest (#2346)
|
||||
- fixed many major OpenChange stability issues
|
||||
|
||||
2.0.5a (2013-04-17)
|
||||
------------------
|
||||
|
||||
Bug fixes
|
||||
- fixed an issue when parsing user CN with leading or trailing spaces (#2287)
|
||||
- fixed a crash that occured when saving contacts or tasks via Outlook
|
||||
|
||||
2.0.5 (2013-04-11)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- new system default SOGoEncryptionKey to be used to encrypt the passwords of
|
||||
remote Web calendars when SOGoTrustProxyAuthentication is enabled
|
||||
- activated the menu option "Mark Folder Read" in the Webmail (#1473)
|
||||
|
||||
Enhancements
|
||||
- added logging of the X-Forwarded-For HTTP header (#2229)
|
||||
- now use BSON instead of GNUstep's binary format for serializing
|
||||
Outlook related cache files
|
||||
- updated Danish, Finnish, Polish and Slovak translations
|
||||
- added Arabic translation - thanks to Anass Ahmed
|
||||
|
||||
Bug fixes
|
||||
- don't use the cache for password lookups from login page (#2169)
|
||||
- fixed issue with exceptions in repeating events
|
||||
- avoid data truncation issue in OpenChange with mysql backend
|
||||
run sql-update-2.0.4b_to_2.0.5-mysql.sh to update existing tables
|
||||
- avoid random crashes in OpenChange due to RTF conversion
|
||||
- fixed issue when modifying/deleting exceptions of recurring events
|
||||
- fixed major cache miss issue leading to slow Outlook resynchronizations
|
||||
- fixed major memory corruption issue when Outlook was saving "messages"
|
||||
- fixed filtering of sql contact entries when using dynamic domains (#2269)
|
||||
- sogo.conf can now be used by all tools (#2226)
|
||||
- SOPE: fixed handling of sieve capabilities after starttls (#2132)
|
||||
- OpenChange: fixed 'stuck email' problem when sending a mail
|
||||
- OpenChange NTLMAuthHandler: avoid tightloop when samba isn't available.
|
||||
- OpenChange NTLMAuthHandler: avoid crash while parsing cookies
|
||||
- OpenChange ocsmanager: a LOT of fixes, see git log
|
||||
|
||||
|
||||
2.0.4b (2013-02-04)
|
||||
------------------
|
||||
|
||||
Bug fixes
|
||||
- Fixed order of precedence for options (#2166)
|
||||
The following order is enforced - first match wins
|
||||
1. Command line arguments
|
||||
2. .GNUstepDefaults
|
||||
3. /etc/sogo/{debconf,sogo}.conf
|
||||
4. SOGoDefaults.plist
|
||||
- fixed handling of LDAP DN containing special characters (#2152, #2207)
|
||||
- fixed handling of credential files for older GNUsteps (#2216)
|
||||
- fixed display of messages with control characters (#2079, #2177)
|
||||
- fixed tooltips in contacts list (#2211)
|
||||
- fixed classification menu in component editor (#2223)
|
||||
- fixed link to ACL editor for 'any authenticated user' (#2222, #2224)
|
||||
- fixed saving preferences when mail module is disabled
|
||||
- fixed handling for long credential strings (#2212)
|
||||
|
||||
2.0.4a (2013-01-30)
|
||||
------------------
|
||||
|
||||
Enhancements
|
||||
- updated Czech translation
|
||||
- birthday is now properly formatted in addressbook module
|
||||
|
||||
Bug fixes
|
||||
- fixed handling of groups with spaces in their UID
|
||||
- fixed possible infinite loop in repeatable object
|
||||
- fixed until date in component editor
|
||||
- fixed saving all-day event in appointment editor
|
||||
- fixed handling of decoding contacts UID
|
||||
- fixed support of GNUstep 1.20 / Debian Squeeze
|
||||
|
||||
2.0.4 (2013-01-25)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- sogo-tool: new "dump-defaults" command to easily create /etc/sogo/sogo.conf
|
||||
|
||||
Enhancements
|
||||
- The sogo user is now a system user.
|
||||
For new installs, this means that 'su - sogo' won't work anymore.
|
||||
Please use 'sudo -u sogo cmd' instead
|
||||
If used in scripts from cronjobs, 'requiretty' must be disabled in sudoers
|
||||
- added basic support for LDAP URL in user sources
|
||||
- renamed default SOGoForceIMAPLoginWithEmail to
|
||||
SOGoForceExternalLoginWithEmail and extended it to SMTP authentication
|
||||
- updated the timezone files to the 2012j edition and removed RRDATES
|
||||
- updated CKEditor to version 4.0.1
|
||||
- added Finnish translation - thanks to Kari Salmu
|
||||
- updated translations
|
||||
- recurrence-id of all-day events is now set as a proper date with no time
|
||||
- 'show completed tasks' is now persistent
|
||||
- fixed memory usage consumption for remote ICS subscriptions
|
||||
|
||||
Bug fixes
|
||||
- fixed usage of browser's language for the login page
|
||||
- fixed partstat of attendee in her/his calendar
|
||||
- fixed French templates encoding
|
||||
- fixed CardDAV collections for OS X
|
||||
- fixed event recurrence editor (until date)
|
||||
- fixed column display for subfolders of draft & sent
|
||||
- improved IE7 support
|
||||
- fixed drag'n'drop of events with Safari
|
||||
- fixed first day of the week in datepickers
|
||||
- fixed exceptions of recurring all-day events
|
||||
|
||||
2.0.3 (2012-12-06)
|
||||
------------------
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
},
|
||||
{
|
||||
columnName = c_participants;
|
||||
sqlType = "VARCHAR(1000000)";
|
||||
sqlType = "TEXT";
|
||||
allowsNull = YES;
|
||||
},
|
||||
{
|
||||
@@ -91,7 +91,7 @@
|
||||
},
|
||||
{
|
||||
columnName = c_cycleinfo;
|
||||
sqlType = "VARCHAR(1000000)";
|
||||
sqlType = "TEXT";
|
||||
allowsNull = YES;
|
||||
},
|
||||
{
|
||||
@@ -126,7 +126,7 @@
|
||||
},
|
||||
{
|
||||
columnName = c_partmails;
|
||||
sqlType = "VARCHAR(100000)";
|
||||
sqlType = "TEXT";
|
||||
allowsNull = YES;
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// BSONCodec.h
|
||||
// BSON Codec for Objective-C.
|
||||
//
|
||||
// Created by Martin Kou on 8/17/10.
|
||||
// MIT License, see LICENSE file for details.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <stdint.h>
|
||||
|
||||
@protocol BSONCoding
|
||||
- (uint8_t) BSONTypeID;
|
||||
- (NSData *) BSONEncode;
|
||||
- (NSData *) BSONRepresentation;
|
||||
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID;
|
||||
@end
|
||||
|
||||
@protocol BSONObjectCoding
|
||||
- (id) initWithBSONDictionary: (NSDictionary *) data;
|
||||
- (NSDictionary *) BSONDictionary;
|
||||
@end
|
||||
|
||||
@interface NSObject (BSONObjectCoding)
|
||||
- (NSData *) BSONEncode;
|
||||
- (NSData *) BSONRepresentation;
|
||||
@end
|
||||
|
||||
|
||||
@interface NSDictionary (BSON) <BSONCoding>
|
||||
@end
|
||||
|
||||
@interface NSData (BSON) <BSONCoding>
|
||||
- (NSDictionary *) BSONValue;
|
||||
@end
|
||||
|
||||
@interface NSNumber (BSON) <BSONCoding>
|
||||
@end
|
||||
|
||||
@interface NSString (BSON) <BSONCoding>
|
||||
@end
|
||||
|
||||
@interface NSArray (BSON) <BSONCoding>
|
||||
@end
|
||||
|
||||
@interface NSNull (BSON) <BSONCoding>
|
||||
@end
|
||||
|
||||
@interface NSCalendarDate (BSON) <BSONCoding>
|
||||
@end
|
||||
@@ -0,0 +1,589 @@
|
||||
//
|
||||
// BSONCodec.m
|
||||
// BSON Codec for Objective-C.
|
||||
//
|
||||
// Created by Martin Kou on 8/17/10.
|
||||
// MIT License, see LICENSE file for details.
|
||||
//
|
||||
|
||||
#import "BSONCodec.h"
|
||||
#import <ctype.h>
|
||||
#import <string.h>
|
||||
#import <objc/objc.h>
|
||||
|
||||
#define BSONTYPE(tag,className) [className class], [NSNumber numberWithChar: (tag)]
|
||||
|
||||
#ifndef objc_msgSend
|
||||
#define objc_msgSend(obj, sel, ...) \
|
||||
objc_msg_lookup(obj, sel)(obj, sel, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
static NSDictionary *BSONTypes()
|
||||
{
|
||||
static NSDictionary *retval = nil;
|
||||
|
||||
if (retval == nil)
|
||||
{
|
||||
retval = [[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
BSONTYPE(0x01, NSNumber),
|
||||
BSONTYPE(0x02, NSString),
|
||||
BSONTYPE(0x03, NSDictionary),
|
||||
BSONTYPE(0x04, NSArray),
|
||||
BSONTYPE(0x05, NSData),
|
||||
BSONTYPE(0x08, NSNumber),
|
||||
BSONTYPE(0x0A, NSNull),
|
||||
BSONTYPE(0x10, NSNumber),
|
||||
BSONTYPE(0x11, NSCalendarDate),
|
||||
BSONTYPE(0x12, NSNumber),
|
||||
nil] retain];
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define SWAP16(x) \
|
||||
((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | \
|
||||
(((uint16_t)(x) & 0x00ff) << 8)))
|
||||
|
||||
#define SWAP32(x) \
|
||||
((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | \
|
||||
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
|
||||
(((uint32_t)(x) & 0x0000ff00) << 8) | \
|
||||
(((uint32_t)(x) & 0x000000ff) << 24)))
|
||||
|
||||
#define SWAP64(x) \
|
||||
((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
|
||||
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
|
||||
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
|
||||
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
|
||||
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
|
||||
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
|
||||
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
|
||||
(((uint64_t)(x) & 0x00000000000000ffULL) << 56)))
|
||||
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define BSONTOHOST16(x) (x)
|
||||
#define BSONTOHOST32(x) (x)
|
||||
#define BSONTOHOST64(x) (x)
|
||||
#define HOSTTOBSON16(x) (x)
|
||||
#define HOSTTOBSON32(x) (x)
|
||||
#define HOSTTOBSON64(x) (x)
|
||||
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#define BSONTOHOST16(x) SWAP16(x)
|
||||
#define BSONTOHOST32(x) SWAP32(x)
|
||||
#define BSONTOHOST64(x) SWAP64(x)
|
||||
#define HOSTTOBSON16(x) SWAP16(x)
|
||||
#define HOSTTOBSON32(x) SWAP16(x)
|
||||
#define HOSTTOBSON64(x) SWAP16(x)
|
||||
|
||||
#endif
|
||||
|
||||
#define CLASS_NAME_MARKER @"$$__CLASS_NAME__$$"
|
||||
|
||||
@implementation NSObject (BSONObjectCoding)
|
||||
- (NSData *) BSONEncode
|
||||
{
|
||||
if (![self conformsToProtocol: @protocol(BSONObjectCoding)])
|
||||
[NSException raise: NSInvalidArgumentException format: @"BSON encoding is only valid on objects conforming to the BSONObjectEncoding protocol."];
|
||||
|
||||
id <BSONObjectCoding> myself = (id <BSONObjectCoding>) self;
|
||||
NSMutableDictionary *values = [[myself BSONDictionary] mutableCopy];
|
||||
|
||||
#if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__)
|
||||
const char* className = class_getName([self class]);
|
||||
#else
|
||||
const char* className = [self class]->name;
|
||||
#endif
|
||||
[values setObject: [NSData dataWithBytes: (void *)className length: strlen(className)] forKey: CLASS_NAME_MARKER];
|
||||
NSData *retval = [values BSONEncode];
|
||||
[values release];
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
- (NSData *) BSONRepresentation
|
||||
{
|
||||
return [self BSONEncode];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSDictionary (BSON)
|
||||
|
||||
- (uint8_t) BSONTypeID
|
||||
{
|
||||
return 0x03;
|
||||
}
|
||||
|
||||
- (NSData *) BSONEncode
|
||||
{
|
||||
// Initialize the components structure.
|
||||
NSMutableArray *components = [[NSMutableArray alloc] init];
|
||||
|
||||
NSMutableData *lengthData = [[NSMutableData alloc] initWithLength: 4];
|
||||
[components addObject: lengthData];
|
||||
[lengthData release];
|
||||
|
||||
NSMutableData *contentsData = [[NSMutableData alloc] init];
|
||||
[components addObject: contentsData];
|
||||
[contentsData release];
|
||||
|
||||
[components addObject: [NSData dataWithBytes: "\x00" length: 1]];
|
||||
|
||||
// Ensure ordered keys. not in BSON spec, but ensures all BSONRepresentations
|
||||
// of the same dict will be the same.
|
||||
NSMutableArray *keys = [[NSMutableArray alloc] init];
|
||||
[keys addObjectsFromArray: [self allKeys]];
|
||||
//[keys sortUsingSelector: @selector(caseInsensitiveCompare:)];
|
||||
|
||||
// Encode data.- (NSData *) BSONEncode;
|
||||
uint8_t elementType = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < [keys count]; i++)
|
||||
{
|
||||
NSString *key = [keys objectAtIndex: i];
|
||||
NSObject *value = [self objectForKey: key];
|
||||
|
||||
if ([value respondsToSelector: @selector(BSONTypeID)])
|
||||
elementType = [(id <BSONCoding>) value BSONTypeID];
|
||||
else
|
||||
elementType = 3;
|
||||
|
||||
[contentsData appendBytes: &elementType length: 1];
|
||||
[contentsData appendData: [key dataUsingEncoding: NSUTF8StringEncoding]];
|
||||
[contentsData appendBytes: "\x00" length: 1];
|
||||
[contentsData appendData: [value BSONEncode]];
|
||||
}
|
||||
[keys release];
|
||||
|
||||
// Write length.
|
||||
uint32_t *length = (uint32_t *)[lengthData mutableBytes];
|
||||
*length = HOSTTOBSON32([contentsData length]) + 4 + 1;
|
||||
|
||||
// Assemble the output data.
|
||||
NSMutableData *retval = [NSMutableData data];
|
||||
for (i = 0; i < [components count]; i++)
|
||||
[retval appendData: [components objectAtIndex: i]];
|
||||
[components release];
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
- (NSData *) BSONRepresentation
|
||||
{
|
||||
return [self BSONEncode];
|
||||
}
|
||||
|
||||
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) t
|
||||
{
|
||||
const void *current = [data bytes];
|
||||
if ((id)base != nil)
|
||||
current = *base;
|
||||
else
|
||||
base = ¤t;
|
||||
|
||||
uint32_t length = BSONTOHOST32(*((uint32_t *)current));
|
||||
const void *endPoint = current + length;
|
||||
current += 4;
|
||||
|
||||
NSMutableDictionary *retval = [NSMutableDictionary dictionary];
|
||||
while (current < endPoint - 1)
|
||||
{
|
||||
uint8_t typeID = *((uint8_t *)current);
|
||||
current++;
|
||||
|
||||
char *utf8Key = (char *) current;
|
||||
while (*((char *)current) != 0 && current < endPoint - 1)
|
||||
current++;
|
||||
current++;
|
||||
NSString *key = [NSString stringWithUTF8String: utf8Key];
|
||||
|
||||
*base = current;
|
||||
Class typeClass = [BSONTypes() objectForKey: [NSNumber numberWithChar: typeID]];
|
||||
id value = objc_msgSend(typeClass, @selector(BSONFragment:at:ofType:), data, base, typeID);
|
||||
current = *base;
|
||||
|
||||
[retval setObject: value forKey: key];
|
||||
}
|
||||
|
||||
*base = current + 1;
|
||||
|
||||
// If the dictionary has a class name marker, then it is to be converted to an object.
|
||||
if ([retval objectForKey: CLASS_NAME_MARKER] != nil)
|
||||
{
|
||||
NSData *classNameData = [retval objectForKey: CLASS_NAME_MARKER];
|
||||
char *className = malloc([classNameData length] + 1);
|
||||
memcpy(className, [classNameData bytes], [classNameData length]);
|
||||
className[[classNameData length]] = 0;
|
||||
|
||||
Class targetClass = objc_getClass(className);
|
||||
if (targetClass == nil)
|
||||
[NSException raise: NSInvalidArgumentException format: @"Class %s found in incoming data is undefined.", className];
|
||||
|
||||
id obj = [[targetClass alloc] initWithBSONDictionary: retval];
|
||||
return obj;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSData (BSON)
|
||||
- (uint8_t) BSONTypeID
|
||||
{
|
||||
return 0x05;
|
||||
}
|
||||
|
||||
- (NSData *) BSONEncode
|
||||
{
|
||||
uint32_t length = HOSTTOBSON32([self length]);
|
||||
NSMutableData *retval = [NSMutableData data];
|
||||
[retval appendBytes: &length length: 4];
|
||||
[retval appendBytes: "\x00" length: 1];
|
||||
[retval appendData: self];
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
- (NSData *) BSONRepresentation
|
||||
{
|
||||
return [self BSONEncode];
|
||||
}
|
||||
|
||||
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) t
|
||||
{
|
||||
const void *current = [data bytes];
|
||||
if ((id)base != nil)
|
||||
current = *base;
|
||||
else
|
||||
base = ¤t;
|
||||
|
||||
uint32_t length = BSONTOHOST32(*((uint32_t *)current));
|
||||
current += 4 + 1;
|
||||
|
||||
NSData *retval = [NSData dataWithBytes: current length: length];
|
||||
current += length;
|
||||
*base = current;
|
||||
return retval;
|
||||
}
|
||||
|
||||
- (NSDictionary *) BSONValue
|
||||
{
|
||||
return [NSDictionary BSONFragment: self at: NULL ofType: 0x03];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSNumber (BSON)
|
||||
- (uint8_t) BSONTypeID
|
||||
{
|
||||
const char encoding = tolower(*([self objCType]));
|
||||
|
||||
switch (encoding) {
|
||||
case 'f':
|
||||
case 'd': return 0x01;
|
||||
case 'b': return 0x08;
|
||||
case 'c':
|
||||
case 's': return 0x10;
|
||||
case 'i':
|
||||
// Ok, if you're running Objective-C on 16-bit platforms...
|
||||
// Then YOU have issues.
|
||||
// So, yeah, we won't handle that case.
|
||||
if (sizeof(int) == 4)
|
||||
return 0x10;
|
||||
else if (sizeof(int) == 8)
|
||||
return 0x12;
|
||||
|
||||
case 'l':
|
||||
if (sizeof(long) == 4)
|
||||
return 0x10;
|
||||
else if (sizeof(long) == 8)
|
||||
return 0x12;
|
||||
|
||||
case 'q': return 0x12;
|
||||
default:
|
||||
[NSException raise: NSInvalidArgumentException format: @"%@::%s - invalid encoding type '%c'", [self class], _cmd, encoding];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (NSData *) BSONEncode
|
||||
{
|
||||
const char encoding = *([self objCType]);
|
||||
|
||||
if (encoding == 'd' || encoding == 'D')
|
||||
{
|
||||
double value = [self doubleValue];
|
||||
return [NSData dataWithBytes: &value length: 8];
|
||||
}
|
||||
|
||||
if (encoding == 'f' || encoding == 'F')
|
||||
{
|
||||
double value = [self floatValue];
|
||||
return [NSData dataWithBytes: &value length: 8];
|
||||
}
|
||||
|
||||
if (encoding == 'b' || encoding == 'B')
|
||||
{
|
||||
char value = [self boolValue];
|
||||
return [NSData dataWithBytes: &value length: 1];
|
||||
}
|
||||
|
||||
if (encoding == 'c' || encoding == 'C')
|
||||
{
|
||||
int32_t value = [self charValue];
|
||||
value = HOSTTOBSON32(value);
|
||||
return [NSData dataWithBytes: &value length: 4];
|
||||
}
|
||||
|
||||
if (encoding == 's' || encoding == 'S')
|
||||
{
|
||||
int32_t value = [self shortValue];
|
||||
value = HOSTTOBSON32(value);
|
||||
return [NSData dataWithBytes: &value length: 4];
|
||||
}
|
||||
|
||||
if (encoding == 'i' || encoding == 'I')
|
||||
{
|
||||
int value = [self intValue];
|
||||
if (sizeof(int) == 4)
|
||||
value = HOSTTOBSON32(value);
|
||||
else if (sizeof(int) == 8)
|
||||
value = HOSTTOBSON64(value);
|
||||
return [NSData dataWithBytes: &value length: sizeof(int)];
|
||||
}
|
||||
|
||||
if (encoding == 'l' || encoding == 'L')
|
||||
{
|
||||
long value = [self longValue];
|
||||
if (sizeof(long) == 4)
|
||||
value = HOSTTOBSON32(value);
|
||||
else if (sizeof(long) == 8)
|
||||
value = HOSTTOBSON64(value);
|
||||
|
||||
return [NSData dataWithBytes: &value length: sizeof(long)];
|
||||
}
|
||||
|
||||
if (encoding == 'q')
|
||||
{
|
||||
long long value = HOSTTOBSON64([self longLongValue]);
|
||||
return [NSData dataWithBytes: &value length: 8];
|
||||
}
|
||||
|
||||
if (encoding == 'Q')
|
||||
{
|
||||
long long value = HOSTTOBSON64([self unsignedLongLongValue]);
|
||||
return [NSData dataWithBytes: &value length: 8];
|
||||
}
|
||||
|
||||
|
||||
[NSException raise: NSInvalidArgumentException format: @"%@::%s - invalid encoding type '%c'", [self class], _cmd, encoding];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSData *) BSONRepresentation
|
||||
{
|
||||
return [self BSONEncode];
|
||||
}
|
||||
|
||||
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) t
|
||||
{
|
||||
if (t == 0x01)
|
||||
{
|
||||
// #5: LLVM GCC requires double pointers to have a certain alignment in ARM CPUs.
|
||||
// So we can't just read the double off directly from the data - need to copy it.
|
||||
double value;
|
||||
memcpy(&value, *base, sizeof(double));
|
||||
*base += 8;
|
||||
return [NSNumber numberWithDouble: value];
|
||||
}
|
||||
|
||||
if (t == 0x08)
|
||||
{
|
||||
char value = ((char *) *base)[0];
|
||||
*base += 1;
|
||||
return [NSNumber numberWithBool: value];
|
||||
}
|
||||
|
||||
if (t == 0x10)
|
||||
{
|
||||
int32_t value = BSONTOHOST32(((int32_t *) *base)[0]);
|
||||
*base += 4;
|
||||
|
||||
if (sizeof(int) == 4)
|
||||
return [NSNumber numberWithInt: value];
|
||||
|
||||
return [NSNumber numberWithLong: value];
|
||||
}
|
||||
|
||||
if (t == 0x12)
|
||||
{
|
||||
int64_t value = BSONTOHOST64(((int64_t *) *base)[0]);
|
||||
*base += 8;
|
||||
|
||||
return [NSNumber numberWithUnsignedLongLong: value];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSString (BSON)
|
||||
- (uint8_t) BSONTypeID
|
||||
{
|
||||
return 0x02;
|
||||
}
|
||||
|
||||
- (NSData *) BSONEncode
|
||||
{
|
||||
NSData *utf8Data = [self dataUsingEncoding: NSUTF8StringEncoding];
|
||||
uint32_t length = HOSTTOBSON32([utf8Data length] + 1);
|
||||
|
||||
NSMutableData *retval = [NSMutableData data];
|
||||
[retval appendBytes: &length length: 4];
|
||||
[retval appendData: utf8Data];
|
||||
[retval appendBytes: "\x00" length: 1];
|
||||
return retval;
|
||||
}
|
||||
|
||||
- (NSData *) BSONRepresentation
|
||||
{
|
||||
return [self BSONEncode];
|
||||
}
|
||||
|
||||
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
|
||||
{
|
||||
uint32_t length = BSONTOHOST32(((const uint32_t *) *base)[0]);
|
||||
*base += 4;
|
||||
|
||||
const char *utf8Str = (const char *) *base;
|
||||
*base += length;
|
||||
|
||||
return [NSString stringWithUTF8String: utf8Str];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSArray (BSON)
|
||||
- (uint8_t) BSONTypeID
|
||||
{
|
||||
return 0x04;
|
||||
}
|
||||
|
||||
- (NSData *) BSONEncode
|
||||
{
|
||||
// Initialize the components structure.
|
||||
NSMutableArray *components = [[NSMutableArray alloc] init];
|
||||
|
||||
NSMutableData *lengthData = [[NSMutableData alloc] initWithLength: 4];
|
||||
[components addObject: lengthData];
|
||||
[lengthData release];
|
||||
|
||||
NSMutableData *contentsData = [[NSMutableData alloc] init];
|
||||
[components addObject: contentsData];
|
||||
[contentsData release];
|
||||
|
||||
[components addObject: [NSData dataWithBytes: "\x00" length: 1]];
|
||||
|
||||
// Encode data.
|
||||
uint8_t elementType = 0;
|
||||
int i, count = [self count];
|
||||
for (i = 0 ; i < count ; i++)
|
||||
{
|
||||
NSObject *value = [self objectAtIndex: i];
|
||||
|
||||
if ([value respondsToSelector: @selector(BSONTypeID)])
|
||||
elementType = [(id <BSONCoding>) value BSONTypeID];
|
||||
else
|
||||
elementType = 3;
|
||||
|
||||
[contentsData appendBytes: &elementType length: 1];
|
||||
[contentsData appendData: [[NSString stringWithFormat: @"%d", i] dataUsingEncoding: NSUTF8StringEncoding]];
|
||||
[contentsData appendBytes: "\x00" length: 1];
|
||||
[contentsData appendData: [value BSONEncode]];
|
||||
}
|
||||
|
||||
// Write length.
|
||||
uint32_t *length = (uint32_t *)[lengthData mutableBytes];
|
||||
*length = HOSTTOBSON32([contentsData length]) + 4 + 1;
|
||||
|
||||
// Assemble the output data.
|
||||
NSMutableData *retval = [NSMutableData data];
|
||||
for (i = 0; i < [components count]; i++)
|
||||
[retval appendData: [components objectAtIndex: i]];
|
||||
[components release];
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
- (NSData *) BSONRepresentation
|
||||
{
|
||||
return [self BSONEncode];
|
||||
}
|
||||
|
||||
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
|
||||
{
|
||||
NSDictionary *tmp = [NSDictionary BSONFragment: data at: base ofType: 0x03];
|
||||
NSMutableArray *retval = [NSMutableArray arrayWithCapacity: [tmp count]];
|
||||
int i;
|
||||
for (i = 0; i < [tmp count]; i++)
|
||||
[retval addObject: [tmp objectForKey: [NSString stringWithFormat: @"%d", i]]];
|
||||
|
||||
return retval;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSNull (BSON)
|
||||
- (uint8_t) BSONTypeID
|
||||
{
|
||||
return 0x0a;
|
||||
}
|
||||
|
||||
- (NSData *) BSONEncode
|
||||
{
|
||||
return [NSData data];
|
||||
}
|
||||
|
||||
- (NSData *) BSONRepresentation
|
||||
{
|
||||
return [self BSONEncode];
|
||||
}
|
||||
|
||||
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
|
||||
{
|
||||
return [NSNull null];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSCalendarDate (BSON)
|
||||
- (uint8_t) BSONTypeID
|
||||
{
|
||||
return 0x11;
|
||||
}
|
||||
|
||||
- (NSData *) BSONEncode
|
||||
{
|
||||
NSString *v;
|
||||
|
||||
v = [self descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %Z"
|
||||
locale: nil];
|
||||
|
||||
return [v BSONEncode];
|
||||
}
|
||||
|
||||
- (NSData *) BSONRepresentation
|
||||
{
|
||||
return [self BSONEncode];
|
||||
}
|
||||
|
||||
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
|
||||
{
|
||||
NSString *v;
|
||||
|
||||
v = [NSString BSONFragment: data at: base ofType: 0x02];
|
||||
|
||||
return [NSCalendarDate dateWithString: v
|
||||
calendarFormat: @"%Y-%m-%d %H:%M:%S %Z"];
|
||||
}
|
||||
@end
|
||||
@@ -46,12 +46,12 @@
|
||||
NSDictionary *properties;
|
||||
BOOL rc;
|
||||
|
||||
[self logWithFormat: @"evaluating object '%@'", object];
|
||||
//[self logWithFormat: @"evaluating object '%@'", object];
|
||||
|
||||
properties = [object properties];
|
||||
rc = [self _evaluateSOGoMAPIDBObject: properties];
|
||||
|
||||
[self logWithFormat: @" evaluation result: %d", rc];
|
||||
//[self logWithFormat: @" evaluation result: %d", rc];
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -150,9 +150,9 @@ typedef BOOL (*EOComparator) (id, SEL, id);
|
||||
rc = ((isZero && (intValue & mask) == 0)
|
||||
|| (!isZero && (intValue & mask) != 0));
|
||||
|
||||
[self logWithFormat: @"evaluation of bitmask qualifier:"
|
||||
@" (%.8x & %.8x) %s 0: %d",
|
||||
intValue, mask, (isZero ? "==" : "!="), rc];
|
||||
//[self logWithFormat: @"evaluation of bitmask qualifier:"
|
||||
// @" (%.8x & %.8x) %s 0: %d",
|
||||
// intValue, mask, (isZero ? "==" : "!="), rc];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
@" c_lastmodified INT NOT NULL,"
|
||||
@" c_version INT NOT NULL DEFAULT 0,"
|
||||
@" c_deleted TINYINT NOT NULL DEFAULT 0,"
|
||||
@" c_content TEXT)");
|
||||
@" c_content LONGTEXT)");
|
||||
|
||||
return [NSString stringWithFormat: sqlFolderFormat, tableName];
|
||||
}
|
||||
|
||||
+5
-30
@@ -7,8 +7,6 @@ include ../Version
|
||||
|
||||
BACKEND_VERSION = 1.0.0
|
||||
|
||||
UNRTF_VERSION = 0.21.2
|
||||
|
||||
### bootstrap library
|
||||
MAPISTORESOGO = MAPIStoreSOGo
|
||||
LIBRARY_NAME = $(MAPISTORESOGO)
|
||||
@@ -24,8 +22,6 @@ BUNDLE_NAME = $(SOGOBACKEND)
|
||||
BUNDLE_EXTENSION = .MAPIStore
|
||||
BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR)
|
||||
|
||||
UNRTF_DIR = unrtf-$(UNRTF_VERSION)
|
||||
|
||||
PYTHON = /usr/bin/python
|
||||
PYTHON_IS_GOOD = $(shell $(PYTHON) -c 'from sys import version_info; a=version_info; print a[0] == 2 and a[1] >= 6')
|
||||
ifeq (${PYTHON_IS_GOOD},False)
|
||||
@@ -37,8 +33,6 @@ all::
|
||||
|
||||
SAMBA_PRIVATE_DIR = $(shell $(PYTHON) ./samba-get-config.py "private dir")
|
||||
|
||||
$(SOGOBACKEND)_SUBPROJECTS += $(UNRTF_DIR)/src
|
||||
|
||||
$(SOGOBACKEND)_PRINCIPAL_CLASS = MAPIApplication
|
||||
|
||||
$(SOGOBACKEND)_OBJC_FILES += \
|
||||
@@ -133,32 +127,14 @@ $(SOGOBACKEND)_OBJC_FILES += \
|
||||
\
|
||||
EOQualifier+MAPI.m \
|
||||
\
|
||||
EOBitmaskQualifier.m
|
||||
EOBitmaskQualifier.m \
|
||||
\
|
||||
BSONCodec.m \
|
||||
RTFHandler.m
|
||||
|
||||
|
||||
$(SOGOBACKEND)_RESOURCE_FILES += \
|
||||
product.plist \
|
||||
$(UNRTF_DIR)/charmaps/SYMBOL.charmap \
|
||||
$(UNRTF_DIR)/outputs/html.conf
|
||||
|
||||
### unrtf
|
||||
all:: $(UNRTF_DIR)/config.h $(UNRTF_DIR)/src/GNUmakefile
|
||||
|
||||
$(UNRTF_DIR): $(UNRTF_DIR).tar.gz $(UNRTF_DIR).diff
|
||||
@echo " Extracting and patching $(UNRTF_DIR)..."
|
||||
@rm -rf $(UNRTF_DIR)
|
||||
@$(TAR) -xvzf $< > /dev/null
|
||||
@(cd $(UNRTF_DIR) && patch -p1 < ../$(UNRTF_DIR).diff) > /dev/null
|
||||
@touch $(UNRTF_DIR)
|
||||
|
||||
$(UNRTF_DIR)-stamp: $(UNRTF_DIR)
|
||||
@touch $@
|
||||
|
||||
$(UNRTF_DIR)/config.h: $(UNRTF_DIR)-stamp unrtf_config_h
|
||||
@cp unrtf_config_h $(UNRTF_DIR)/config.h
|
||||
|
||||
$(UNRTF_DIR)/src/GNUmakefile: $(UNRTF_DIR)-stamp GNUmakefile.unrtf
|
||||
@cp GNUmakefile.unrtf $@
|
||||
product.plist
|
||||
|
||||
### pl reader
|
||||
PLREADER_TOOL = plreader
|
||||
@@ -210,7 +186,6 @@ ADDITIONAL_INCLUDE_DIRS += \
|
||||
-DSAMBA_PRIVATE_DIR=@"\"$(SAMBA_PRIVATE_DIR)\"" \
|
||||
$(LIBMAPI_CFLAGS) \
|
||||
$(LIBMAPISTORE_CFLAGS) \
|
||||
-I$(UNRTF_DIR)/src \
|
||||
-I../SoObjects -I../SOPE \
|
||||
-DBACKEND_BUNDLE_NAME="@\"$(BUNDLE_NAME)$(BUNDLE_EXTENSION)\"" \
|
||||
-DSOGO_BUNDLES_DIR="@\"$(BUNDLE_INSTALL_DIR)\""
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
# -*-makefile-*-
|
||||
|
||||
# GNUstep makefile
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/common.make
|
||||
|
||||
UNRTF = unrtf
|
||||
|
||||
SUBPROJECT_NAME = $(UNRTF)
|
||||
|
||||
$(UNRTF)_C_FILES = \
|
||||
attr.c \
|
||||
convert.c \
|
||||
error.c \
|
||||
hash.c \
|
||||
malloc.c \
|
||||
my_iconv.c \
|
||||
output.c \
|
||||
parse.c \
|
||||
unicode.c \
|
||||
user.c \
|
||||
util.c \
|
||||
word.c
|
||||
|
||||
$(UNRTF)_CFLAGS = -DHAVE_CONFIG_H=1 -I. -I../
|
||||
|
||||
# Option include to set any additional variables
|
||||
-include GNUmakefile.preamble
|
||||
|
||||
# Include in the rules for making libraries
|
||||
include $(GNUSTEP_MAKEFILES)/subproject.make
|
||||
|
||||
# Option include to define any additional rules
|
||||
-include GNUmakefile.postamble
|
||||
@@ -161,7 +161,7 @@
|
||||
return [self getNo: data inMemCtx: memCtx];
|
||||
}
|
||||
|
||||
- (void) save
|
||||
- (void) save: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
// (gdb) po embeddedMessage->properties
|
||||
// 2442592320 = "2012-07-11 22:30:00 +0000";
|
||||
@@ -208,7 +208,8 @@
|
||||
|
||||
[[container event] updateFromMAPIProperties: properties
|
||||
inUserContext: [self userContext]
|
||||
withActiveUser: activeUser];
|
||||
withActiveUser: activeUser
|
||||
inMemCtx: memCtx];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -63,7 +63,7 @@
|
||||
SOGoAppointmentObject *newEntry;
|
||||
NSString *name;
|
||||
|
||||
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
|
||||
name = [NSString stringWithFormat: @"%@.ics",
|
||||
[SOGoObject globallyUniqueObjectId]];
|
||||
|
||||
@@ -200,6 +200,7 @@ static Class NSArrayK;
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
//NSLog(@"MAPIStoreCalendarMessage: -dealloc (%p)", self);
|
||||
[calendar release];
|
||||
[super dealloc];
|
||||
}
|
||||
@@ -417,7 +418,7 @@ static Class NSArrayK;
|
||||
return [self getYes: data inMemCtx: memCtx];
|
||||
}
|
||||
|
||||
- (NSString *) _uidFromGlobalObjectId
|
||||
- (NSString *) _uidFromGlobalObjectId: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
NSData *objectId;
|
||||
NSString *uid = nil;
|
||||
@@ -431,7 +432,7 @@ static Class NSArrayK;
|
||||
if (objectId)
|
||||
{
|
||||
length = [objectId length];
|
||||
bytesDup = talloc_array (NULL, char, length + 1);
|
||||
bytesDup = talloc_array (memCtx, char, length + 1);
|
||||
memcpy (bytesDup, [objectId bytes], length);
|
||||
bytesDup[length] = 0;
|
||||
uidStart = bytesDup + length - 1;
|
||||
@@ -596,7 +597,7 @@ static Class NSArrayK;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) save
|
||||
- (void) save: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
// iCalCalendar *vCalendar;
|
||||
// NSCalendarDate *now;
|
||||
@@ -608,7 +609,7 @@ static Class NSArrayK;
|
||||
|
||||
if (isNew)
|
||||
{
|
||||
uid = [self _uidFromGlobalObjectId];
|
||||
uid = [self _uidFromGlobalObjectId: memCtx];
|
||||
if (uid)
|
||||
{
|
||||
/* Hack required because of what's explained in oxocal 3.1.4.7.1:
|
||||
@@ -650,12 +651,12 @@ static Class NSArrayK;
|
||||
activeUser = [[self context] activeUser];
|
||||
[masterEvent updateFromMAPIProperties: properties
|
||||
inUserContext: [self userContext]
|
||||
withActiveUser: activeUser];
|
||||
withActiveUser: activeUser
|
||||
inMemCtx: memCtx];
|
||||
[self _updateAttachedEvents];
|
||||
[[self userContext] activateWithUser: activeUser];
|
||||
[sogoObject updateContentWithCalendar: calendar
|
||||
fromRequest: nil];
|
||||
|
||||
[self updateVersions];
|
||||
}
|
||||
|
||||
|
||||
@@ -911,7 +911,7 @@ fromProperties: (NSDictionary *) attachmentProps
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) save
|
||||
- (void) save:(TALLOC_CTX *) memCtx
|
||||
{
|
||||
NSArray *elements, *units;
|
||||
CardElement *element;
|
||||
|
||||
@@ -224,7 +224,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||
NSURL *baseURL;
|
||||
int rc = MAPISTORE_ERR_NOT_FOUND;
|
||||
|
||||
NSLog (@"METHOD '%s' (%d) -- uri: '%s'", __FUNCTION__, __LINE__, newUri);
|
||||
//NSLog (@"METHOD '%s' (%d) -- uri: '%s'", __FUNCTION__, __LINE__, newUri);
|
||||
|
||||
context = nil;
|
||||
|
||||
@@ -532,8 +532,8 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||
mappingId = [mapping idFromURL: childURL];
|
||||
if (mappingId == NSNotFound)
|
||||
{
|
||||
[self warnWithFormat: @"no id exist yet for '%@', requesting one...",
|
||||
childURL];
|
||||
//[self warnWithFormat: @"no id exist yet for '%@', requesting one...",
|
||||
// childURL];
|
||||
openchangedb_get_new_folderID (connInfo->oc_ctx, &mappingId);
|
||||
[mapping registerURL: childURL withID: mappingId];
|
||||
contextId = 0;
|
||||
|
||||
@@ -130,6 +130,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||
withNewName: (NSString *) newFolderName
|
||||
isMove: (BOOL) isMove
|
||||
isRecursive: (BOOL) isRecursive
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
NSString *path, *pathComponent, *targetPath, *newPath;
|
||||
@@ -164,7 +165,8 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||
else
|
||||
rc = [super moveCopyToFolder: targetFolder withNewName: newFolderName
|
||||
isMove: isMove
|
||||
isRecursive: isRecursive];
|
||||
isRecursive: isRecursive
|
||||
inMemCtx: memCtx];
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -234,7 +236,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||
messageKeys = [self messageKeys];
|
||||
|
||||
date = [NSCalendarDate date];
|
||||
[self logWithFormat: @"current date: %@", date];
|
||||
//[self logWithFormat: @"current date: %@", date];
|
||||
|
||||
max = [messageKeys count];
|
||||
for (count = 0; count < max; count++)
|
||||
@@ -243,7 +245,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||
fileDate = [msg lastModificationTime];
|
||||
if ([date laterDate: fileDate] == fileDate)
|
||||
{
|
||||
[self logWithFormat: @"current date: %@", date];
|
||||
//[self logWithFormat: @"current date: %@", date];
|
||||
|
||||
date = fileDate;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
@@ -34,6 +35,7 @@
|
||||
#import "MAPIStoreDBMessage.h"
|
||||
#import "MAPIStoreTypes.h"
|
||||
#import "NSObject+MAPIStore.h"
|
||||
#import "NSString+MAPIStore.h"
|
||||
|
||||
#undef DEBUG
|
||||
#include <mapistore/mapistore.h>
|
||||
@@ -99,6 +101,21 @@
|
||||
return objectVersion;
|
||||
}
|
||||
|
||||
//
|
||||
// FIXME: how this can happen?
|
||||
//
|
||||
// We might get there if for some reasons, all classes weren't able
|
||||
// to tell us the message class.
|
||||
//
|
||||
- (int) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
*data = [@"IPM.Note" asUnicodeInMemCtx: memCtx];
|
||||
|
||||
[self logWithFormat: @"METHOD '%s' - unable to determine message class. Falling back to IPM.Note", __FUNCTION__];
|
||||
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
- (int) getProperties: (struct mapistore_property_data *) data
|
||||
withTags: (enum MAPITAGS *) tags
|
||||
andCount: (uint16_t) columnCount
|
||||
@@ -135,7 +152,7 @@
|
||||
[super addProperties: newNewProperties];
|
||||
}
|
||||
|
||||
- (void) save
|
||||
- (void) save: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
uint64_t newVersion;
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ static Class MAPIStoreDBMessageK = Nil;
|
||||
cVersion = exchange_globcnt (([value unsignedLongLongValue] >> 16)
|
||||
& 0x0000ffffffffffffLL);
|
||||
version = [NSNumber numberWithUnsignedLongLong: cVersion];
|
||||
[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
|
||||
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
|
||||
[self logWithFormat: @" version: %.16lx", cVersion];
|
||||
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version"
|
||||
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
|
||||
|
||||
@@ -146,7 +146,7 @@ static Class MAPIStoreAttachmentK;
|
||||
return ULLONG_MAX;
|
||||
}
|
||||
|
||||
- (void) save
|
||||
- (void) save: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
return [self getYes: data inMemCtx: memCtx];
|
||||
}
|
||||
|
||||
- (enum mapistore_error) saveMessage
|
||||
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx;
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
MAPIStoreContext *context;
|
||||
@@ -60,7 +60,7 @@
|
||||
context = [self context];
|
||||
ownerUser = [[self userContext] sogoUser];
|
||||
if ([[context activeUser] isEqual: ownerUser])
|
||||
rc = [super saveMessage];
|
||||
rc = [super saveMessage: memCtx];
|
||||
else
|
||||
rc = MAPISTORE_ERR_DENIED;
|
||||
|
||||
|
||||
@@ -129,7 +129,8 @@
|
||||
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
|
||||
withNewName: (NSString *) newFolderName
|
||||
isMove: (BOOL) isMove
|
||||
isRecursive: (BOOL) isRecursive;
|
||||
isRecursive: (BOOL) isRecursive
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
|
||||
- (int) getDeletedFMIDs: (struct UI8Array_r **) fmidsPtr
|
||||
andCN: (uint64_t *) cnPtr
|
||||
|
||||
@@ -180,7 +180,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
|
||||
// [messageKeys release];
|
||||
// [faiMessageKeys release];
|
||||
@@ -366,7 +366,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
MAPIStoreMapping *mapping;
|
||||
NSString *childURL;
|
||||
|
||||
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
|
||||
mapping = [self mapping];
|
||||
childURL = [mapping urlFromID: fid];
|
||||
@@ -393,7 +393,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
MAPIStoreFolder *childFolder;
|
||||
SOGoUser *ownerUser;
|
||||
|
||||
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
|
||||
ownerUser = [[self userContext] sogoUser];
|
||||
if ([[context activeUser] isEqual: ownerUser]
|
||||
@@ -450,8 +450,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
NSArray *keys;
|
||||
int rc = MAPISTORE_SUCCESS;
|
||||
|
||||
[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d",
|
||||
__FUNCTION__, __LINE__, tableType];
|
||||
//[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d",
|
||||
//__FUNCTION__, __LINE__, tableType];
|
||||
|
||||
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
||||
keys = [self messageKeys];
|
||||
@@ -513,8 +513,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
MAPIStoreMapping *mapping;
|
||||
SOGoUser *ownerUser;
|
||||
|
||||
[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16llx associated: %d",
|
||||
__FUNCTION__, mid, isAssociated];
|
||||
//[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16llx associated: %d",
|
||||
// __FUNCTION__, mid, isAssociated];
|
||||
|
||||
context = [self context];
|
||||
ownerUser = [[self userContext] sogoUser];
|
||||
@@ -699,7 +699,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
if (rc != MAPISTORE_SUCCESS)
|
||||
goto end;
|
||||
}
|
||||
[destMsg save];
|
||||
[destMsg save: memCtx];
|
||||
if (!wantCopy)
|
||||
rc = [sourceFolder deleteMessageWithMID: srcMid andFlags: 0];
|
||||
|
||||
@@ -786,6 +786,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
withNewName: (NSString *) newFolderName
|
||||
isMove: (BOOL) isMove
|
||||
isRecursive: (BOOL) isRecursive
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
NSAutoreleasePool *pool;
|
||||
@@ -798,9 +800,9 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
NSUInteger count, max;
|
||||
NSString *childKey;
|
||||
uint64_t fmid;
|
||||
TALLOC_CTX *memCtx;
|
||||
//TALLOC_CTX *memCtx;
|
||||
|
||||
memCtx = talloc_zero (NULL, TALLOC_CTX);
|
||||
//memCtx = talloc_zero (NULL, TALLOC_CTX);
|
||||
|
||||
/* TODO: one possible issue with this algorithm is that moved messages will
|
||||
lack a version number and will all be assigned a new one, even though
|
||||
@@ -842,7 +844,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
[mapping registerURL: [targetMessage url]
|
||||
withID: fmid];
|
||||
}
|
||||
[targetMessage save];
|
||||
[targetMessage save: memCtx];
|
||||
}
|
||||
[pool release];
|
||||
|
||||
@@ -863,7 +865,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
[mapping registerURL: [targetMessage url]
|
||||
withID: fmid];
|
||||
}
|
||||
[targetMessage save];
|
||||
[targetMessage save: memCtx];
|
||||
}
|
||||
[pool release];
|
||||
|
||||
@@ -878,7 +880,9 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
subFolder = [self lookupFolder: childKey];
|
||||
[subFolder moveCopyToFolder: newFolder withNewName: nil
|
||||
isMove: isMove
|
||||
isRecursive: isRecursive];
|
||||
isRecursive: isRecursive
|
||||
inMemCtx: memCtx];
|
||||
|
||||
}
|
||||
[pool release];
|
||||
}
|
||||
@@ -898,7 +902,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
else
|
||||
rc = MAPISTORE_ERR_DENIED;
|
||||
|
||||
talloc_free (memCtx);
|
||||
//talloc_free (memCtx);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,8 @@
|
||||
[MAPIApp setUserContext: userContext];
|
||||
moduleName = [self MAPIModuleName];
|
||||
parentFolder = [[userContext rootFolders] objectForKey: moduleName];
|
||||
nameInContainer = nil;
|
||||
|
||||
if (![parentFolder newFolderWithName: folderName
|
||||
nameInContainer: &nameInContainer])
|
||||
mapistoreURI = [NSString stringWithFormat: @"sogo://%@@%@/%@/",
|
||||
|
||||
@@ -259,7 +259,6 @@ static Class NSNumberK;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
- (void) _setChangeKey: (NSData *) changeKey
|
||||
forMessageEntry: (NSMutableDictionary *) messageEntry
|
||||
inChangeListOnly: (BOOL) inChangeListOnly
|
||||
@@ -461,7 +460,10 @@ static Class NSNumberK;
|
||||
[mapping setObject: cLastModified forKey: changeNumber];
|
||||
[messageEntry setObject: changeNumber forKey: @"version"];
|
||||
|
||||
newChangeNum = [changeNumber unsignedLongValue];
|
||||
newChangeNum = [changeNumber unsignedLongLongValue];
|
||||
|
||||
// A GLOBCNT structure is a 6-byte global namespace counter,
|
||||
// we strip the first 2 bytes. The first two bytes is the ReplicaId
|
||||
changeKey = [self getReplicaKeyFromGlobCnt: newChangeNum >> 16];
|
||||
[self _setChangeKey: changeKey forMessageEntry: messageEntry
|
||||
inChangeListOnly: NO];
|
||||
|
||||
@@ -92,8 +92,8 @@
|
||||
value = NSObjectFromMAPISPropValue (&res->lpProp);
|
||||
lastModified = [(MAPIStoreGCSFolder *)
|
||||
container lastModifiedFromMessageChangeNumber: value];
|
||||
[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
|
||||
[self logWithFormat: @" c_lastmodified: %@", lastModified];
|
||||
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
|
||||
//[self logWithFormat: @" c_lastmodified: %@", lastModified];
|
||||
if (lastModified)
|
||||
{
|
||||
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_lastmodified"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSURL.h>
|
||||
#import <NGImap4/NSString+Imap4.h>
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <Mailer/SOGoMailAccount.h>
|
||||
#import <Mailer/SOGoMailFolder.h>
|
||||
@@ -156,7 +157,7 @@ MakeDisplayFolderName (NSString *folderName)
|
||||
stringData = [NSString stringWithFormat: @"%@%@",
|
||||
urlBase, [currentName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
|
||||
context->url = [stringData asUnicodeInMemCtx: context];
|
||||
stringData = [[currentName substringFromIndex: 6] fromCSSIdentifier];
|
||||
stringData = [[[currentName substringFromIndex: 6] fromCSSIdentifier] stringByDecodingImap4FolderName];
|
||||
context->name = [stringData asUnicodeInMemCtx: context];
|
||||
context->main_folder = false;
|
||||
context->role = MAPISTORE_MAIL_ROLE;
|
||||
@@ -188,7 +189,7 @@ MakeDisplayFolderName (NSString *folderName)
|
||||
if ([newFolder create])
|
||||
mapistoreURI = [NSString stringWithFormat: @"sogo://%@:%@@mail/%@/",
|
||||
userName, userName,
|
||||
[folderName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
|
||||
[[folderName stringByEncodingImap4FolderName] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
|
||||
else
|
||||
mapistoreURI = nil;
|
||||
[MAPIApp setUserContext: nil];
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/* MAPIStoreMailFolder.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2011-2012 Inverse inc
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
* Copyright (C) 2011-2013 Inverse inc
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -36,6 +34,7 @@
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGImap4/NGImap4Connection.h>
|
||||
#import <NGImap4/NGImap4Client.h>
|
||||
#import <NGImap4/NSString+Imap4.h>
|
||||
#import <Mailer/SOGoDraftsFolder.h>
|
||||
#import <Mailer/SOGoMailAccount.h>
|
||||
#import <Mailer/SOGoMailAccounts.h>
|
||||
@@ -177,7 +176,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
||||
if (folderName)
|
||||
{
|
||||
nameInContainer = [NSString stringWithFormat: @"folder%@",
|
||||
[folderName asCSSIdentifier]];
|
||||
[[folderName stringByEncodingImap4FolderName] asCSSIdentifier]];
|
||||
newFolder = [SOGoMailFolderK objectWithName: nameInContainer
|
||||
inContainer: sogoObject];
|
||||
if ([newFolder create])
|
||||
@@ -315,7 +314,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
||||
|
||||
if (![subfolderName hasPrefix: @"folder"])
|
||||
abort ();
|
||||
strippedName = [subfolderName substringFromIndex: 6];
|
||||
strippedName = [[subfolderName substringFromIndex: 6] stringByDecodingImap4FolderName];
|
||||
[representation appendFormat: @"/%@", strippedName];
|
||||
|
||||
return representation;
|
||||
@@ -390,7 +389,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
||||
else
|
||||
value = [NSDate date];
|
||||
|
||||
[self logWithFormat: @"lastMessageModificationTime: %@", value];
|
||||
//[self logWithFormat: @"lastMessageModificationTime: %@", value];
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -613,8 +612,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
||||
[messageEntry setObject: modseq forKey: @"modseq"];
|
||||
[messageEntry setObject: changeNumber forKey: @"version"];
|
||||
|
||||
[self logWithFormat: @"added message entry for uid %@, modseq %@,"
|
||||
@" version %@", uid, modseq, changeNumber];
|
||||
//[self logWithFormat: @"added message entry for uid %@, modseq %@,"
|
||||
// @" version %@", uid, modseq, changeNumber];
|
||||
|
||||
changeKey = [self getReplicaKeyFromGlobCnt: newChangeNum >> 16];
|
||||
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
|
||||
@@ -796,7 +795,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
||||
|
||||
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
||||
{
|
||||
changeNumber = [NSString stringWithUnsignedLongLong: changeNum];
|
||||
changeNumber = [NSString stringWithFormat: @"0x%.16llx", changeNum];
|
||||
modseq = [[self modseqFromMessageChangeNumber: changeNumber]
|
||||
unsignedLongLongValue];
|
||||
if (modseq > 0)
|
||||
@@ -1055,6 +1054,7 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
||||
withNewName: (NSString *) newFolderName
|
||||
isMove: (BOOL) isMove
|
||||
isRecursive: (BOOL) isRecursive
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
NSURL *folderURL, *newFolderURL;
|
||||
@@ -1150,7 +1150,8 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
||||
moveCopyToFolder: newFolder
|
||||
withNewName: nil
|
||||
isMove: NO
|
||||
isRecursive: YES];
|
||||
isRecursive: YES
|
||||
inMemCtx: memCtx];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1163,7 +1164,8 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
||||
else
|
||||
rc = [super moveCopyToFolder: targetFolder withNewName: newFolderName
|
||||
isMove: isMove
|
||||
isRecursive: isRecursive];
|
||||
isRecursive: isRecursive
|
||||
inMemCtx: memCtx];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -693,7 +693,15 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||
ngAddress = [[NGMailAddressParser mailAddressParserWithString: fullMail]
|
||||
parse];
|
||||
if ([ngAddress isKindOfClass: [NGMailAddress class]])
|
||||
cn = [ngAddress displayName];
|
||||
{
|
||||
cn = [ngAddress displayName];
|
||||
|
||||
// If we don't have a displayName, we use the email address instead. This
|
||||
// avoid bug #2119 - where Outlook won't display anything in the "From" field,
|
||||
// nor in the recipient field if we reply to the email.
|
||||
if (![cn length])
|
||||
cn = [ngAddress address];
|
||||
}
|
||||
else
|
||||
cn = @"";
|
||||
|
||||
@@ -1576,7 +1584,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||
bodySetup = YES;
|
||||
}
|
||||
|
||||
- (void) save
|
||||
- (void) save: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
NSNumber *value;
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
|
||||
case PidLidAppointmentStartWhole:
|
||||
case PidLidAppointmentEndWhole:
|
||||
case PidLidRecurring:
|
||||
[self logWithFormat: @"apt restriction on mail folder?"];
|
||||
//[self logWithFormat: @"apt restriction on mail folder?"];
|
||||
rc = MAPIRestrictionStateAlwaysFalse;
|
||||
break;
|
||||
|
||||
@@ -155,10 +155,11 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
|
||||
|
||||
case PidTagChangeNumber:
|
||||
{
|
||||
value = [NSString stringWithFormat: @"0x%.16llx", [value unsignedLongLongValue]];
|
||||
modseq = [(MAPIStoreMailFolder *)
|
||||
container modseqFromMessageChangeNumber: value];
|
||||
[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
|
||||
[self logWithFormat: @" modseq: %.16lx", [modseq unsignedLongLongValue]];
|
||||
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
|
||||
//[self logWithFormat: @" modseq: %.16lx", [modseq unsignedLongLongValue]];
|
||||
if (modseq)
|
||||
modseq = [NSNumber numberWithUnsignedLongLong:
|
||||
[modseq unsignedLongLongValue] + 1];
|
||||
@@ -316,7 +317,7 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
|
||||
ASSIGN (sortOrderings, newSortOrderings);
|
||||
else
|
||||
ASSIGN (sortOrderings, [NSArray arrayWithObject: @"ARRIVAL"]);
|
||||
[self logWithFormat: @"new sort orderings: '%@'", sortOrderings];
|
||||
//[self logWithFormat: @"new sort orderings: '%@'", sortOrderings];
|
||||
}
|
||||
else
|
||||
ASSIGN (sortOrderings, [NSArray arrayWithObject: @"ARRIVAL"]);
|
||||
|
||||
@@ -543,6 +543,7 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
|
||||
NSDictionary *recipients;
|
||||
NSUInteger type, bccLimit;
|
||||
SOGoUser *activeUser;
|
||||
NSNumber *priority;
|
||||
|
||||
activeUser
|
||||
= [SOGoUser
|
||||
@@ -596,6 +597,21 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
|
||||
[headers addObject: [date rfc822DateString] forKey: @"date"];
|
||||
}
|
||||
[headers addObject: @"1.0" forKey: @"MIME-Version"];
|
||||
|
||||
priority = [mailProperties objectForKey: MAPIPropertyKey (PidTagImportance)];
|
||||
|
||||
if ([priority intValue] == 2)
|
||||
{
|
||||
[headers addObject: @"1 (Highest)" forKey: @"X-Priority"];
|
||||
}
|
||||
else if ([priority intValue] == 1)
|
||||
{
|
||||
[headers removeAllObjectsForKey: @"X-Priority"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[headers addObject: @"5 (Lowest)" forKey: @"X-Priority"];
|
||||
}
|
||||
}
|
||||
|
||||
static NSArray *
|
||||
@@ -904,7 +920,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
- (void) save
|
||||
- (void) save: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
NSString *folderName, *flag, *newIdString, *messageKey;
|
||||
NSData *changeKey, *messageData;
|
||||
@@ -943,7 +959,14 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
|
||||
[mapping registerURL: [self url] withID: mid];
|
||||
|
||||
/* synchronise the cache and update the change key with the one provided
|
||||
by the client */
|
||||
by the client. Before doing this, lets issue a unselect/select combo
|
||||
because of timing issues with Dovecot in obtaining the latest modseq.
|
||||
Sometimes, Dovecot doesn't return the newly appended UID if we do
|
||||
a "UID SORT (DATE) UTF-8 (MODSEQ XYZ) (NOT DELETED)" command (where
|
||||
XYZ is the HIGHESTMODSEQ+1) immediately after IMAP APPEND */
|
||||
[client unselect];
|
||||
[client select: folderName];
|
||||
|
||||
[(MAPIStoreMailFolder *) container synchroniseCache];
|
||||
changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
|
||||
if (changeKey)
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
- (int) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr
|
||||
andRowCount: (uint32_t *) countPtr;
|
||||
- (int) setReadFlag: (uint8_t) flag;
|
||||
- (enum mapistore_error) saveMessage;
|
||||
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx;
|
||||
|
||||
- (NSArray *) activeContainerMessageTables;
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
- (void) copyToMessage: (MAPIStoreMessage *) newMessage inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
|
||||
/* subclasses */
|
||||
- (void) save;
|
||||
- (void) save: (TALLOC_CTX *) memCtx;
|
||||
|
||||
/* attachments (subclasses) */
|
||||
- (MAPIStoreAttachment *) createAttachment;
|
||||
|
||||
@@ -45,11 +45,10 @@
|
||||
#import "NSData+MAPIStore.h"
|
||||
#import "NSObject+MAPIStore.h"
|
||||
#import "NSString+MAPIStore.h"
|
||||
#import "RTFHandler.h"
|
||||
|
||||
#import "MAPIStoreMessage.h"
|
||||
|
||||
#include <unrtf.h>
|
||||
|
||||
#undef DEBUG
|
||||
#include <stdbool.h>
|
||||
#include <gen_ndr/exchange.h>
|
||||
@@ -60,17 +59,6 @@ static Class MAPIStoreFolderK, MAPIStoreEmbeddedMessageK;
|
||||
|
||||
static NSString *resourcesDir = nil;
|
||||
|
||||
/* rtf conversion via unrtf */
|
||||
static int
|
||||
unrtf_data_output (void *data, const char *str, size_t str_len)
|
||||
{
|
||||
NSMutableData *rtfData = data;
|
||||
|
||||
[rtfData appendBytes: str length: str_len];
|
||||
|
||||
return str_len;
|
||||
}
|
||||
|
||||
static NSData *
|
||||
uncompressRTF (NSData *compressedRTF)
|
||||
{
|
||||
@@ -97,22 +85,17 @@ rtf2html (NSData *compressedRTF)
|
||||
{
|
||||
NSData *rtf;
|
||||
NSMutableData *html = nil;
|
||||
int rc;
|
||||
struct unRTFOptions unrtfOptions;
|
||||
|
||||
rtf = uncompressRTF (compressedRTF);
|
||||
if (rtf)
|
||||
{
|
||||
html = [NSMutableData data];
|
||||
memset (&unrtfOptions, 0, sizeof (struct unRTFOptions));
|
||||
unrtf_set_output_device (&unrtfOptions, unrtf_data_output, html);
|
||||
unrtfOptions.config_directory = [resourcesDir UTF8String];
|
||||
unrtfOptions.output_format = "html";
|
||||
unrtfOptions.nopict_mode = YES;
|
||||
rc = unrtf_convert_from_string (&unrtfOptions,
|
||||
[rtf bytes], [rtf length]);
|
||||
if (!rc)
|
||||
html = nil;
|
||||
//html = [NSMutableData data];
|
||||
RTFHandler *handler;
|
||||
|
||||
handler = [[RTFHandler alloc] initWithData: rtf];
|
||||
AUTORELEASE(handler);
|
||||
|
||||
html = [handler parse];
|
||||
}
|
||||
|
||||
return html;
|
||||
@@ -139,7 +122,7 @@ rtf2html (NSData *compressedRTF)
|
||||
|
||||
- (id) init
|
||||
{
|
||||
[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
|
||||
//[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
|
||||
|
||||
if ((self = [super init]))
|
||||
{
|
||||
@@ -153,7 +136,7 @@ rtf2html (NSData *compressedRTF)
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
|
||||
//[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
|
||||
[activeUserRoles release];
|
||||
[attachmentKeys release];
|
||||
[attachmentParts release];
|
||||
@@ -260,7 +243,7 @@ rtf2html (NSData *compressedRTF)
|
||||
struct mapistore_message_recipient *recipient;
|
||||
NSUInteger count;
|
||||
|
||||
[self logWithFormat: @"METHOD '%s'", __FUNCTION__];
|
||||
//[self logWithFormat: @"METHOD '%s'", __FUNCTION__];
|
||||
|
||||
recipients = [NSMutableDictionary new];
|
||||
recipientProperties = [NSDictionary dictionaryWithObject: recipients
|
||||
@@ -450,7 +433,7 @@ rtf2html (NSData *compressedRTF)
|
||||
NSString *key;
|
||||
MAPIStoreAttachment *attachment, *newAttachment;
|
||||
|
||||
[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
|
||||
//[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
|
||||
|
||||
//memCtx = talloc_zero (NULL, TALLOC_CTX);
|
||||
|
||||
@@ -477,7 +460,7 @@ rtf2html (NSData *compressedRTF)
|
||||
//talloc_free (memCtx);
|
||||
}
|
||||
|
||||
- (enum mapistore_error) saveMessage
|
||||
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
NSArray *containerTables;
|
||||
@@ -490,7 +473,7 @@ rtf2html (NSData *compressedRTF)
|
||||
BOOL userIsOwner;
|
||||
MAPIStoreMessage *mainMessage;
|
||||
|
||||
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
||||
|
||||
context = [self context];
|
||||
ownerUser = [[self userContext] sogoUser];
|
||||
@@ -518,7 +501,7 @@ rtf2html (NSData *compressedRTF)
|
||||
|
||||
/* folder modified */
|
||||
notif_parameters
|
||||
= talloc_zero(NULL, struct mapistore_object_notification_parameters);
|
||||
= talloc_zero(memCtx, struct mapistore_object_notification_parameters);
|
||||
notif_parameters->object_id = folderId;
|
||||
if (isNew)
|
||||
{
|
||||
@@ -542,7 +525,7 @@ rtf2html (NSData *compressedRTF)
|
||||
if (isNew)
|
||||
{
|
||||
notif_parameters
|
||||
= talloc_zero(NULL,
|
||||
= talloc_zero(memCtx,
|
||||
struct mapistore_object_notification_parameters);
|
||||
notif_parameters->object_id = [self objectId];
|
||||
notif_parameters->folder_id = folderId;
|
||||
@@ -562,7 +545,7 @@ rtf2html (NSData *compressedRTF)
|
||||
[[containerTables objectAtIndex: count] restrictedChildKeys];
|
||||
}
|
||||
|
||||
[self save];
|
||||
[self save: memCtx];
|
||||
/* We make sure that any change-related properties are removes from the
|
||||
properties dictionary, to make sure that related methods will be
|
||||
invoked the next time they are requested. */
|
||||
@@ -937,7 +920,7 @@ rtf2html (NSData *compressedRTF)
|
||||
return MAPISTORE_ERROR;
|
||||
}
|
||||
|
||||
- (void) save
|
||||
- (void) save: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
@@ -284,6 +284,9 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// The GlobCnt is 6 bytes long.
|
||||
//
|
||||
- (NSData *) getReplicaKeyFromGlobCnt: (uint64_t) objectCnt
|
||||
{
|
||||
struct mapistore_connection_info *connInfo;
|
||||
|
||||
@@ -68,7 +68,7 @@ sogo_backend_atexit (void)
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
NSLog (@"allocated classes:\n%s", GSDebugAllocationList (YES));
|
||||
//NSLog (@"allocated classes:\n%s", GSDebugAllocationList (YES));
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
}
|
||||
@@ -611,7 +611,7 @@ sogo_folder_move_copy_messages(void *folder_object,
|
||||
|
||||
static enum mapistore_error
|
||||
sogo_folder_move_folder(void *folder_object, void *target_folder_object,
|
||||
const char *new_folder_name)
|
||||
TALLOC_CTX *mem_ctx, const char *new_folder_name)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
MAPIStoreFolder *moveFolder, *targetFolder;
|
||||
@@ -643,7 +643,9 @@ sogo_folder_move_folder(void *folder_object, void *target_folder_object,
|
||||
rc = [moveFolder moveCopyToFolder: targetFolder
|
||||
withNewName: newFolderName
|
||||
isMove: YES
|
||||
isRecursive: YES];
|
||||
isRecursive: YES
|
||||
inMemCtx: mem_ctx];
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
}
|
||||
@@ -656,7 +658,7 @@ sogo_folder_move_folder(void *folder_object, void *target_folder_object,
|
||||
}
|
||||
|
||||
static enum mapistore_error
|
||||
sogo_folder_copy_folder(void *folder_object, void *target_folder_object,
|
||||
sogo_folder_copy_folder(void *folder_object, void *target_folder_object, TALLOC_CTX *mem_ctx,
|
||||
bool recursive, const char *new_folder_name)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
@@ -683,7 +685,9 @@ sogo_folder_copy_folder(void *folder_object, void *target_folder_object,
|
||||
rc = [copyFolder moveCopyToFolder: targetFolder
|
||||
withNewName: newFolderName
|
||||
isMove: NO
|
||||
isRecursive: recursive];
|
||||
isRecursive: recursive
|
||||
inMemCtx: mem_ctx];
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
}
|
||||
@@ -1020,7 +1024,7 @@ sogo_message_set_read_flag (void *message_object, uint8_t flag)
|
||||
}
|
||||
|
||||
static enum mapistore_error
|
||||
sogo_message_save (void *message_object)
|
||||
sogo_message_save (void *message_object, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct MAPIStoreTallocWrapper *wrapper;
|
||||
NSAutoreleasePool *pool;
|
||||
@@ -1035,7 +1039,7 @@ sogo_message_save (void *message_object)
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [message saveMessage];
|
||||
rc = [message saveMessage: mem_ctx];
|
||||
// [context tearDownRequest];
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
@@ -1225,7 +1229,7 @@ sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restr
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
[table setRestrictions: restrictions];
|
||||
[table cleanupCaches];
|
||||
//[table cleanupCaches];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
*table_status = TBLSTAT_COMPLETE;
|
||||
[pool release];
|
||||
|
||||
@@ -375,12 +375,12 @@ static Class NSDataK, NSStringK;
|
||||
|
||||
- (void) setRestrictions: (const struct mapi_SRestriction *) res
|
||||
{
|
||||
EOQualifier *oldRestriction;
|
||||
//EOQualifier *oldRestriction;
|
||||
|
||||
// [self logWithFormat: @"set restriction to (table type: %d): %@",
|
||||
// type, MAPIStringForRestriction (res)];
|
||||
|
||||
oldRestriction = restriction;
|
||||
//oldRestriction = restriction;
|
||||
[restriction autorelease];
|
||||
if (res)
|
||||
restrictionState = [self evaluateRestriction: res
|
||||
@@ -396,11 +396,11 @@ static Class NSDataK, NSStringK;
|
||||
// FIXME: we should not flush the caches if the restrictions matches
|
||||
[self cleanupCaches];
|
||||
|
||||
if (restriction)
|
||||
[self logWithFormat: @"restriction set to EOQualifier: %@",
|
||||
restriction];
|
||||
else if (oldRestriction)
|
||||
[self logWithFormat: @"restriction unset (was %@)", oldRestriction];
|
||||
//if (restriction)
|
||||
// [self logWithFormat: @"restriction set to EOQualifier: %@",
|
||||
// restriction];
|
||||
// else if (oldRestriction)
|
||||
// [self logWithFormat: @"restriction unset (was %@)", oldRestriction];
|
||||
}
|
||||
|
||||
- (MAPIRestrictionState) evaluateNotRestriction: (struct mapi_SNotRestriction *) res
|
||||
|
||||
@@ -357,7 +357,7 @@
|
||||
return rc;
|
||||
}
|
||||
|
||||
- (void) save
|
||||
- (void) save:(TALLOC_CTX *) memCtx
|
||||
{
|
||||
iCalCalendar *vCalendar;
|
||||
iCalToDo *vToDo;
|
||||
|
||||
@@ -52,9 +52,9 @@ static inline NSNumber *
|
||||
MAPIPropertyKey (enum MAPITAGS propTag)
|
||||
{
|
||||
#if (GS_SIZEOF_LONG == 4)
|
||||
return [NSNumber numberWithUnsignedLong: propTag];
|
||||
return [NSString stringWithFormat: @"%ul", propTag];
|
||||
#elif (GS_SIZEOF_INT == 4)
|
||||
return [NSNumber numberWithUnsignedInt: propTag];
|
||||
return [NSString stringWithFormat: @"%u", propTag];
|
||||
#else
|
||||
#error No suitable type for 4 bytes integers
|
||||
#endif
|
||||
|
||||
@@ -342,7 +342,8 @@ MAPIStoreDumpMessageProperties (NSDictionary *properties)
|
||||
{
|
||||
NSNumber *key;
|
||||
NSArray *allKeys;
|
||||
NSUInteger keyAsInt, count, max;
|
||||
NSUInteger count, max;
|
||||
NSUInteger keyAsInt;
|
||||
id value;
|
||||
|
||||
allKeys = [properties allKeys];
|
||||
@@ -351,7 +352,7 @@ MAPIStoreDumpMessageProperties (NSDictionary *properties)
|
||||
NSLog (@"message properties (%d):", max);
|
||||
|
||||
value = [properties objectForKey: @"recipients"];
|
||||
if (value)
|
||||
if (value)
|
||||
NSLog (@" recipients: %@", value);
|
||||
|
||||
for (count = 0; count < max; count++)
|
||||
@@ -363,7 +364,7 @@ MAPIStoreDumpMessageProperties (NSDictionary *properties)
|
||||
value = [properties objectForKey: key];
|
||||
NSLog (@" 0x%.4x: %@ (%@)",
|
||||
keyAsInt, value,
|
||||
NSStringFromClass ([value class]));
|
||||
NSStringFromClass ([value class]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSCharacterSet.h>
|
||||
#import <Foundation/NSData.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSMapTable.h>
|
||||
@@ -107,15 +108,17 @@ static NSMapTable *contextsTable = nil;
|
||||
password = nil;
|
||||
|
||||
path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR
|
||||
@"/mapistore/%@/password", newUsername];
|
||||
@"/mapistore/%@/password", newUsername];
|
||||
|
||||
content = [NSData dataWithContentsOfFile: path];
|
||||
|
||||
if (content)
|
||||
{
|
||||
password = [[NSString alloc] initWithData: content
|
||||
encoding: NSUTF8StringEncoding];
|
||||
encoding: NSUTF8StringEncoding];
|
||||
[password autorelease];
|
||||
password = [password stringByTrimmingCharactersInSet:
|
||||
[NSCharacterSet characterSetWithCharactersInString: @"\r\n"]];
|
||||
}
|
||||
|
||||
return password;
|
||||
|
||||
@@ -148,6 +148,7 @@ static void _fillFlatUIDWithGUID (struct FlatUID_r *flatUID, const struct GUID *
|
||||
- (struct XID *) asXIDInMemCtx: (void *) memCtx
|
||||
{
|
||||
struct XID *xid;
|
||||
uint8_t *bytes;
|
||||
NSUInteger max;
|
||||
|
||||
max = [self length];
|
||||
@@ -158,7 +159,9 @@ static void _fillFlatUIDWithGUID (struct FlatUID_r *flatUID, const struct GUID *
|
||||
[self _extractGUID: &xid->GUID];
|
||||
|
||||
xid->Size = max - 16;
|
||||
xid->Data = talloc_memdup (xid, [self bytes] + 16, xid->Size);
|
||||
|
||||
bytes = (uint8_t *) [self bytes];
|
||||
xid->Data = talloc_memdup (xid, (bytes+16), xid->Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -50,8 +50,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
wrapper = data;
|
||||
//NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject);
|
||||
NSLog (@"destroying wrapped object (wrapper: %p)", wrapper);
|
||||
//NSLog (@"destroying wrapped object (wrapper: %p; object: %p (%@))...\n", wrapper, wrapper->instance, NSStringFromClass([wrapper->instance class]));
|
||||
[wrapper->instance release];
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
@@ -67,8 +66,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
|
||||
talloc_set_destructor ((void *) wrapper, MAPIStoreTallocWrapperDestroy);
|
||||
wrapper->instance = self;
|
||||
[self retain];
|
||||
NSLog (@"returning wrapper: %p; object: %p", wrapper, self);
|
||||
|
||||
//NSLog (@"returning wrapper: %p; object: %p (%@)", wrapper, self, NSStringFromClass([self class]));
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#import <Foundation/NSValue.h>
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
|
||||
#import "BSONCodec.h"
|
||||
|
||||
const char *indentationStep = " ";
|
||||
|
||||
@interface NSObject (plext)
|
||||
@@ -142,41 +144,43 @@ const char *indentationStep = " ";
|
||||
static void
|
||||
OCDumpPListData (NSData *content)
|
||||
{
|
||||
NSDictionary *d;
|
||||
NSPropertyListFormat format;
|
||||
NSString *error = nil;
|
||||
const char *formatName;
|
||||
//NSDictionary *d;
|
||||
//NSPropertyListFormat format;
|
||||
//NSString *error = nil;
|
||||
//const char *formatName;
|
||||
|
||||
d = [NSPropertyListSerialization propertyListFromData: content
|
||||
mutabilityOption: NSPropertyListImmutable
|
||||
format: &format
|
||||
errorDescription: &error];
|
||||
if (d)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case NSPropertyListOpenStepFormat:
|
||||
formatName = "OpenStep";
|
||||
break;
|
||||
case NSPropertyListXMLFormat_v1_0:
|
||||
formatName = "XML";
|
||||
break;
|
||||
case NSPropertyListBinaryFormat_v1_0:
|
||||
formatName = "Binary";
|
||||
break;
|
||||
case NSPropertyListGNUstepFormat:
|
||||
formatName = "GNUstep";
|
||||
break;
|
||||
case NSPropertyListGNUstepBinaryFormat:
|
||||
formatName = "GNUstep binary";
|
||||
break;
|
||||
default: formatName = "unknown";
|
||||
}
|
||||
//d = [NSPropertyListSerialization propertyListFromData: content
|
||||
// mutabilityOption: NSPropertyListImmutable
|
||||
// format: &format
|
||||
// errorDescription: &error];
|
||||
//d = [content BSONValue];
|
||||
|
||||
printf ("File format is: %s\n", formatName);
|
||||
[d displayWithIndentation: 0];
|
||||
printf ("\n");
|
||||
}
|
||||
else
|
||||
printf ("an error occurred: %s\n", [error UTF8String]);
|
||||
// if (d)
|
||||
// {
|
||||
// switch (format)
|
||||
// {
|
||||
// case NSPropertyListOpenStepFormat:
|
||||
// formatName = "OpenStep";
|
||||
// break;
|
||||
// case NSPropertyListXMLFormat_v1_0:
|
||||
// formatName = "XML";
|
||||
// break;
|
||||
// case NSPropertyListBinaryFormat_v1_0:
|
||||
// formatName = "Binary";
|
||||
// break;
|
||||
// case NSPropertyListGNUstepFormat:
|
||||
// formatName = "GNUstep";
|
||||
// break;
|
||||
// case NSPropertyListGNUstepBinaryFormat:
|
||||
// formatName = "GNUstep binary";
|
||||
// break;
|
||||
// default: formatName = "unknown";
|
||||
// }
|
||||
|
||||
// printf ("File format is: %s\n", formatName);
|
||||
// [d displayWithIndentation: 0];
|
||||
// printf ("\n");
|
||||
// }
|
||||
// else
|
||||
// printf ("an error occurred: %s\n", [error UTF8String]);
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright (C) 2005-2012 Inverse inc.
|
||||
|
||||
This file is part of SOGo.
|
||||
|
||||
SOGo is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with OGo; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
#include <Foundation/NSObject.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@interface RTFHandler : NSObject
|
||||
{
|
||||
NSMapTable *_charsets;
|
||||
NSMutableData *_html;
|
||||
NSData *_data;
|
||||
|
||||
const char *_bytes;
|
||||
int _current_pos;
|
||||
int _len;
|
||||
}
|
||||
|
||||
- (id) initWithData: (NSData *) theData;
|
||||
- (NSMutableData *) parse;
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@interface RTFStack: NSObject
|
||||
{
|
||||
NSMutableArray *a;
|
||||
}
|
||||
- (void) push: (id) theObject;
|
||||
- (id) pop;
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@interface RTFFormattingOptions : NSObject
|
||||
{
|
||||
@public
|
||||
BOOL bold;
|
||||
BOOL italic;
|
||||
BOOL underline;
|
||||
BOOL strikethrough;
|
||||
int font_index;
|
||||
int color_index;
|
||||
int start_pos;
|
||||
}
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@interface RTFFontInfo : NSObject
|
||||
{
|
||||
@public
|
||||
NSString *family;
|
||||
NSString *charset;
|
||||
NSString *name;
|
||||
unsigned int pitch;
|
||||
unsigned int index;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
// \fX - font, index in font table
|
||||
//
|
||||
@interface RTFFontTable : NSObject
|
||||
{
|
||||
@public
|
||||
NSMapTable *fontInfos;
|
||||
}
|
||||
|
||||
- (void) addFontInfo: (RTFFontInfo *) theFontInfo
|
||||
atIndex: (unsigned int ) theIndex;
|
||||
|
||||
- (RTFFontInfo *) fontInfoAtIndex: (unsigned int ) theIndex;
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@interface RTFColorDef : NSObject
|
||||
{
|
||||
@public
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
// {\colortbl\red0\green0\blue0;\red128\green0\blue0;\red255\green0\blue0;}
|
||||
//
|
||||
// \cfX - color/foreground - index
|
||||
// \cbX - color/background - index
|
||||
//
|
||||
//
|
||||
@interface RTFColorTable : NSObject
|
||||
{
|
||||
@public
|
||||
NSMutableArray *colorDefs;
|
||||
}
|
||||
|
||||
- (void) addColorDef: (RTFColorDef *) theColorDef;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,961 @@
|
||||
/*
|
||||
Copyright (C) 2005-2013 Inverse inc.
|
||||
|
||||
This file is part of SOGo.
|
||||
|
||||
SOGo is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with OGo; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "RTFHandler.h"
|
||||
#include <Foundation/NSValue.h>
|
||||
|
||||
//
|
||||
// Useful macros
|
||||
//
|
||||
#define ADVANCE _bytes++; _current_pos++;
|
||||
#define REWIND _bytes--; _current_pos--;
|
||||
|
||||
|
||||
//
|
||||
// Charset definitions. See http://msdn.microsoft.com/en-us/goglobal/bb964654 for all details.
|
||||
//
|
||||
const unsigned short ansicpg1250[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x0000, 0x201a, 0x0000, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
|
||||
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
|
||||
0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
|
||||
0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
|
||||
0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
|
||||
0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
|
||||
0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
|
||||
0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9 };
|
||||
|
||||
const unsigned short ansicpg1251[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
|
||||
0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
|
||||
0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
|
||||
0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
|
||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
|
||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
|
||||
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
|
||||
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f };
|
||||
|
||||
const unsigned short ansicpg1252[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017d, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff };
|
||||
|
||||
const unsigned short ansicpg1253[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, 0x203a, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x00a0, 0x0385, 0x0386, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x0000, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x2015,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x00b5, 0x00b6, 0x00b7, 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f,
|
||||
0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
|
||||
0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
|
||||
0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
|
||||
0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000 };
|
||||
|
||||
const unsigned short ansicpg1254[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x0000, 0x0178,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff };
|
||||
|
||||
const unsigned short ansicpg1255[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0000, 0x203a, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, 0x05b8, 0x05b9, 0x0000, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf,
|
||||
0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
|
||||
0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x200e, 0x200f, 0x0000 };
|
||||
|
||||
const unsigned short ansicpg1256[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
|
||||
0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba,
|
||||
0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f,
|
||||
0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
|
||||
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7, 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643,
|
||||
0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef,
|
||||
0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2 };
|
||||
|
||||
const unsigned short ansicpg1257[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x0000, 0x201a, 0x0000, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00a8, 0x02c7, 0x00b8,
|
||||
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, 0x203a, 0x0000, 0x00af, 0x02db, 0x0000,
|
||||
0x00a0, 0x0000, 0x00a2, 0x00a3, 0x00a4, 0x0000, 0x00a6, 0x00a7, 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
|
||||
0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
|
||||
0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df,
|
||||
0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
|
||||
0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x02d9 };
|
||||
|
||||
const unsigned short ansicpg1258[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0000, 0x203a, 0x0153, 0x0000, 0x0000, 0x0178,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x0300, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x0110, 0x00d1, 0x0309, 0x00d3, 0x00d4, 0x01a0, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x01af, 0x0303, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0301, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x0111, 0x00f1, 0x0323, 0x00f3, 0x00f4, 0x01a1, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x01b0, 0x20ab, 0x00ff };
|
||||
|
||||
const unsigned short ansicpg874[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x20ac, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
|
||||
0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
|
||||
0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
|
||||
0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0e3f,
|
||||
0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
|
||||
0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0x0000, 0x0000, 0x0000, 0x0000 };
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@implementation RTFStack
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
a = [[NSMutableArray alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
RELEASE(a);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) push: (id) theObject
|
||||
{
|
||||
[a addObject: theObject];
|
||||
}
|
||||
|
||||
- (id) pop
|
||||
{
|
||||
id o = nil;
|
||||
|
||||
if ([a count])
|
||||
{
|
||||
o = AUTORELEASE([[a lastObject] retain]);
|
||||
[a removeLastObject];
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
- (id) top
|
||||
{
|
||||
id o = nil;
|
||||
|
||||
if ([a count])
|
||||
{
|
||||
o = AUTORELEASE([[a lastObject] retain]);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@implementation RTFFormattingOptions
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@implementation RTFFontInfo
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
RELEASE(family);
|
||||
RELEASE(charset);
|
||||
RELEASE(name);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@implementation RTFFontTable
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fontInfos = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 128);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
NSFreeMapTable(fontInfos);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) addFontInfo: (RTFFontInfo *) theFontInfo
|
||||
atIndex: (unsigned int) theIndex
|
||||
{
|
||||
NSNumber *key;
|
||||
|
||||
key = [NSNumber numberWithInt: theIndex];
|
||||
NSMapInsert(fontInfos, key, (void*) theFontInfo);
|
||||
}
|
||||
|
||||
- (RTFFontInfo *) fontInfoAtIndex: (unsigned int) theIndex
|
||||
{
|
||||
NSNumber *key;
|
||||
|
||||
key = [NSNumber numberWithInt: theIndex];
|
||||
return NSMapGet(fontInfos, key);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@implementation RTFColorDef
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@implementation RTFColorTable
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
colorDefs = [[NSMutableArray alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
RELEASE(colorDefs);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) addColorDef: (RTFColorDef *) theColorDef
|
||||
{
|
||||
[colorDefs addObject: theColorDef];
|
||||
}
|
||||
|
||||
- (RTFColorDef *) colorDefAtIndex: (unsigned int) theIndex
|
||||
{
|
||||
return [colorDefs objectAtIndex: theIndex];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@implementation RTFHandler
|
||||
|
||||
- (id) initWithData: (NSData *) theData
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
ASSIGN(_data, theData);
|
||||
_bytes = (char *)[_data bytes];
|
||||
_len = [_data length];
|
||||
_current_pos = 0;
|
||||
|
||||
_charsets = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 10);
|
||||
NSMapInsert(_charsets, @"ansicpg1250", ansicpg1250);
|
||||
NSMapInsert(_charsets, @"ansicpg1251", ansicpg1251);
|
||||
NSMapInsert(_charsets, @"ansicpg1252", ansicpg1252);
|
||||
NSMapInsert(_charsets, @"ansicpg1253", ansicpg1253);
|
||||
NSMapInsert(_charsets, @"ansicpg1254", ansicpg1254);
|
||||
NSMapInsert(_charsets, @"ansicpg1255", ansicpg1255);
|
||||
NSMapInsert(_charsets, @"ansicpg1256", ansicpg1256);
|
||||
NSMapInsert(_charsets, @"ansicpg1257", ansicpg1257);
|
||||
NSMapInsert(_charsets, @"ansicpg1258", ansicpg1258);
|
||||
NSMapInsert(_charsets, @"ansicpg874", ansicpg874);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
NSFreeMapTable(_charsets);
|
||||
RELEASE(_data);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (const char *) parseControlWord: (unsigned int *) len
|
||||
{
|
||||
const char *start, *end;
|
||||
|
||||
start = ADVANCE;
|
||||
|
||||
while (isalnum(*_bytes) || *_bytes == '-')
|
||||
{
|
||||
ADVANCE;
|
||||
}
|
||||
end = _bytes;
|
||||
|
||||
*len = end-start-1;
|
||||
return start+1;
|
||||
}
|
||||
|
||||
//
|
||||
// {\colortbl\red0\green0\blue0;\red128\green0\blue0;\red255\green0\blue0;}
|
||||
//
|
||||
- (RTFColorTable *) parseColorTable
|
||||
{
|
||||
RTFColorTable *colorTable;
|
||||
RTFColorDef *colorDef;
|
||||
|
||||
colorTable = [[[RTFColorTable alloc] init] autorelease];
|
||||
colorDef = [[[RTFColorDef alloc] init] autorelease];
|
||||
|
||||
while (*_bytes != '}')
|
||||
{
|
||||
if (*_bytes == ';')
|
||||
{
|
||||
[colorTable addColorDef: colorDef];
|
||||
colorDef = [[[RTFColorDef alloc] init] autorelease];
|
||||
ADVANCE;
|
||||
}
|
||||
else if (*_bytes == '\\')
|
||||
{
|
||||
const char *cw;
|
||||
unsigned int len;
|
||||
NSString *s;
|
||||
|
||||
cw = [self parseControlWord: &len];
|
||||
|
||||
// Skip our control word
|
||||
//if (strncmp(start+1, "colortbl", len) == 0)
|
||||
// continue;
|
||||
|
||||
s = [[NSString alloc] initWithBytesNoCopy: (void *)cw
|
||||
length: len
|
||||
encoding: NSASCIIStringEncoding
|
||||
freeWhenDone: NO];
|
||||
[s autorelease];
|
||||
|
||||
if ([s hasPrefix: @"red"])
|
||||
{
|
||||
colorDef->red = [[s substringFromIndex: 3] intValue];
|
||||
}
|
||||
else if ([s hasPrefix: @"green"])
|
||||
{
|
||||
colorDef->green = [[s substringFromIndex: 4] intValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
colorDef->blue = [[s substringFromIndex: 4] intValue];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ADVANCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return colorTable;
|
||||
}
|
||||
|
||||
//
|
||||
// Possible formats:
|
||||
//
|
||||
// {\fonttbl\f0\fswiss Helvetica;}
|
||||
// {\fonttbl{\f0\froman\fcharset0\fprq2 Arial;}{\f1\fswiss\fprq2\fcharset0 Arial;}}
|
||||
//
|
||||
// FIXME: Complex ones not handled right now:
|
||||
//
|
||||
// {\fonttbl{\f2\fnil\fcharset256\fprq2{\*\panose 00020703090202050204}Courier New;}{...
|
||||
// {\fonttbl{\f31\fnil\fcharset0\fprq0 Times New Roman Monotype{\*\falt Times New Roman};}{...
|
||||
//
|
||||
// We receive the full string.
|
||||
//
|
||||
- (RTFFontTable *) parseFontTable
|
||||
{
|
||||
NSMutableString *fontName;
|
||||
RTFFontTable *fontTable;
|
||||
RTFFontInfo *fontInfo;
|
||||
|
||||
unsigned int count;
|
||||
|
||||
fontTable = [[[RTFFontTable alloc] init] autorelease];
|
||||
fontName = nil;
|
||||
count = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (*_bytes == '{')
|
||||
{
|
||||
if (fontTable)
|
||||
{
|
||||
fontInfo = [[[RTFFontInfo alloc] init] autorelease];
|
||||
fontName = [[[NSMutableString alloc] init] autorelease];
|
||||
}
|
||||
ADVANCE;
|
||||
count++;
|
||||
}
|
||||
else if (*_bytes == '}')
|
||||
{
|
||||
if (fontTable) //&& ![NSAllMapTableValues(fontTable->fontInfos) containsObject: fontInfo])
|
||||
{
|
||||
ASSIGN(fontInfo->name, fontName);
|
||||
[fontTable addFontInfo: fontInfo atIndex: fontInfo->index];
|
||||
}
|
||||
ADVANCE;
|
||||
count--;
|
||||
}
|
||||
else if (*_bytes == '\\')
|
||||
{
|
||||
const char *cw;
|
||||
unsigned int len;
|
||||
NSString *s;
|
||||
|
||||
cw = [self parseControlWord: &len];
|
||||
|
||||
// Skip our control word
|
||||
if (strncmp((const char*)cw, "fonttbl", len) == 0)
|
||||
continue;
|
||||
|
||||
// We must at least parse <fontnum><fontfamily><fcharset>
|
||||
s = [[NSString alloc] initWithBytesNoCopy: (void *)cw+1
|
||||
length: len-1
|
||||
encoding: NSASCIIStringEncoding
|
||||
freeWhenDone: NO];
|
||||
[s autorelease];
|
||||
|
||||
// If we got a fontnum, let's parse all three fields at once)
|
||||
if (isdigit(*(cw+1)))
|
||||
{
|
||||
fontInfo->index = [s intValue];
|
||||
|
||||
// We now parse <fontfamily><fcharset>
|
||||
cw = [self parseControlWord: &len];
|
||||
fontInfo->family = [[NSString alloc] initWithBytesNoCopy: (void *)cw+1
|
||||
length: len-1
|
||||
encoding: NSASCIIStringEncoding
|
||||
freeWhenDone: NO];
|
||||
|
||||
cw = [self parseControlWord: &len];
|
||||
fontInfo->charset = [[NSString alloc] initWithBytesNoCopy: (void *)cw+1
|
||||
length: len-1
|
||||
encoding: NSASCIIStringEncoding
|
||||
freeWhenDone: NO];
|
||||
|
||||
// We now skip everything until we find our final group closer ('}')
|
||||
int cc = 1;
|
||||
|
||||
do
|
||||
{
|
||||
if (*_bytes == '{')
|
||||
cc++;
|
||||
if (*_bytes == '}')
|
||||
cc--;
|
||||
|
||||
ADVANCE;
|
||||
}
|
||||
while (cc != 0);
|
||||
|
||||
// move back our buffer;
|
||||
REWIND;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isalnum(*_bytes))
|
||||
[fontName appendFormat: @"%c", *_bytes];
|
||||
ADVANCE;
|
||||
}
|
||||
} while (count != 0);
|
||||
|
||||
return fontTable;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) parseStyleSheet
|
||||
{
|
||||
unsigned int count;
|
||||
|
||||
count = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (*_bytes == '{')
|
||||
{
|
||||
count++;
|
||||
}
|
||||
else if (*_bytes == '}')
|
||||
{
|
||||
count--;
|
||||
}
|
||||
ADVANCE;
|
||||
|
||||
} while (count != 0);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) parsePicture
|
||||
{
|
||||
// Do the same as -parseStyleSheet for now, that is, ignore everything.
|
||||
[self parseStyleSheet];
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (NSMutableData *) parse
|
||||
{
|
||||
RTFFormattingOptions *formattingOptions;
|
||||
RTFColorTable *colorTable;
|
||||
RTFFontTable *fontTable;
|
||||
RTFStack *stack;
|
||||
|
||||
unsigned short *charset;
|
||||
char c;
|
||||
|
||||
stack = [[RTFStack alloc] init];
|
||||
fontTable = nil;
|
||||
colorTable = nil;
|
||||
charset = NULL;
|
||||
|
||||
_html = [[NSMutableData alloc] init];
|
||||
[_html appendBytes: "<html><meta charset='utf-8'><body>" length: 34];
|
||||
|
||||
|
||||
|
||||
// Check if we got RTF data
|
||||
if (_len > 4 && strncmp((const char*)_bytes, "{\\rtf", 4) != 0)
|
||||
return NO;
|
||||
|
||||
while (_current_pos < _len)
|
||||
{
|
||||
c = *_bytes;
|
||||
|
||||
// RTF control code
|
||||
if (c == '\\')
|
||||
{
|
||||
unsigned int len;
|
||||
const char *cw;
|
||||
NSString *s;
|
||||
|
||||
if (*(_bytes+1) == '\'' && charset)
|
||||
{
|
||||
// A hexadecimal value, based on the specified character set (may be used to identify 8-bit values).
|
||||
NSString *s;
|
||||
NSData *d;
|
||||
|
||||
const char *b1, *b2;
|
||||
unsigned short index;
|
||||
|
||||
ADVANCE;
|
||||
ADVANCE;
|
||||
|
||||
b1 = ADVANCE;
|
||||
b2 = ADVANCE;
|
||||
|
||||
index = (isdigit(*b1) ? *b1 - 48 : toupper(*b1) - 55) * 16;
|
||||
index += (isdigit(*b2) ? *b2 - 48 : toupper(*b2) - 55);
|
||||
|
||||
s = [NSString stringWithCharacters: &(charset[index]) length: 1];
|
||||
d = [s dataUsingEncoding: NSUTF8StringEncoding];
|
||||
[_html appendData: d];
|
||||
continue;
|
||||
}
|
||||
else if (*(_bytes+1) == '*')
|
||||
{
|
||||
int cc = 1;
|
||||
|
||||
do
|
||||
{
|
||||
if (*_bytes == '{')
|
||||
cc++;
|
||||
if (*_bytes == '}')
|
||||
cc--;
|
||||
|
||||
ADVANCE;
|
||||
}
|
||||
while (cc != 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
cw = [self parseControlWord: &len];
|
||||
|
||||
s = [[NSString alloc] initWithBytesNoCopy: (void *)cw
|
||||
length: len
|
||||
encoding: NSASCIIStringEncoding
|
||||
freeWhenDone: NO];
|
||||
[s autorelease];
|
||||
|
||||
if (strncmp(cw, "ansicpg", 7) == 0)
|
||||
{
|
||||
charset = NSMapGet(_charsets, s);
|
||||
}
|
||||
else if (strncmp(cw, "fonttbl", 7) == 0)
|
||||
{
|
||||
// We rewind our buffer so we start at the beginning of {\fonttbl...
|
||||
_bytes = cw-2;
|
||||
_current_pos -= 10;
|
||||
fontTable = [self parseFontTable];
|
||||
|
||||
// We go back 1 byte in order to end our section properly ('}' character
|
||||
REWIND;
|
||||
}
|
||||
else if (strncmp(cw, "stylesheet", 10) == 0)
|
||||
{
|
||||
_bytes = cw-2;
|
||||
_current_pos -= 13;
|
||||
[self parseStyleSheet];
|
||||
REWIND;
|
||||
}
|
||||
else if (strncmp(cw, "colortbl", 8) == 0)
|
||||
{
|
||||
colorTable = [self parseColorTable];
|
||||
}
|
||||
else if (strncmp(cw, "pict", 4) == 0)
|
||||
{
|
||||
_bytes = cw-2;
|
||||
_current_pos -= 7;
|
||||
[self parsePicture];
|
||||
REWIND;
|
||||
}
|
||||
else if ([s isEqualToString: @"b"] && formattingOptions)
|
||||
{
|
||||
[_html appendBytes: "<b>" length: 3];
|
||||
formattingOptions->bold = YES;
|
||||
}
|
||||
else if ([s isEqualToString: @"b0"] && formattingOptions)
|
||||
{
|
||||
[_html appendBytes: "</b>" length: 4];
|
||||
formattingOptions->bold = NO;
|
||||
}
|
||||
else if ([s hasPrefix: @"cf"] && [s length] > 2)
|
||||
{
|
||||
RTFColorDef *colorDef;
|
||||
int color_index;
|
||||
char *v;
|
||||
|
||||
color_index = [[s substringFromIndex: 2] intValue];
|
||||
|
||||
if (!formattingOptions)
|
||||
continue;
|
||||
|
||||
if (formattingOptions->color_index >= 0) // && color_index != formattingOptions->color_index)
|
||||
{
|
||||
[_html appendBytes: "</font>" length: 7];
|
||||
}
|
||||
|
||||
formattingOptions->color_index = color_index;
|
||||
colorDef = [colorTable colorDefAtIndex: color_index];
|
||||
|
||||
v = malloc(23*sizeof(char));
|
||||
memset(v, 0, 23);
|
||||
sprintf(v, "<font color=\"#%02x%02x%02x\">", colorDef->red, colorDef->green, colorDef->blue);
|
||||
[_html appendBytes: v length: strlen(v)];
|
||||
free(v);
|
||||
}
|
||||
else if ([s hasPrefix: @"fcs"])
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
else if ([s hasPrefix: @"fs"])
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
else if ([s hasPrefix: @"fbidis"])
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
else if ([s hasPrefix: @"fromhtml"])
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
else if ([s hasPrefix: @"fromtext"])
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
else if ([s hasPrefix: @"f"] && [s length] > 1)
|
||||
{
|
||||
RTFFontInfo *fontInfo;
|
||||
int font_index;
|
||||
|
||||
font_index = [[s substringFromIndex: 1] intValue];
|
||||
|
||||
if (!formattingOptions)
|
||||
continue;
|
||||
|
||||
if (formattingOptions->font_index >= 0 &&
|
||||
font_index != formattingOptions->font_index)
|
||||
{
|
||||
[_html appendBytes: "</font>" length: 7];
|
||||
}
|
||||
|
||||
formattingOptions->font_index = font_index;
|
||||
|
||||
fontInfo = [fontTable fontInfoAtIndex: font_index];
|
||||
|
||||
char *v = malloc(128*sizeof(char));
|
||||
memset(v, 0, 128);
|
||||
sprintf(v, "<font face=\"%s\">", [fontInfo->name UTF8String]);
|
||||
[_html appendBytes: v length: strlen(v)];
|
||||
free(v);
|
||||
}
|
||||
else if ([s isEqualToString: @"i"] && formattingOptions)
|
||||
{
|
||||
[_html appendBytes: "<i>" length: 3];
|
||||
formattingOptions->italic = YES;
|
||||
}
|
||||
else if ([s isEqualToString: @"i0"] && formattingOptions)
|
||||
{
|
||||
[_html appendBytes: "</i>" length: 4];
|
||||
formattingOptions->italic = NO;
|
||||
}
|
||||
else if ([s isEqualToString: @"tab"])
|
||||
{
|
||||
[_html appendBytes: " " length: 12];
|
||||
}
|
||||
else if ([s isEqualToString: @"softline"] || [s isEqualToString: @"par"])
|
||||
{
|
||||
[_html appendBytes: "<br>" length: 4];
|
||||
}
|
||||
else if ([s isEqualToString: @"strike"] && formattingOptions)
|
||||
{
|
||||
[_html appendBytes: "<strike>" length: 8];
|
||||
formattingOptions->strikethrough = YES;
|
||||
}
|
||||
else if ([s isEqualToString: @"strike0"] && formattingOptions)
|
||||
{
|
||||
[_html appendBytes: "</strike>" length: 9];
|
||||
formattingOptions->strikethrough = NO;
|
||||
}
|
||||
else if ([s hasPrefix: @"u"] && [s length] > 1 && isdigit([s characterAtIndex: 1]))
|
||||
{
|
||||
NSData *d;
|
||||
unichar ch;
|
||||
|
||||
ch = (unichar)[[s substringFromIndex: 1] intValue];
|
||||
s = [NSString stringWithCharacters: &ch length: 1];
|
||||
d = [s dataUsingEncoding: NSUTF8StringEncoding];
|
||||
[_html appendData: d];
|
||||
}
|
||||
else if ([s isEqualToString: @"ul"] && formattingOptions)
|
||||
{
|
||||
[_html appendBytes: "<u>" length: 3];
|
||||
formattingOptions->underline = YES;
|
||||
}
|
||||
else if (([s isEqualToString: @"ul0"] || [s isEqualToString: @"ulnone"])
|
||||
&& formattingOptions)
|
||||
{
|
||||
[_html appendBytes: "</u>" length: 4];
|
||||
formattingOptions->underline = NO;
|
||||
}
|
||||
|
||||
// If a space delimits the control word, the space does not appear in the document.
|
||||
// Any characters following the delimiter, including spaces, will appear in the document.
|
||||
if (*_bytes == ' ')
|
||||
{
|
||||
ADVANCE;
|
||||
}
|
||||
}
|
||||
else if (c == '{')
|
||||
{
|
||||
formattingOptions = [[[RTFFormattingOptions alloc] init] autorelease];
|
||||
|
||||
formattingOptions->bold = NO;
|
||||
formattingOptions->italic = NO;
|
||||
formattingOptions->strikethrough = NO;
|
||||
formattingOptions->underline = NO;
|
||||
formattingOptions->font_index = -1;
|
||||
formattingOptions->color_index = -1;
|
||||
formattingOptions->start_pos = [_html length];
|
||||
[stack push: formattingOptions];
|
||||
ADVANCE;
|
||||
}
|
||||
else if (c == '}')
|
||||
{
|
||||
formattingOptions = [stack pop];
|
||||
|
||||
if (formattingOptions)
|
||||
{
|
||||
// Handle {\b bold} vs. \b bold \b0
|
||||
if (formattingOptions->bold)
|
||||
{
|
||||
[_html appendBytes: "</b>" length: 4];
|
||||
}
|
||||
|
||||
if (formattingOptions->italic)
|
||||
{
|
||||
[_html appendBytes: "</i>" length: 4];
|
||||
}
|
||||
|
||||
if (formattingOptions->strikethrough)
|
||||
{
|
||||
[_html appendBytes: "</strike>" length: 9];
|
||||
}
|
||||
|
||||
if (formattingOptions->underline)
|
||||
{
|
||||
[_html appendBytes: "</u>" length: 4];
|
||||
}
|
||||
|
||||
if (formattingOptions->font_index >= 0)
|
||||
{
|
||||
[_html appendBytes: "</font>" length: 7];
|
||||
}
|
||||
|
||||
if (formattingOptions->color_index >= 0)
|
||||
{
|
||||
[_html appendBytes: "</font>" length: 7];
|
||||
}
|
||||
}
|
||||
|
||||
formattingOptions = [stack top];
|
||||
ADVANCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We avoid appending NULL bytes
|
||||
if (*_bytes)
|
||||
[_html appendBytes: _bytes length: 1];
|
||||
ADVANCE;
|
||||
}
|
||||
}
|
||||
|
||||
[_html appendBytes: "</body></html>" length: 14];
|
||||
|
||||
RELEASE(stack);
|
||||
return AUTORELEASE(_html);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -28,6 +28,7 @@
|
||||
#import <Foundation/NSPropertyList.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSURL.h>
|
||||
#import <Foundation/NSUserDefaults.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
#import <GDLAccess/EOAdaptor.h>
|
||||
#import <GDLAccess/EOAdaptorChannel.h>
|
||||
@@ -45,9 +46,22 @@
|
||||
#import "GCSSpecialQueries+OpenChange.h"
|
||||
#import "MAPIStoreTypes.h"
|
||||
#import "SOGoMAPIDBFolder.h"
|
||||
#import "BSONCodec.h"
|
||||
|
||||
#import "SOGoMAPIDBObject.h"
|
||||
|
||||
//
|
||||
// This defines the storage for internal properly list, stored in the
|
||||
// database. Possible values are:
|
||||
//
|
||||
// NSPropertyListGNUstepFormat = 1000
|
||||
// NSPropertyListGNUstepBinaryFormat = 1001
|
||||
// NSPropertyListOpenStepFormat = 1
|
||||
// NSPropertyListXMLFormat_v1_0 = 100
|
||||
// NSPropertyListBinaryFormat_v1_0 = 200
|
||||
//
|
||||
static NSPropertyListFormat plistFormat;
|
||||
|
||||
static EOAttribute *textColumn = nil;
|
||||
|
||||
@implementation SOGoMAPIDBObject
|
||||
@@ -56,6 +70,11 @@ static EOAttribute *textColumn = nil;
|
||||
{
|
||||
NSDictionary *description;
|
||||
|
||||
plistFormat = [[NSUserDefaults standardUserDefaults] integerForKey: @"SOGoPropertyListFormat"];
|
||||
|
||||
if (!plistFormat)
|
||||
plistFormat = NSPropertyListGNUstepBinaryFormat;
|
||||
|
||||
if (!textColumn)
|
||||
{
|
||||
/* TODO: this is a hack for providing an EOAttribute definition that is
|
||||
@@ -138,9 +157,9 @@ static EOAttribute *textColumn = nil;
|
||||
- (void) setupFromRecord: (NSDictionary *) record
|
||||
{
|
||||
NSInteger intValue;
|
||||
NSString *propsValue, *error;
|
||||
NSString *propsValue;//, *error;
|
||||
NSDictionary *newValues;
|
||||
NSPropertyListFormat format;
|
||||
//NSPropertyListFormat format;
|
||||
|
||||
objectType = [[record objectForKey: @"c_type"] intValue];
|
||||
intValue = [[record objectForKey: @"c_creationdate"] intValue];
|
||||
@@ -156,13 +175,8 @@ static EOAttribute *textColumn = nil;
|
||||
propsValue = [record objectForKey: @"c_content"];
|
||||
if ([propsValue isNotNull])
|
||||
{
|
||||
newValues = [NSPropertyListSerialization propertyListFromData: [propsValue dataByDecodingBase64]
|
||||
mutabilityOption: NSPropertyListMutableContainers
|
||||
format: &format
|
||||
errorDescription: &error];
|
||||
newValues = [[propsValue dataByDecodingBase64] BSONValue];
|
||||
[properties addEntriesFromDictionary: newValues];
|
||||
// [properties addEntriesFromDictionary: [propsValue
|
||||
// objectFromJSONString]];
|
||||
}
|
||||
else
|
||||
[properties removeAllObjects];
|
||||
@@ -237,13 +251,13 @@ static EOAttribute *textColumn = nil;
|
||||
className = @"MAPIStoreNotesMessage";
|
||||
else
|
||||
className = @"MAPIStoreDBMessage";
|
||||
[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'",
|
||||
mapiMsgClass, className];
|
||||
//[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'",
|
||||
// mapiMsgClass, className];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self warnWithFormat: @"PidTagMessageClass is not set, falling back"
|
||||
@" to 'MAPIStoreDBMessage'"];
|
||||
//[self warnWithFormat: @"PidTagMessageClass is not set, falling back"
|
||||
// @" to 'MAPIStoreDBMessage'"];
|
||||
className = @"MAPIStoreDBMessage";
|
||||
}
|
||||
break;
|
||||
@@ -508,10 +522,7 @@ static EOAttribute *textColumn = nil;
|
||||
|
||||
if ([properties count] > 0)
|
||||
{
|
||||
content = [NSPropertyListSerialization
|
||||
dataFromPropertyList: properties
|
||||
format: NSPropertyListGNUstepBinaryFormat
|
||||
errorDescription: NULL];
|
||||
content = [properties BSONRepresentation];
|
||||
propsValue = [adaptor formatValue: [content stringByEncodingBase64]
|
||||
forAttribute: textColumn];
|
||||
}
|
||||
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import getopt
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
|
||||
h_template = """unsigned short %(charsetName)s[%(len)d] = { %(values)s };"""
|
||||
CHAR_UNDEF = "0x0000"
|
||||
MAP_LEN = 256
|
||||
itemsPerLine = 16
|
||||
|
||||
def usage():
|
||||
usageMsg = """
|
||||
Usage: %s -f inputFile
|
||||
""" % (os.path.basename(sys.argv[0]))
|
||||
sys.stderr.write(usageMsg)
|
||||
|
||||
def parseCharsetFile(file = None):
|
||||
if file is None:
|
||||
return None
|
||||
|
||||
charmap = [CHAR_UNDEF] * MAP_LEN
|
||||
|
||||
# Sample line:
|
||||
# FD = U+200E : LEFT-TO-RIGHT MARK
|
||||
for line in file.xreadlines():
|
||||
m = re.search("(\w{2}) = U\+(\w{4}) :", line)
|
||||
if not m:
|
||||
sys.stderr.write("Skipping weird line: %s" % line)
|
||||
continue
|
||||
|
||||
ind = int(m.group(1), base=16)
|
||||
unicodeValue = str(m.group(2)).lower()
|
||||
|
||||
charmap[ind] = "0x%s" % (unicodeValue)
|
||||
|
||||
return charmap
|
||||
|
||||
|
||||
def formatCharacterMap(charmap = None):
|
||||
if not charmap:
|
||||
return None
|
||||
|
||||
value = ""
|
||||
for i in xrange(0,MAP_LEN-1):
|
||||
char = charmap[i]
|
||||
if i % itemsPerLine == 0:
|
||||
value += "\n "
|
||||
value += "%s, " % (char)
|
||||
i += 1
|
||||
value += charmap[MAP_LEN-1]
|
||||
|
||||
return value
|
||||
|
||||
if __name__ == '__main__':
|
||||
inputFile = None
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "f:")
|
||||
except getopt.GetoptError, err:
|
||||
sys.stderr.write(str(err))
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
for o, a in opts:
|
||||
if o == "-f":
|
||||
inputFile = a
|
||||
else:
|
||||
assert False, "unhandled option"
|
||||
|
||||
if not inputFile:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
f = open(inputFile, "r", 1)
|
||||
|
||||
charsetMap = parseCharsetFile(f)
|
||||
charsetValues = formatCharacterMap(charsetMap)
|
||||
print h_template % {"len": len(charsetMap),
|
||||
"charsetName": os.path.basename(inputFile),
|
||||
"values": charsetValues}
|
||||
@@ -23,6 +23,8 @@
|
||||
#ifndef ICALEVENT_MAPISTORE_H
|
||||
#define ICALEVENT_MAPISTORE_H
|
||||
|
||||
#include <talloc.h>
|
||||
|
||||
#import <NGCards/iCalEvent.h>
|
||||
|
||||
@class MAPIStoreUserContext;
|
||||
@@ -34,8 +36,8 @@
|
||||
|
||||
- (void) updateFromMAPIProperties: (NSDictionary *) properties
|
||||
inUserContext: (MAPIStoreUserContext *) userContext
|
||||
withActiveUser: (SOGoUser *) activeUser;
|
||||
|
||||
withActiveUser: (SOGoUser *) activeUser
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
@end
|
||||
|
||||
#endif /* ICALEVENT_MAPISTORE_H */
|
||||
@@ -20,7 +20,6 @@
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <talloc.h>
|
||||
#include <util/attr.h>
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
@@ -75,16 +74,17 @@
|
||||
@implementation iCalEvent (MAPIStoreProperties)
|
||||
|
||||
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
struct Binary_r *blob;
|
||||
struct AppointmentRecurrencePattern *pattern;
|
||||
|
||||
blob = [mapiRecurrenceData asBinaryInMemCtx: NULL];
|
||||
pattern = get_AppointmentRecurrencePattern (blob, blob);
|
||||
blob = [mapiRecurrenceData asBinaryInMemCtx: memCtx];
|
||||
pattern = get_AppointmentRecurrencePattern (memCtx, blob);
|
||||
[(iCalCalendar *) parent
|
||||
setupRecurrenceWithMasterEntity: self
|
||||
fromRecurrencePattern: &pattern->RecurrencePattern];
|
||||
talloc_free (blob);
|
||||
//talloc_free (blob);
|
||||
}
|
||||
|
||||
- (void) _setupEventAlarmFromProperties: (NSDictionary *) properties
|
||||
@@ -134,6 +134,7 @@
|
||||
- (void) updateFromMAPIProperties: (NSDictionary *) properties
|
||||
inUserContext: (MAPIStoreUserContext *) userContext
|
||||
withActiveUser: (SOGoUser *) activeUser
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
BOOL isAllDay;
|
||||
iCalDateTime *start, *end;
|
||||
@@ -328,7 +329,7 @@
|
||||
value = [properties
|
||||
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
|
||||
if (value)
|
||||
[self _setupEventRecurrence: value];
|
||||
[self _setupEventRecurrence: value inMemCtx: memCtx];
|
||||
|
||||
/* alarm */
|
||||
[self _setupEventAlarmFromProperties: properties];
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Binary file not shown.
@@ -1,75 +0,0 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <ctype.h> header file. */
|
||||
#define HAVE_CTYPE_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
#define HAVE_MALLOC 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#define HAVE_STRCHR 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strstr' function. */
|
||||
#define HAVE_STRSTR 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "unrtf"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "bug-unrtf@gnu.org"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "unrtf"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "unrtf 0.21.2"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "unrtf"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.21.2"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.21.2"
|
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */
|
||||
/* #undef malloc */
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#import "EOQualifier+GCS.h"
|
||||
|
||||
#if __GNU_LIBOBJC__ >= 20100911
|
||||
#if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__)
|
||||
# define sel_eq(__A__,__B__) sel_isEqual(__A__,__B__)
|
||||
#endif
|
||||
|
||||
|
||||
Loaded 100 of 1402 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user