Compare commits
391
Commits
SOGo-3.2.3
...
SOGo-3.2.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9b9150b96 | ||
|
|
4d490d0f1e | ||
|
|
bc23130f9b | ||
|
|
28bc489c1a | ||
|
|
650f337c41 | ||
|
|
8de9b8ff53 | ||
|
|
8b812ba4f0 | ||
|
|
836700fb7e | ||
|
|
ba583f41b1 | ||
|
|
0e82550f6b | ||
|
|
0185ba9d46 | ||
|
|
9700b93ad1 | ||
|
|
63cb80142b | ||
|
|
c3ef225a02 | ||
|
|
b42876bb0a | ||
|
|
da4033eeab | ||
|
|
f1329a3d36 | ||
|
|
b46781c693 | ||
|
|
ef5728dcaf | ||
|
|
663a0b60dd | ||
|
|
59dbef5ee7 | ||
|
|
4caff58918 | ||
|
|
634cbe3d1b | ||
|
|
3d0c958a19 | ||
|
|
da44afdcf5 | ||
|
|
11f847cdfb | ||
|
|
5f71ee4d52 | ||
|
|
68eae92d2d | ||
|
|
9459185059 | ||
|
|
a9763e94a4 | ||
|
|
5c573b9a76 | ||
|
|
513d81eb59 | ||
|
|
2b4e357da6 | ||
|
|
ab50a41a86 | ||
|
|
7582ec8462 | ||
|
|
dd6b77a25b | ||
|
|
0091ff749a | ||
|
|
c09dff3fc8 | ||
|
|
8a59180c0e | ||
|
|
d87dc6cdf2 | ||
|
|
0af81b0831 | ||
|
|
6fd9927092 | ||
|
|
8bcda19799 | ||
|
|
5570d28d12 | ||
|
|
b8369ddb37 | ||
|
|
e1ea6392c2 | ||
|
|
011e112a1a | ||
|
|
7d396a51f5 | ||
|
|
dbf5039011 | ||
|
|
76e6c064f7 | ||
|
|
04f930dba5 | ||
|
|
08fcee67bd | ||
|
|
cc9602fbc8 | ||
|
|
c92d489017 | ||
|
|
4cf59cd92e | ||
|
|
c4ad338aed | ||
|
|
c8708d9164 | ||
|
|
9bf7247835 | ||
|
|
ed3f794226 | ||
|
|
b9f4947f8a | ||
|
|
f83d6a20a1 | ||
|
|
8ff189229b | ||
|
|
4c1de4cecc | ||
|
|
a7254fe4dd | ||
|
|
308938dcfa | ||
|
|
c11d961bf3 | ||
|
|
4e82820db7 | ||
|
|
26dac618d0 | ||
|
|
f1cc36b533 | ||
|
|
cf07f5746c | ||
|
|
a328f022cb | ||
|
|
46c7af5fdd | ||
|
|
7065c4f765 | ||
|
|
2c8d1d0a26 | ||
|
|
dab48bfc60 | ||
|
|
b0cc012849 | ||
|
|
1d028e4cf5 | ||
|
|
4dcc1af46a | ||
|
|
c57f42b44b | ||
|
|
736921bdf7 | ||
|
|
0cc7c6be3d | ||
|
|
b7bc59d599 | ||
|
|
2f92484064 | ||
|
|
b463fd4eda | ||
|
|
75aaef0f3d | ||
|
|
e7a06c42a4 | ||
|
|
5ff8463fba | ||
|
|
bc8146ef5d | ||
|
|
b25480f228 | ||
|
|
585cda36d1 | ||
|
|
b6d9c3e8e0 | ||
|
|
ce8f2e9481 | ||
|
|
cb532de83a | ||
|
|
1aebad854b | ||
|
|
9f6bc8a749 | ||
|
|
d24ff75ecf | ||
|
|
f60ffa923e | ||
|
|
19512a85d2 | ||
|
|
baa6d39e28 | ||
|
|
5d9673415a | ||
|
|
50f25b0597 | ||
|
|
0a0f8a8d89 | ||
|
|
489e35158c | ||
|
|
11d9df6e6a | ||
|
|
e5dc76cc19 | ||
|
|
ab7ec63f4b | ||
|
|
1964fdebcb | ||
|
|
5b6807b78c | ||
|
|
9603971c1f | ||
|
|
4ae8961947 | ||
|
|
0ffbc13376 | ||
|
|
a02fa44dc7 | ||
|
|
682f699e2f | ||
|
|
f3b098da75 | ||
|
|
6a963bf84b | ||
|
|
270ff1bd29 | ||
|
|
74c2926bca | ||
|
|
75aa6e90a2 | ||
|
|
3c35c16bf3 | ||
|
|
e95e8e9eac | ||
|
|
588ec2b005 | ||
|
|
0627c2f58b | ||
|
|
f6ed816243 | ||
|
|
25430a8128 | ||
|
|
79a0d5e133 | ||
|
|
018b7b7ab9 | ||
|
|
c8539dffa1 | ||
|
|
c995c6e9d7 | ||
|
|
8322d318aa | ||
|
|
4d88eab13b | ||
|
|
a3d7ae3a6b | ||
|
|
a29ced853a | ||
|
|
5047aed6ed | ||
|
|
3c46a6ef14 | ||
|
|
af3a35169a | ||
|
|
6b471994ef | ||
|
|
23ff62a9e0 | ||
|
|
2a820bd780 | ||
|
|
125178e526 | ||
|
|
e1979976a6 | ||
|
|
d87cf6980a | ||
|
|
dfce966e79 | ||
|
|
4002650748 | ||
|
|
0fa8cbf9cb | ||
|
|
7a4dbcb364 | ||
|
|
784503bdbc | ||
|
|
91b32faac2 | ||
|
|
f24d9ae389 | ||
|
|
b501014935 | ||
|
|
cc52e82524 | ||
|
|
fe42180bc0 | ||
|
|
7f67e90c53 | ||
|
|
bf001b1af6 | ||
|
|
3c65973cd5 | ||
|
|
48b2008da4 | ||
|
|
fd13fd632c | ||
|
|
b1e8f30138 | ||
|
|
fc68709956 | ||
|
|
06238a39b1 | ||
|
|
9f84162c5d | ||
|
|
6ffc9a3552 | ||
|
|
3894d6f9fa | ||
|
|
07720563b9 | ||
|
|
5ceafa5005 | ||
|
|
24da483e2a | ||
|
|
9434e3882e | ||
|
|
7d1dd4ec76 | ||
|
|
54eedb3363 | ||
|
|
e9ea104a94 | ||
|
|
99277421a1 | ||
|
|
3d5c0be441 | ||
|
|
dd8cccdafc | ||
|
|
dcfed38fc7 | ||
|
|
b58ec19625 | ||
|
|
d90533399d | ||
|
|
4db1f8185a | ||
|
|
50d8975f9d | ||
|
|
b412788e39 | ||
|
|
15b277fa8e | ||
|
|
d159b191a6 | ||
|
|
539a6c3beb | ||
|
|
abccdd304f | ||
|
|
4143a23afd | ||
|
|
a020286780 | ||
|
|
1b264ef6ba | ||
|
|
ef4e311a5a | ||
|
|
1d8caa4297 | ||
|
|
0500499d91 | ||
|
|
d289a441bb | ||
|
|
fcfbc50139 | ||
|
|
88bc1294cd | ||
|
|
ac127a375f | ||
|
|
f90b2efadb | ||
|
|
c9a50aa057 | ||
|
|
621adb38c2 | ||
|
|
872afaec32 | ||
|
|
892e6d6eb2 | ||
|
|
ed62670a1a | ||
|
|
7a6df34cb6 | ||
|
|
556460982d | ||
|
|
2beb3dca6d | ||
|
|
d14b0b0b5e | ||
|
|
8efd01d55e | ||
|
|
831c1bc980 | ||
|
|
d277f2fe0f | ||
|
|
0b9ca225d0 | ||
|
|
04c256ab6c | ||
|
|
3cbeba32d9 | ||
|
|
1825b167dc | ||
|
|
214ce5ef86 | ||
|
|
927f0c3220 | ||
|
|
227cf582d9 | ||
|
|
8cdc435945 | ||
|
|
3efe0e8098 | ||
|
|
d38d42b83a | ||
|
|
1f3a89b984 | ||
|
|
0dea9c226d | ||
|
|
db1cc24c20 | ||
|
|
d7d88e2620 | ||
|
|
4fca484ed0 | ||
|
|
fcb79dc14b | ||
|
|
41dbb88b64 | ||
|
|
bb97b57ad7 | ||
|
|
5300d4185d | ||
|
|
26b69d25ee | ||
|
|
a3c056ea84 | ||
|
|
e4b2539b04 | ||
|
|
fcb6542d06 | ||
|
|
174fcd5c31 | ||
|
|
2f6c5148aa | ||
|
|
936b21b8c0 | ||
|
|
5f2a6c53c4 | ||
|
|
ba12c14a1d | ||
|
|
4158f7555e | ||
|
|
6e0f5b2254 | ||
|
|
4a21a02f98 | ||
|
|
9d7d2575d3 | ||
|
|
905859053c | ||
|
|
e5d0b0b0ca | ||
|
|
589827a414 | ||
|
|
42ee981613 | ||
|
|
5985262e0f | ||
|
|
c36fcd2902 | ||
|
|
bce09f413f | ||
|
|
9477c1af16 | ||
|
|
8011d9093e | ||
|
|
37334db0e3 | ||
|
|
6637bde56d | ||
|
|
e27efc4d3a | ||
|
|
ff7b9a3725 | ||
|
|
36c7ffcc3c | ||
|
|
3912d2ab3e | ||
|
|
5e775ea4ce | ||
|
|
841fdb96cc | ||
|
|
51ff746595 | ||
|
|
ef1f5a948f | ||
|
|
3560f0486e | ||
|
|
327ebf00a4 | ||
|
|
abb1e1b447 | ||
|
|
818233535f | ||
|
|
65e3fe978c | ||
|
|
0216f19e55 | ||
|
|
8404de758b | ||
|
|
5ec7ad54bb | ||
|
|
be8e1373ea | ||
|
|
9fbc84158a | ||
|
|
071c1032c1 | ||
|
|
af8baf41cb | ||
|
|
0b7ddf7ca4 | ||
|
|
942ddcabe4 | ||
|
|
bdd8254e02 | ||
|
|
ce0575517d | ||
|
|
ea7934a73c | ||
|
|
02fc147624 | ||
|
|
02a1ad48fc | ||
|
|
e7e1283fb3 | ||
|
|
d5e04be1df | ||
|
|
e2ec8af0db | ||
|
|
477c06a7ff | ||
|
|
479b534857 | ||
|
|
f6bcf26793 | ||
|
|
cdf6aaa53e | ||
|
|
1a9b20519e | ||
|
|
4f211678e9 | ||
|
|
e578787acd | ||
|
|
239dffa391 | ||
|
|
6cd3d90410 | ||
|
|
93dfbc5a94 | ||
|
|
896f57f634 | ||
|
|
f48ab310d6 | ||
|
|
5bc21e4f53 | ||
|
|
8296123650 | ||
|
|
2cebee42b7 | ||
|
|
7c7440c988 | ||
|
|
eed5679068 | ||
|
|
f1dbb88303 | ||
|
|
9cb6772ae8 | ||
|
|
dceab8fd2a | ||
|
|
7197b7eb41 | ||
|
|
18b502c39c | ||
|
|
94fc5d17db | ||
|
|
8c075d2e1b | ||
|
|
278aeef864 | ||
|
|
ef69344a59 | ||
|
|
457fccd5ac | ||
|
|
1da36a3ef9 | ||
|
|
7327ec21b2 | ||
|
|
94c522ea5c | ||
|
|
5c0229466e | ||
|
|
eb6d234c4b | ||
|
|
06903f8376 | ||
|
|
596c4bb4c2 | ||
|
|
3d16283d3c | ||
|
|
31d2db51ad | ||
|
|
abd0c0a744 | ||
|
|
1375237697 | ||
|
|
4c78d81bf7 | ||
|
|
2e9168080c | ||
|
|
1eb378c956 | ||
|
|
e739ed46a3 | ||
|
|
93f559a0df | ||
|
|
13a4398c4d | ||
|
|
462d274497 | ||
|
|
ab1c699bc7 | ||
|
|
9882052e81 | ||
|
|
3adbef5aa4 | ||
|
|
5ecf917e6b | ||
|
|
a02642cad9 | ||
|
|
92ba421dd1 | ||
|
|
ea940e645e | ||
|
|
651c0fdf14 | ||
|
|
15a3bf48d9 | ||
|
|
8493701408 | ||
|
|
f0085ef43e | ||
|
|
e0108088ee | ||
|
|
5591b9d423 | ||
|
|
ef96c21334 | ||
|
|
d8eae96d63 | ||
|
|
f6acc3e984 | ||
|
|
340ddf0ae6 | ||
|
|
b0fcaeef86 | ||
|
|
ec19a1290d | ||
|
|
384f1cb53f | ||
|
|
d0e0d5300a | ||
|
|
4b2b3693c5 | ||
|
|
011fae8a65 | ||
|
|
2a2ebd553e | ||
|
|
0038e4bc60 | ||
|
|
e053f12e78 | ||
|
|
c663f7ab4c | ||
|
|
68ddcd7045 | ||
|
|
ffd69337f6 | ||
|
|
ba5bd65ea3 | ||
|
|
6ce64a9a27 | ||
|
|
41701cc94c | ||
|
|
56d7f634a0 | ||
|
|
80f67785c3 | ||
|
|
29dfadfe75 | ||
|
|
fb743d6381 | ||
|
|
203dcf1d05 | ||
|
|
0d95267fe5 | ||
|
|
e997923c31 | ||
|
|
277c6e901e | ||
|
|
2c24901803 | ||
|
|
8f90aa96fe | ||
|
|
ee5b60c544 | ||
|
|
d2b94eba09 | ||
|
|
c9467e1ce3 | ||
|
|
b4e9b7b60c | ||
|
|
66710f1b17 | ||
|
|
a61ea24cdb | ||
|
|
3e448d2c2c | ||
|
|
9aa00d049d | ||
|
|
fdea54f5e7 | ||
|
|
3c098ceca5 | ||
|
|
f7dd835f92 | ||
|
|
7705c11cf7 | ||
|
|
52cdb71d1f | ||
|
|
a1746cd386 | ||
|
|
cd08ab81f1 | ||
|
|
d293fe79ed | ||
|
|
6f732ba535 | ||
|
|
b27c868271 | ||
|
|
e0b0a1d783 | ||
|
|
e059a6043e | ||
|
|
e253f5735d | ||
|
|
328d67ec3a | ||
|
|
c3376a4ddf | ||
|
|
220fb3d607 | ||
|
|
fb873fcae9 | ||
|
|
d2e03386d2 |
No files matched your search
@@ -19,8 +19,6 @@ UI/WebServerResources/.bowerrc
|
||||
UI/WebServerResources/.sass-cache/
|
||||
UI/WebServerResources/bower_components/
|
||||
UI/WebServerResources/css/
|
||||
UI/WebServerResources/css/styles.css
|
||||
UI/WebServerResources/css/styles.css.map
|
||||
UI/WebServerResources/js/*.js
|
||||
UI/WebServerResources/js/*.js.map
|
||||
UI/WebServerResources/js/vendor/*.js
|
||||
|
||||
+11
@@ -15,6 +15,7 @@ trans.es_ES = UI/MailerUI/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = UI/MailerUI/Basque.lproj/Localizable.strings
|
||||
trans.fi = UI/MailerUI/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/MailerUI/French.lproj/Localizable.strings
|
||||
trans.he = UI/MailerUI/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = UI/MailerUI/Croatian.lproj/Localizable.strings
|
||||
trans.hu = UI/MailerUI/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/MailerUI/Icelandic.lproj/Localizable.strings
|
||||
@@ -50,6 +51,7 @@ trans.es_ES = UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = UI/PreferencesUI/Basque.lproj/Localizable.strings
|
||||
trans.fi = UI/PreferencesUI/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/PreferencesUI/French.lproj/Localizable.strings
|
||||
trans.he = UI/PreferencesUI/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = UI/PreferencesUI/Croatian.lproj/Localizable.strings
|
||||
trans.hu = UI/PreferencesUI/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/PreferencesUI/Icelandic.lproj/Localizable.strings
|
||||
@@ -85,6 +87,7 @@ trans.es_ES = UI/Scheduler/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = UI/Scheduler/Basque.lproj/Localizable.strings
|
||||
trans.fi = UI/Scheduler/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/Scheduler/French.lproj/Localizable.strings
|
||||
trans.he = UI/Scheduler/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = UI/Scheduler/Croatian.lproj/Localizable.strings
|
||||
trans.hu = UI/Scheduler/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/Scheduler/Icelandic.lproj/Localizable.strings
|
||||
@@ -120,6 +123,7 @@ trans.es_ES = UI/Contacts/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = UI/Contacts/Basque.lproj/Localizable.strings
|
||||
trans.fi = UI/Contacts/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/Contacts/French.lproj/Localizable.strings
|
||||
trans.he = UI/Contacts/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = UI/Contacts/Croatian.lproj/Localizable.strings
|
||||
trans.hu = UI/Contacts/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/Contacts/Icelandic.lproj/Localizable.strings
|
||||
@@ -155,6 +159,7 @@ trans.es_ES = UI/MainUI/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = UI/MainUI/Basque.lproj/Localizable.strings
|
||||
trans.fi = UI/MainUI/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/MainUI/French.lproj/Localizable.strings
|
||||
trans.he = UI/MainUI/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = UI/MainUI/Croatian.lproj/Localizable.strings
|
||||
trans.hu = UI/MainUI/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/MainUI/Icelandic.lproj/Localizable.strings
|
||||
@@ -190,6 +195,7 @@ trans.es_ES = UI/Common/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = UI/Common/Basque.lproj/Localizable.strings
|
||||
trans.fi = UI/Common/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/Common/French.lproj/Localizable.strings
|
||||
trans.he = UI/Common/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = UI/Common/Croatian.lproj/Localizable.strings
|
||||
trans.hu = UI/Common/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/Common/Icelandic.lproj/Localizable.strings
|
||||
@@ -225,6 +231,7 @@ trans.es_ES = UI/AdministrationUI/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = UI/AdministrationUI/Basque.lproj/Localizable.strings
|
||||
trans.fi = UI/AdministrationUI/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/AdministrationUI/French.lproj/Localizable.strings
|
||||
trans.he = UI/AdministrationUI/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = UI/AdministrationUI/Croatian.lproj/Localizable.strings
|
||||
trans.hu = UI/AdministrationUI/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/AdministrationUI/Icelandic.lproj/Localizable.strings
|
||||
@@ -260,6 +267,7 @@ trans.es_ES = SoObjects/Appointments/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = SoObjects/Appointments/Basque.lproj/Localizable.strings
|
||||
trans.fi = SoObjects/Appointments/Finnish.lproj/Localizable.strings
|
||||
trans.fr = SoObjects/Appointments/French.lproj/Localizable.strings
|
||||
trans.he = SoObjects/Appointments/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = SoObjects/Appointments/Croatian.lproj/Localizable.strings
|
||||
trans.hu = SoObjects/Appointments/Hungarian.lproj/Localizable.strings
|
||||
trans.is = SoObjects/Appointments/Icelandic.lproj/Localizable.strings
|
||||
@@ -295,6 +303,7 @@ trans.es_ES = SoObjects/Contacts/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = SoObjects/Contacts/Basque.lproj/Localizable.strings
|
||||
trans.fi = SoObjects/Contacts/Finnish.lproj/Localizable.strings
|
||||
trans.fr = SoObjects/Contacts/French.lproj/Localizable.strings
|
||||
trans.he = SoObjects/Contacts/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = SoObjects/Contacts/Croatian.lproj/Localizable.strings
|
||||
trans.hu = SoObjects/Contacts/Hungarian.lproj/Localizable.strings
|
||||
trans.is = SoObjects/Contacts/Icelandic.lproj/Localizable.strings
|
||||
@@ -330,6 +339,7 @@ trans.es_ES = SoObjects/Mailer/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = SoObjects/Mailer/Basque.lproj/Localizable.strings
|
||||
trans.fi = SoObjects/Mailer/Finnish.lproj/Localizable.strings
|
||||
trans.fr = SoObjects/Mailer/French.lproj/Localizable.strings
|
||||
trans.he = SoObjects/Mailer/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = SoObjects/Mailer/Croatian.lproj/Localizable.strings
|
||||
trans.hu = SoObjects/Mailer/Hungarian.lproj/Localizable.strings
|
||||
trans.is = SoObjects/Mailer/Icelandic.lproj/Localizable.strings
|
||||
@@ -365,6 +375,7 @@ trans.es_ES = UI/MailPartViewers/SpanishSpain.lproj/Localizable.strings
|
||||
trans.eu = UI/MailPartViewers/Basque.lproj/Localizable.strings
|
||||
trans.fi = UI/MailPartViewers/Finnish.lproj/Localizable.strings
|
||||
trans.fr = UI/MailPartViewers/French.lproj/Localizable.strings
|
||||
trans.he = UI/MailPartViewers/Hebrew.lproj/Localizable.strings
|
||||
trans.hr_HR = UI/MailPartViewers/Croatian.lproj/Localizable.strings
|
||||
trans.hu = UI/MailPartViewers/Hungarian.lproj/Localizable.strings
|
||||
trans.is = UI/MailPartViewers/Icelandic.lproj/Localizable.strings
|
||||
|
||||
@@ -83,7 +83,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
|
||||
{
|
||||
NSArray *emails, *addresses, *categories, *elements;
|
||||
CardElement *n, *homeAdr, *workAdr;
|
||||
NSMutableArray *other_addresses;
|
||||
CardElement *n, *homeAdr, *workAdr, *otherAdr;
|
||||
NSMutableString *s, *a;
|
||||
NSString *url;
|
||||
id o;
|
||||
@@ -186,7 +187,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
if ((o = [homeAdr flattenedValueAtIndex: 1 forKey: @""]) && [o length])
|
||||
[a appendFormat: @"\n%@", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", [a activeSyncRepresentationInContext: context]];
|
||||
[s appendFormat: @"<HomeStreet xmlns=\"Contacts:\">%@</HomeStreet>", a];
|
||||
|
||||
if ((o = [homeAdr flattenedValueAtIndex: 3 forKey: @""]))
|
||||
[s appendFormat: @"<HomeCity xmlns=\"Contacts:\">%@</HomeCity>", [o activeSyncRepresentationInContext: context]];
|
||||
@@ -217,7 +218,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
if ((o = [workAdr flattenedValueAtIndex: 1 forKey: @""]) && [o length])
|
||||
[a appendFormat: @"\n%@", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", [a activeSyncRepresentationInContext: context]];
|
||||
[s appendFormat: @"<BusinessStreet xmlns=\"Contacts:\">%@</BusinessStreet>", a];
|
||||
|
||||
if ((o = [workAdr flattenedValueAtIndex: 3 forKey: @""]))
|
||||
[s appendFormat: @"<BusinessCity xmlns=\"Contacts:\">%@</BusinessCity>", [o activeSyncRepresentationInContext: context]];
|
||||
@@ -232,6 +233,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[s appendFormat: @"<BusinessCountry xmlns=\"Contacts:\">%@</BusinessCountry>", [o activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
|
||||
|
||||
// Other Address
|
||||
|
||||
other_addresses = [[self childrenWithTag: @"adr"] mutableCopy];
|
||||
[other_addresses removeObjectsInArray: [self childrenWithTag: @"adr" andAttribute: @"type" havingValue: @"work"]];
|
||||
[other_addresses removeObjectsInArray: [self childrenWithTag: @"adr" andAttribute: @"type" havingValue: @"home"]];
|
||||
|
||||
if ([other_addresses count])
|
||||
{
|
||||
otherAdr = [other_addresses objectAtIndex: 0];
|
||||
a = [NSMutableString string];
|
||||
|
||||
if ((o = [otherAdr flattenedValueAtIndex: 2 forKey: @""]))
|
||||
[a appendString: [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [otherAdr flattenedValueAtIndex: 1 forKey: @""]) && [o length])
|
||||
[a appendFormat: @"\n%@", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
[s appendFormat: @"<OtherStreet xmlns=\"Contacts:\">%@</OtherStreet>", a];
|
||||
|
||||
if ((o = [otherAdr flattenedValueAtIndex: 3 forKey: @""]))
|
||||
[s appendFormat: @"<OtherCity xmlns=\"Contacts:\">%@</OtherCity>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [otherAdr flattenedValueAtIndex: 4 forKey: @""]))
|
||||
[s appendFormat: @"<OtherState xmlns=\"Contacts:\">%@</OtherState>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [otherAdr flattenedValueAtIndex: 5 forKey: @""]))
|
||||
[s appendFormat: @"<OtherPostalCode xmlns=\"Contacts:\">%@</OtherPostalCode>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [otherAdr flattenedValueAtIndex: 6 forKey: @""]))
|
||||
[s appendFormat: @"<OtherCountry xmlns=\"Contacts:\">%@</OtherCountry>", [o activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
|
||||
// Other, less important fields
|
||||
if ((o = [self birthday]))
|
||||
{
|
||||
@@ -267,7 +301,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
inContext: (WOContext *) context
|
||||
{
|
||||
CardElement *element;
|
||||
NSMutableArray *addressLines;
|
||||
NSMutableArray *addressLines, *other_addresses;
|
||||
id o;
|
||||
|
||||
// Contact's note
|
||||
@@ -398,6 +432,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
atIndex: 6 forKey: @""];
|
||||
}
|
||||
|
||||
// OtherCountry
|
||||
//
|
||||
|
||||
other_addresses = [[self childrenWithTag: @"adr"] mutableCopy];
|
||||
[other_addresses removeObjectsInArray: [self childrenWithTag: @"adr" andAttribute: @"type" havingValue: @"work"]];
|
||||
[other_addresses removeObjectsInArray: [self childrenWithTag: @"adr" andAttribute: @"type" havingValue: @"home"]];
|
||||
|
||||
if ([other_addresses count])
|
||||
element = [other_addresses objectAtIndex: 0];
|
||||
else
|
||||
{
|
||||
element = [CardElement elementWithTag: @"adr"];
|
||||
[self addChild: element];
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"OtherStreet"]) || ![self _isGhosted: @"OtherStreet" inContext: context])
|
||||
{
|
||||
addressLines = [NSMutableArray arrayWithArray: [o componentsSeparatedByString: @"\n"]];
|
||||
|
||||
[element setSingleValue: @""
|
||||
atIndex: 1 forKey: @""];
|
||||
[element setSingleValue: [addressLines count] ? [addressLines objectAtIndex: 0] : @""
|
||||
atIndex: 2 forKey: @""];
|
||||
|
||||
// Extended address line. If there are more then 2 address lines we add them to the extended address line.
|
||||
if ([addressLines count] > 1)
|
||||
{
|
||||
[addressLines removeObjectAtIndex: 0];
|
||||
[element setSingleValue: [addressLines componentsJoinedByString: @" "]
|
||||
atIndex: 1 forKey: @""];
|
||||
}
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"OtherCity"]) || ![self _isGhosted: @"OtherCity" inContext: context])
|
||||
{
|
||||
[element setSingleValue: [theValues objectForKey: @"OtherCity"]
|
||||
atIndex: 3 forKey: @""];
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"OtherState"]) || ![self _isGhosted: @"OtherState" inContext: context])
|
||||
{
|
||||
[element setSingleValue: [theValues objectForKey: @"OtherState"]
|
||||
atIndex: 4 forKey: @""];
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"OtherPostalCode"]) || ![self _isGhosted: @"OtherPostalCode" inContext: context])
|
||||
{
|
||||
[element setSingleValue: [theValues objectForKey: @"OtherPostalCode"]
|
||||
atIndex: 5 forKey: @""];
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"OtherCountry"]) || ![self _isGhosted: @"OtherCountry" inContext: context])
|
||||
{
|
||||
[element setSingleValue: [theValues objectForKey: @"OtherCountry"]
|
||||
atIndex: 6 forKey: @""];
|
||||
}
|
||||
|
||||
// Company's name
|
||||
if ((o = [theValues objectForKey: @"CompanyName"]))
|
||||
[self setOrg: o units: nil];
|
||||
|
||||
@@ -148,6 +148,10 @@ static NSArray *easCommandParameters = nil;
|
||||
const char* qs_bytes;
|
||||
|
||||
queryString = [[components objectAtIndex: 0] dataByDecodingBase64];
|
||||
|
||||
if (![queryString length])
|
||||
return nil;
|
||||
|
||||
qs_bytes = (const char*)[queryString bytes];
|
||||
|
||||
return [NSString stringWithFormat:@"%.1f", (float)((uint8_t)qs_bytes[0]/10)];
|
||||
@@ -196,6 +200,11 @@ static NSArray *easCommandParameters = nil;
|
||||
|
||||
// Command code, 1 byte, ie.: cmd=
|
||||
cmd_code = qs_bytes[1];
|
||||
|
||||
// Check whether the command code is within the known range.
|
||||
if (cmd_code < 0 || cmd_code > 22)
|
||||
return nil;
|
||||
|
||||
[components addObject: [NSString stringWithFormat: @"cmd=%@", [easCommandCodes objectAtIndex: cmd_code]]];
|
||||
|
||||
// Device ID length and Device ID (variable)
|
||||
|
||||
@@ -53,9 +53,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#import <SOGo/SOGoCacheGCSObject.h>
|
||||
#import <SOGo/SOGoPermissions.h>
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
|
||||
#import <Appointments/iCalEntityObject+SOGo.h>
|
||||
#import <Appointments/SOGoAppointmentObject.h>
|
||||
#import <Appointments/SOGoTaskObject.h>
|
||||
#import <Appointments/SOGoAppointmentFolder.h>
|
||||
|
||||
#import <Contacts/SOGoContactGCSEntry.h>
|
||||
|
||||
@@ -227,7 +230,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
return nameInCache;
|
||||
}
|
||||
|
||||
- (void) _removeAllAlarmsFromCalendar: (iCalCalendar *) theCalendar
|
||||
{
|
||||
NSArray *allComponents;
|
||||
iCalEntityObject *currentComponent;
|
||||
NSUInteger count, max;
|
||||
|
||||
if (debugOn)
|
||||
[self logWithFormat: @"EAS - Remove all alarms"];
|
||||
|
||||
allComponents = [theCalendar allObjects];
|
||||
|
||||
max = [allComponents count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
currentComponent = [allComponents objectAtIndex: count];
|
||||
if ([currentComponent isKindOfClass: [iCalEvent class]] ||
|
||||
[currentComponent isKindOfClass: [iCalToDo class]])
|
||||
[currentComponent removeAllAlarms];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// <?xml version="1.0"?>
|
||||
@@ -269,6 +291,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
- (void) processSyncAddCommand: (id <DOMElement>) theDocumentElement
|
||||
inCollection: (id) theCollection
|
||||
withType: (SOGoMicrosoftActiveSyncFolderType) theFolderType
|
||||
objectsToTouch: (NSMutableArray *) objectsToTouch
|
||||
inBuffer: (NSMutableString *) theBuffer
|
||||
{
|
||||
NSMutableDictionary *folderMetadata, *dateCache, *syncCache, *uidCache, *allValues;
|
||||
@@ -280,6 +303,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
int i;
|
||||
|
||||
additions = (id)[theDocumentElement getElementsByTagName: @"Add"];
|
||||
|
||||
if ([additions count])
|
||||
{
|
||||
for (i = 0; i < [additions count]; i++)
|
||||
@@ -367,9 +391,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{
|
||||
[o takeActiveSyncValues: allValues inContext: context];
|
||||
[sogoObject setIsNew: is_new];
|
||||
[sogoObject saveComponent: o];
|
||||
|
||||
if (theFolderType == ActiveSyncEventFolder)
|
||||
[sogoObject saveComponent: o force: YES];
|
||||
else
|
||||
[sogoObject saveComponent: o];
|
||||
|
||||
}
|
||||
|
||||
if ([sogoObject isKindOfClass: [SOGoAppointmentObject class]] && [sogoObject resourceHasAutoAccepted])
|
||||
[objectsToTouch addObject: sogoObject];
|
||||
|
||||
// Update syncCache
|
||||
folderMetadata = [self _folderMetadataForKey: [self _getNameInCache: theCollection withType: theFolderType]];
|
||||
|
||||
@@ -421,7 +453,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[theBuffer appendFormat: @"<ServerId>%@</ServerId>", easId];
|
||||
[theBuffer appendFormat: @"<Status>%d</Status>", 1];
|
||||
[theBuffer appendString: @"</Add>"];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,7 +496,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
- (void) processSyncChangeCommand: (id <DOMElement>) theDocumentElement
|
||||
inCollection: (id) theCollection
|
||||
withType: (SOGoMicrosoftActiveSyncFolderType) theFolderType
|
||||
inBuffer: (NSMutableString *) theBuffer
|
||||
objectsToTouch: (NSMutableArray *) objectsToTouch
|
||||
inBuffer: (NSMutableString *) theBuffer
|
||||
{
|
||||
NSDictionary *allChanges;
|
||||
NSString *serverId, *easId, *origServerId, *mergedFolder;
|
||||
@@ -505,6 +537,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[self processSyncChangeCommand: theDocumentElement
|
||||
inCollection: [self collectionFromId: mergedFolder type: theFolderType]
|
||||
withType: theFolderType
|
||||
objectsToTouch: objectsToTouch
|
||||
inBuffer: theBuffer];
|
||||
|
||||
continue;
|
||||
@@ -588,7 +621,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
if ([roles containsObject: SOGoCalendarRole_ComponentModifier] || [[sogoObject ownerInContext: context] isEqualToString: [[context activeUser] login]])
|
||||
{
|
||||
[o takeActiveSyncValues: allChanges inContext: context];
|
||||
[sogoObject saveComponent: o];
|
||||
|
||||
if (theFolderType == ActiveSyncEventFolder)
|
||||
{
|
||||
[sogoObject saveComponent: o force: YES];
|
||||
if ([sogoObject resourceHasAutoAccepted])
|
||||
[objectsToTouch addObject: sogoObject];
|
||||
}
|
||||
else
|
||||
[sogoObject saveComponent: o];
|
||||
|
||||
if ([syncCache objectForKey: serverId])
|
||||
[syncCache setObject: [NSString stringWithFormat: @"%f", [[sogoObject lastModified] timeIntervalSince1970]] forKey: serverId];
|
||||
@@ -1202,6 +1243,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
d = [NSCalendarDate distantFuture];
|
||||
|
||||
[dateCache setObject: d forKey: uid];
|
||||
|
||||
if (!([theCollection showCalendarAlarms]))
|
||||
[self _removeAllAlarmsFromCalendar: [componentObject parent]];
|
||||
}
|
||||
|
||||
if (updated)
|
||||
@@ -1562,7 +1606,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[s appendString: [mailObject activeSyncRepresentationInContext: context]];
|
||||
[s appendString: @"</ApplicationData>"];
|
||||
[s appendString: @"</Add>"];
|
||||
|
||||
|
||||
[syncCache setObject: [aCacheObject sequence] forKey: [aCacheObject uid]];
|
||||
[dateCache setObject: [NSCalendarDate date] forKey: [aCacheObject uid]];
|
||||
|
||||
@@ -1637,6 +1681,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
inCollection: (id) theCollection
|
||||
withType: (SOGoMicrosoftActiveSyncFolderType) theFolderType
|
||||
inBuffer: (NSMutableString *) theBuffer
|
||||
objectsToTouch: (NSMutableArray *) objectsToTouch
|
||||
processed: (BOOL *) processed
|
||||
{
|
||||
id <DOMElement> aCommand, element;
|
||||
@@ -1665,6 +1710,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[self processSyncAddCommand: element
|
||||
inCollection: theCollection
|
||||
withType: theFolderType
|
||||
objectsToTouch: objectsToTouch
|
||||
inBuffer: theBuffer];
|
||||
*processed = YES;
|
||||
}
|
||||
@@ -1674,6 +1720,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[self processSyncChangeCommand: element
|
||||
inCollection: theCollection
|
||||
withType: theFolderType
|
||||
objectsToTouch: objectsToTouch
|
||||
inBuffer: theBuffer];
|
||||
*processed = YES;
|
||||
}
|
||||
@@ -1711,7 +1758,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{
|
||||
NSString *collectionId, *realCollectionId, *syncKey, *davCollectionTag, *bodyPreferenceType, *mimeSupport, *mimeTruncation, *filterType, *lastServerKey, *syncKeyInCache, *folderKey;
|
||||
NSMutableDictionary *folderMetadata, *folderOptions;
|
||||
NSMutableArray *supportedElements, *supportedElementNames;
|
||||
NSMutableArray *supportedElements, *supportedElementNames, *objectsToTouch;
|
||||
NSMutableString *changeBuffer, *commandsBuffer;
|
||||
id collection, value;
|
||||
|
||||
@@ -1941,6 +1988,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// We process the commands from the request
|
||||
//
|
||||
objectsToTouch = [NSMutableArray array];
|
||||
|
||||
if (!first_sync)
|
||||
{
|
||||
NSMutableString *s;
|
||||
@@ -1953,6 +2002,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
inCollection: collection
|
||||
withType: folderType
|
||||
inBuffer: s
|
||||
objectsToTouch: objectsToTouch
|
||||
processed: &processed];
|
||||
|
||||
// Windows phones don't like empty Responses tags - such as: <Responses></Responses>.
|
||||
@@ -2271,6 +2321,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[theBuffer appendString: changeBuffer];
|
||||
|
||||
[theBuffer appendString: @"</Collection>"];
|
||||
|
||||
// We touch objects (likely only SOGoAppointmentObjects for now) that might have been changed
|
||||
// by the server and that we want the EAS client to re-pull. For example, that's the case for
|
||||
// auto-accepted events by resources
|
||||
for (i = 0; i < [objectsToTouch count]; i++)
|
||||
{
|
||||
sleep(1);
|
||||
[[objectsToTouch objectAtIndex: i] touch];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -43,6 +43,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#import <NGObjWeb/WOCoreApplication.h>
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <NGCards/iCalEvent.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
|
||||
#import <NGExtensions/NGBase64Coding.h>
|
||||
|
||||
@@ -59,8 +61,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import <NGMime/NGMimeBodyPart.h>
|
||||
#import <NGMime/NGMimeFileData.h>
|
||||
#import <NGMime/NGMimeMultipartBody.h>
|
||||
#import <NGMime/NGMimeType.h>
|
||||
#import <NGMime/NGMimeMultipartBody.h>
|
||||
#import <NGMime/NGConcreteMimeType.h>
|
||||
#import <NGMail/NGMimeMessageParser.h>
|
||||
#import <NGMail/NGMimeMessageGenerator.h>
|
||||
|
||||
@@ -947,6 +950,7 @@ void handle_eas_terminate(int signum)
|
||||
command_count++;
|
||||
}
|
||||
[o destroy];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove the folder from device if it is a contact folder and we have no SOGoRole_ObjectViewer.
|
||||
@@ -1097,6 +1101,7 @@ void handle_eas_terminate(int signum)
|
||||
![currentFolder synchronize])
|
||||
{
|
||||
[folders removeObjectAtIndex: count];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove the folder from the device if it is a contact folder and we have no SOGoRole_ObjectViewer access right.
|
||||
@@ -1815,7 +1820,7 @@ void handle_eas_terminate(int signum)
|
||||
{
|
||||
appointmentObject = [[SOGoAppointmentObject alloc] initWithName: [NSString stringWithFormat: @"%@.ics", [event uid]]
|
||||
inContainer: collection];
|
||||
[appointmentObject saveComponent: event];
|
||||
[appointmentObject saveComponent: event force: YES];
|
||||
}
|
||||
|
||||
if (uidCache && [calendarId length] > 64)
|
||||
@@ -2651,6 +2656,7 @@ void handle_eas_terminate(int signum)
|
||||
NSData *d;
|
||||
|
||||
unsigned int startdate, enddate, increments;
|
||||
NGCalendarDateRange *r1, *r2;
|
||||
char c;
|
||||
|
||||
startDate = [[[(id)[theDocumentElement getElementsByTagName: @"StartTime"] lastObject] textValue] calendarDate];
|
||||
@@ -2697,17 +2703,13 @@ void handle_eas_terminate(int signum)
|
||||
folder = [user personalCalendarFolderInContext: context];
|
||||
freebusy = [folder fetchFreeBusyInfosFrom: startDate to: endDate];
|
||||
|
||||
|
||||
NGCalendarDateRange *r1, *r2;
|
||||
|
||||
for (j = 1; j <= increments; j++)
|
||||
for (j = 0; j < increments; j++)
|
||||
{
|
||||
c = '0';
|
||||
|
||||
r1 = [NGCalendarDateRange calendarDateRangeWithStartDate: [NSDate dateWithTimeIntervalSince1970: (startdate+j*30*60)]
|
||||
endDate: [NSDate dateWithTimeIntervalSince1970: (startdate+j*30*60 + 30)]];
|
||||
|
||||
|
||||
|
||||
for (k = 0; k < [freebusy count]; k++)
|
||||
{
|
||||
|
||||
@@ -2725,11 +2727,8 @@ void handle_eas_terminate(int signum)
|
||||
[s appendFormat: @"%c", c];
|
||||
}
|
||||
|
||||
|
||||
[s appendString: @"</MergedFreeBusy>"];
|
||||
[s appendString: @"</Availability>"];
|
||||
|
||||
|
||||
[s appendString: @"</Recipient>"];
|
||||
[s appendString: @"</Response>"];
|
||||
}
|
||||
@@ -2760,7 +2759,7 @@ void handle_eas_terminate(int signum)
|
||||
inResponse: (WOResponse *) theResponse
|
||||
{
|
||||
SOGoContactSourceFolder *currentFolder;
|
||||
NSArray *allKeys, *allContacts, *mails;
|
||||
NSArray *allKeys, *allContacts, *mails, *a;
|
||||
NSDictionary *systemSources, *contact;
|
||||
SOGoContactFolders *contactFolders;
|
||||
NSString *current_mail, *query;
|
||||
@@ -2770,7 +2769,10 @@ void handle_eas_terminate(int signum)
|
||||
NSData *d;
|
||||
id o;
|
||||
|
||||
int i, j, total;
|
||||
int i, j, t, v, total, minResult, maxResult, maxSize, maxPictures;
|
||||
BOOL withPhoto;
|
||||
|
||||
withPhoto = NO;
|
||||
|
||||
query = [[(id)[theDocumentElement getElementsByTagName: @"Query"] lastObject] textValue];
|
||||
|
||||
@@ -2779,6 +2781,33 @@ void handle_eas_terminate(int signum)
|
||||
systemSources = [contactFolders systemSources];
|
||||
allKeys = [systemSources allKeys];
|
||||
|
||||
// We check for the maximum number of results to return.
|
||||
a = [[[(id)[theDocumentElement getElementsByTagName: @"Range"] lastObject] textValue] componentsSeparatedByString: @"-"];
|
||||
minResult = [[a objectAtIndex: 0] intValue];
|
||||
maxResult = [[a objectAtIndex: 1] intValue];
|
||||
|
||||
if (maxResult == 0)
|
||||
maxResult = 99;
|
||||
|
||||
if ((o = [(id)[[(id)[theDocumentElement getElementsByTagName: @"Options"] lastObject] getElementsByTagName: @"Picture"] lastObject]))
|
||||
{
|
||||
withPhoto = YES;
|
||||
|
||||
// We check for a MaxSize, default to 102400.
|
||||
maxSize = [[[(id)[o getElementsByTagName: @"MaxSize"] lastObject] textValue] intValue];
|
||||
|
||||
// We check if we must overwrite the maxSize with a system preference. This can be useful
|
||||
// if we don't want to have pictures in the response.
|
||||
if ((v = [[SOGoSystemDefaults sharedSystemDefaults] maximumPictureSize]))
|
||||
maxSize = v;
|
||||
|
||||
// We check for a MaxPictures, default to 99.
|
||||
maxPictures = [[[(id)[o getElementsByTagName: @"MaxPictures"] lastObject] textValue] intValue];
|
||||
|
||||
if (maxPictures == 0)
|
||||
maxPictures = 99;
|
||||
}
|
||||
|
||||
s = [NSMutableString string];
|
||||
|
||||
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
|
||||
@@ -2800,7 +2829,7 @@ void handle_eas_terminate(int signum)
|
||||
ordering: NSOrderedAscending
|
||||
inDomain: [[context activeUser] domain]];
|
||||
|
||||
for (j = 0; j < [allContacts count]; j++)
|
||||
for (j = minResult; (j < [allContacts count] && j < maxResult) ; j++)
|
||||
{
|
||||
contact = [allContacts objectAtIndex: j];
|
||||
|
||||
@@ -2818,42 +2847,60 @@ void handle_eas_terminate(int signum)
|
||||
else
|
||||
mails = [NSArray arrayWithObjects: o ? o : @"", nil];
|
||||
|
||||
for (total = 0; total < [mails count]; total++)
|
||||
for (t = 0; t < [mails count]; t++)
|
||||
{
|
||||
current_mail = [mails objectAtIndex: total];
|
||||
current_mail = [mails objectAtIndex: t];
|
||||
|
||||
[s appendString: @"<Result xmlns=\"Search:\">"];
|
||||
[s appendString: @"<Properties>"];
|
||||
|
||||
if ((o = [contact objectForKey: @"displayname"]))
|
||||
[s appendFormat: @"<DisplayName xmlns=\"Gal:\">%@</DisplayName>", o];
|
||||
[s appendFormat: @"<DisplayName xmlns=\"Gal:\">%@</DisplayName>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [contact objectForKey: @"title"]))
|
||||
[s appendFormat: @"<Title xmlns=\"Gal:\">%@</Title>", o];
|
||||
[s appendFormat: @"<Title xmlns=\"Gal:\">%@</Title>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [contact objectForKey: @"givenname"]))
|
||||
[s appendFormat: @"<FirstName xmlns=\"Gal:\">%@</FirstName>", o];
|
||||
[s appendFormat: @"<FirstName xmlns=\"Gal:\">%@</FirstName>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [contact objectForKey: @"sn"]))
|
||||
[s appendFormat: @"<LastName xmlns=\"Gal:\">%@</LastName>", o];
|
||||
[s appendFormat: @"<LastName xmlns=\"Gal:\">%@</LastName>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ([current_mail length] > 0)
|
||||
[s appendFormat: @"<EmailAddress xmlns=\"Gal:\">%@</EmailAddress>", current_mail];
|
||||
[s appendFormat: @"<EmailAddress xmlns=\"Gal:\">%@</EmailAddress>", [current_mail activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [contact objectForKey: @"telephonenumber"]))
|
||||
[s appendFormat: @"<Phone xmlns=\"Gal:\">%@</Phone>", o];
|
||||
[s appendFormat: @"<Phone xmlns=\"Gal:\">%@</Phone>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [contact objectForKey: @"homephone"]))
|
||||
[s appendFormat: @"<HomePhone xmlns=\"Gal:\">%@</HomePhone>", o];
|
||||
[s appendFormat: @"<HomePhone xmlns=\"Gal:\">%@</HomePhone>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [contact objectForKey: @"mobile"]))
|
||||
[s appendFormat: @"<MobilePhone xmlns=\"Gal:\">%@</MobilePhone>", o];
|
||||
[s appendFormat: @"<MobilePhone xmlns=\"Gal:\">%@</MobilePhone>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ((o = [contact objectForKey: @"o"]))
|
||||
[s appendFormat: @"<Company xmlns=\"Gal:\">%@</Company>", o];
|
||||
|
||||
[s appendFormat: @"<Company xmlns=\"Gal:\">%@</Company>", [o activeSyncRepresentationInContext: context]];
|
||||
|
||||
if ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 14.1 && withPhoto)
|
||||
{
|
||||
o = [contact objectForKey: @"photo"];
|
||||
if (o && [o length] <= maxSize && total < maxPictures)
|
||||
{
|
||||
[s appendString: @"<Picture xmlns=\"Gal:\"><Status>1</Status><Data>"];
|
||||
[s appendString: [o activeSyncRepresentationInContext: context]];
|
||||
[s appendString: @"</Data></Picture>"];
|
||||
}
|
||||
else if (!o)
|
||||
[s appendString: @"<Picture xmlns=\"Gal:\"><Status>173</Status></Picture>"];
|
||||
else if ([o length] > maxSize)
|
||||
[s appendString: @"<Picture xmlns=\"Gal:\"><Status>174</Status></Picture>"];
|
||||
else if (total >= maxPictures)
|
||||
[s appendString: @"<Picture xmlns=\"Gal:\"><Status>175</Status></Picture>"];
|
||||
}
|
||||
|
||||
[s appendString: @"</Properties>"];
|
||||
[s appendString: @"</Result>"];
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3167,6 +3214,28 @@ void handle_eas_terminate(int signum)
|
||||
return nil;
|
||||
}
|
||||
|
||||
//
|
||||
// See https://msdn.microsoft.com/en-us/library/ee218647(v=exchg.80).aspx
|
||||
// for valid status codes.
|
||||
//
|
||||
- (NSData *) _sendMailErrorResponseWithStatus: (int) status
|
||||
{
|
||||
NSMutableString *s;
|
||||
NSData *d;
|
||||
|
||||
s = [NSMutableString string];
|
||||
|
||||
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
|
||||
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
|
||||
[s appendString: @"<SendMail xmlns=\"ComposeMail:\">"];
|
||||
[s appendFormat: @"<Status>%d</Status>", status];
|
||||
[s appendString: @"</SendMail>"];
|
||||
|
||||
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -3180,6 +3249,7 @@ void handle_eas_terminate(int signum)
|
||||
NSData *new_from_header;
|
||||
NSDictionary *identity;
|
||||
NSString *fullName, *email;
|
||||
NGMimeType *contentType;
|
||||
NSArray *from;
|
||||
|
||||
const char *bytes;
|
||||
@@ -3195,6 +3265,40 @@ void handle_eas_terminate(int signum)
|
||||
message = [parser parsePartFromData: data];
|
||||
RELEASE(parser);
|
||||
|
||||
// If an EAS client is trying to send an invitation email (request or response), we make sure to
|
||||
// remove all attendees that have NO email addresses. Outlook 2016 (and likely other EAS clients)
|
||||
// do that when sending IMIP only to "newly added or deleted attendees" - existing attendees have
|
||||
// their email addresses stripped, while keeping the display name value.
|
||||
contentType = [message contentType];
|
||||
|
||||
if ([contentType isKindOfClass: [NGConcreteTextMimeType class]] &&
|
||||
[[[message contentType] subType] caseInsensitiveCompare: @"calendar"] == NSOrderedSame &&
|
||||
([[(NGConcreteTextMimeType *)[message contentType] method] caseInsensitiveCompare: @"request"] == NSOrderedSame ||
|
||||
[[(NGConcreteTextMimeType *)[message contentType] method] caseInsensitiveCompare: @"reply"] == NSOrderedSame))
|
||||
{
|
||||
NGMimeMessageGenerator *generator;
|
||||
iCalCalendar *calendar;
|
||||
iCalPerson *attendee;
|
||||
NSArray *attendees;
|
||||
iCalEvent *event;
|
||||
|
||||
calendar = [iCalCalendar parseSingleFromSource: [message body]];
|
||||
event = [[calendar events] lastObject];
|
||||
attendees = [event attendees];
|
||||
|
||||
for (i = [attendees count]-1; i >= 0; i--)
|
||||
{
|
||||
attendee = [attendees objectAtIndex: i];
|
||||
if (![attendee rfc822Email] || [[attendee rfc822Email] caseInsensitiveCompare: @"nomail"] == NSOrderedSame)
|
||||
[event removeFromAttendees: attendee];
|
||||
}
|
||||
|
||||
// We regenerate the data to use
|
||||
[message setBody: [[calendar versitString] dataUsingEncoding: NSUTF8StringEncoding]];
|
||||
generator = [[[NGMimeMessageGenerator alloc] init] autorelease];
|
||||
data = [NSMutableData dataWithData: [generator generateMimeFromPart: message]];
|
||||
}
|
||||
|
||||
from = [message headersForKey: @"from"];
|
||||
|
||||
if (![from count] || ![self _isEMailValid: [[from objectAtIndex: 0] pureEMailAddress]] ||
|
||||
@@ -3296,20 +3400,7 @@ void handle_eas_terminate(int signum)
|
||||
{
|
||||
if ([[context objectForKey: @"ASProtocolVersion"] floatValue] >= 14.0)
|
||||
{
|
||||
NSMutableString *s;
|
||||
NSData *d;
|
||||
|
||||
s = [NSMutableString string];
|
||||
|
||||
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
|
||||
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
|
||||
[s appendString: @"<SendMail xmlns=\"ComposeMail:\">"];
|
||||
[s appendString: @"<Status>120</Status>"];
|
||||
[s appendString: @"</SendMail>"];
|
||||
|
||||
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
|
||||
|
||||
[theResponse setContent: d];
|
||||
[theResponse setContent: [self _sendMailErrorResponseWithStatus: 120]];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3498,10 +3589,14 @@ void handle_eas_terminate(int signum)
|
||||
{
|
||||
NSString *folderId, *itemId, *realCollectionId;
|
||||
SOGoMicrosoftActiveSyncFolderType folderType;
|
||||
SOGoMailAccounts *accountsFolder;
|
||||
SOGoMailFolder *currentFolder;
|
||||
SOGoUserFolder *userFolder;
|
||||
SOGoMailObject *mailObject;
|
||||
SOGoUserDefaults *ud;
|
||||
|
||||
BOOL htmlComposition, isHTML;
|
||||
id value;
|
||||
id value, currentCollection;
|
||||
|
||||
isHTML = NO;
|
||||
ud = [[context activeUser] userDefaults];
|
||||
@@ -3527,23 +3622,31 @@ void handle_eas_terminate(int signum)
|
||||
|
||||
value = [theDocumentElement getElementsByTagName: @"ReplaceMime"];
|
||||
|
||||
// We fetch the mail object from the server
|
||||
userFolder = [[context activeUser] homeFolderInContext: context];
|
||||
accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO];
|
||||
currentFolder = [accountsFolder lookupName: @"0" inContext: context acquire: NO];
|
||||
|
||||
currentCollection = [currentFolder lookupName: [NSString stringWithFormat: @"folder%@", realCollectionId]
|
||||
inContext: context
|
||||
acquire: NO];
|
||||
|
||||
mailObject = [currentCollection lookupName: itemId inContext: context acquire: NO];
|
||||
|
||||
// ReplaceMime IS specified so we must NOT use the server copy
|
||||
// but rather take the data as-is from the client.
|
||||
if ([value count])
|
||||
{
|
||||
[self processSendMail: theDocumentElement
|
||||
inResponse: theResponse];
|
||||
[self processSendMail: theDocumentElement inResponse: theResponse];
|
||||
if (!isSmartForward)
|
||||
[mailObject addFlags: @"Answered"];
|
||||
else
|
||||
[mailObject addFlags: @"$Forwarded"];
|
||||
return;
|
||||
}
|
||||
|
||||
if (folderType == ActiveSyncMailFolder)
|
||||
{
|
||||
SOGoMailAccounts *accountsFolder;
|
||||
SOGoMailFolder *currentFolder;
|
||||
SOGoUserFolder *userFolder;
|
||||
SOGoMailObject *mailObject;
|
||||
id currentCollection;
|
||||
|
||||
NGMimeMessage *messageFromSmartForward, *messageToSend;
|
||||
NGMimeMessageParser *parser;
|
||||
NSData *data;
|
||||
@@ -3562,16 +3665,6 @@ void handle_eas_terminate(int signum)
|
||||
|
||||
int a;
|
||||
|
||||
userFolder = [[context activeUser] homeFolderInContext: context];
|
||||
accountsFolder = [userFolder lookupName: @"Mail" inContext: context acquire: NO];
|
||||
currentFolder = [accountsFolder lookupName: @"0" inContext: context acquire: NO];
|
||||
|
||||
currentCollection = [currentFolder lookupName: [NSString stringWithFormat: @"folder%@", realCollectionId]
|
||||
inContext: context
|
||||
acquire: NO];
|
||||
|
||||
mailObject = [currentCollection lookupName: itemId inContext: context acquire: NO];
|
||||
|
||||
parser = [[NGMimeMessageParser alloc] init];
|
||||
data = [[[[(id)[theDocumentElement getElementsByTagName: @"MIME"] lastObject] textValue] stringByDecodingBase64] dataUsingEncoding: NSUTF8StringEncoding];
|
||||
messageFromSmartForward = [parser parsePartFromData: data];
|
||||
@@ -3937,6 +4030,14 @@ void handle_eas_terminate(int signum)
|
||||
|
||||
// Get the device ID, device type and "stash" them
|
||||
deviceId = [[theRequest uri] deviceId];
|
||||
|
||||
if ([deviceId isEqualToString: @"Unknown"])
|
||||
{
|
||||
[(WOResponse *)theResponse setStatus: 500];
|
||||
[self logWithFormat: @"EAS - No device id provided, ignoring request."];
|
||||
return nil;
|
||||
}
|
||||
|
||||
[context setObject: deviceId forKey: @"DeviceId"];
|
||||
[context setObject: [[theRequest uri] deviceType] forKey: @"DeviceType"];
|
||||
[context setObject: [[theRequest uri] attachmentName] forKey: @"AttachmentName"];
|
||||
@@ -3993,23 +4094,32 @@ void handle_eas_terminate(int signum)
|
||||
}
|
||||
|
||||
xml = [NSString stringWithFormat: @"<?xml version=\"1.0\"?><!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\"><%@ xmlns=\"ComposeMail:\"><SaveInSentItems/><MIME>%@</MIME></%@>", cmdName, [s stringByEncodingBase64], cmdName];
|
||||
|
||||
|
||||
|
||||
d = [xml dataUsingEncoding: NSASCIIStringEncoding];
|
||||
}
|
||||
else
|
||||
{
|
||||
d = [[theRequest content] wbxml2xml];
|
||||
// Handle empty Ping request, no need to try decoding the WBXML blob here
|
||||
if ([[theRequest content] length])
|
||||
d = [[theRequest content] wbxml2xml];
|
||||
else
|
||||
d = nil;
|
||||
}
|
||||
|
||||
documentElement = nil;
|
||||
|
||||
if (!d)
|
||||
{
|
||||
// If we got no data in the SendMail request, that means SOPE rejected it because of the WOMaxUploadSize.
|
||||
// We generate here the proper failed response for SendMail
|
||||
if ([cmdName caseInsensitiveCompare: @"SendMail"] == NSOrderedSame)
|
||||
{
|
||||
[theResponse setHeader: @"application/vnd.ms-sync.wbxml" forKey: @"Content-Type"];
|
||||
[theResponse setContent: [self _sendMailErrorResponseWithStatus: 122]];
|
||||
goto return_response;
|
||||
}
|
||||
// We check if it's a Ping command with no body.
|
||||
// See http://msdn.microsoft.com/en-us/library/ee200913(v=exchg.80).aspx for details
|
||||
if ([cmdName caseInsensitiveCompare: @"Ping"] != NSOrderedSame && [cmdName caseInsensitiveCompare: @"GetAttachment"] != NSOrderedSame && [cmdName caseInsensitiveCompare: @"Sync"] != NSOrderedSame)
|
||||
else if ([cmdName caseInsensitiveCompare: @"Ping"] != NSOrderedSame && [cmdName caseInsensitiveCompare: @"GetAttachment"] != NSOrderedSame && [cmdName caseInsensitiveCompare: @"Sync"] != NSOrderedSame)
|
||||
{
|
||||
RELEASE(context);
|
||||
RELEASE(pool);
|
||||
@@ -4047,6 +4157,7 @@ void handle_eas_terminate(int signum)
|
||||
|
||||
[self performSelector: aSelector withObject: documentElement withObject: theResponse];
|
||||
|
||||
return_response:
|
||||
[theResponse setHeader: @"14.1" forKey: @"MS-Server-ActiveSync"];
|
||||
[theResponse setHeader: @"Sync,SendMail,SmartForward,SmartReply,GetAttachment,GetHierarchy,CreateCollection,DeleteCollection,MoveCollection,FolderSync,FolderCreate,FolderDelete,FolderUpdate,MoveItems,GetItemEstimate,MeetingResponse,Search,Settings,Ping,ItemOperations,ResolveRecipients,ValidateCert" forKey: @"MS-ASProtocolCommands"];
|
||||
[theResponse setHeader: @"2.5,12.0,12.1,14.0,14.1" forKey: @"MS-ASProtocolVersions"];
|
||||
|
||||
@@ -163,7 +163,7 @@ struct GlobalObjectId {
|
||||
const char *bytes;
|
||||
|
||||
uid = [event uid];
|
||||
uidAsASCII = [uid decodeFromHexidecimal];
|
||||
uidAsASCII = [uid dataUsingEncoding: NSASCIIStringEncoding];
|
||||
newGlobalId = (struct GlobalObjectId*)calloc(sizeof(uint8_t), sizeof(struct GlobalObjectId) + 0x0c + [uidAsASCII length]);
|
||||
|
||||
prefix = @"040000008200e00074c5b7101a82e008";
|
||||
@@ -726,12 +726,53 @@ struct GlobalObjectId {
|
||||
//
|
||||
//
|
||||
//
|
||||
- (iCalCalendar *) calendarFromIMIPMessage
|
||||
- (iCalCalendar *) _calendarFromParts: (NSArray *) parts
|
||||
parent: (id) parent
|
||||
{
|
||||
NSDictionary *part;
|
||||
id bodyPart;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < [parts count]; i++)
|
||||
{
|
||||
part = [parts objectAtIndex: i];
|
||||
bodyPart = [parent lookupImap4BodyPartKey: [NSString stringWithFormat: @"%d", i+1]
|
||||
inContext: self->context];
|
||||
|
||||
if ([[part objectForKey: @"type"] isEqualToString: @"text"] &&
|
||||
[[part objectForKey: @"subtype"] isEqualToString: @"calendar"])
|
||||
{
|
||||
if (bodyPart)
|
||||
{
|
||||
iCalCalendar *calendar;
|
||||
NSData *calendarData;
|
||||
|
||||
calendarData = [bodyPart fetchBLOBWithPeek: YES];
|
||||
calendar = nil;
|
||||
|
||||
NS_DURING
|
||||
calendar = [iCalCalendar parseSingleFromSource: calendarData];
|
||||
NS_HANDLER
|
||||
calendar = nil;
|
||||
NS_ENDHANDLER
|
||||
|
||||
return calendar;
|
||||
}
|
||||
}
|
||||
else if ([[part objectForKey: @"type"] isEqualToString: @"multipart"])
|
||||
return [self _calendarFromParts: [part objectForKey: @"parts"] parent: bodyPart];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (iCalCalendar *) calendarFromIMIPMessage
|
||||
{
|
||||
NSString *type, *subtype;
|
||||
NSArray *parts;
|
||||
int i;
|
||||
|
||||
type = [[[self bodyStructure] valueForKey: @"type"] lowercaseString];
|
||||
subtype = [[[self bodyStructure] valueForKey: @"subtype"] lowercaseString];
|
||||
@@ -764,38 +805,7 @@ struct GlobalObjectId {
|
||||
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 fetchBLOBWithPeek: YES];
|
||||
calendar = nil;
|
||||
|
||||
NS_DURING
|
||||
calendar = [iCalCalendar parseSingleFromSource: calendarData];
|
||||
NS_HANDLER
|
||||
calendar = nil;
|
||||
NS_ENDHANDLER
|
||||
|
||||
return calendar;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [self _calendarFromParts: parts parent: self];
|
||||
|
||||
return nil;
|
||||
}
|
||||
@@ -934,7 +944,7 @@ struct GlobalObjectId {
|
||||
else if ([method isEqualToString: @"COUNTER"])
|
||||
className = @"IPM.Schedule.Meeting.Resp.Tent";
|
||||
else if ([method isEqualToString: @"CANCEL"])
|
||||
className = @"IPM.Schedule.Meeting.Cancelled";
|
||||
className = @"IPM.Schedule.Meeting.Canceled";
|
||||
else
|
||||
className = @"IPM.Appointment";
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#import <NGCards/iCalAlarm.h>
|
||||
#import <NGCards/iCalEvent.h>
|
||||
#import <NGCards/iCalTrigger.h>
|
||||
#import <NGCards/NSCalendarDate+NGCards.h>
|
||||
|
||||
#include "NSDate+ActiveSync.h"
|
||||
|
||||
@implementation iCalAlarm (ActiveSync)
|
||||
|
||||
@@ -53,9 +56,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
nextAlarmDate = [self nextAlarmDate];
|
||||
delta = (int)(([[(iCalEvent *)parent startDate] timeIntervalSince1970] - [nextAlarmDate timeIntervalSince1970])/60);
|
||||
|
||||
// don't send negative reminder - not supported
|
||||
if (delta > 0)
|
||||
[s appendFormat: @"<Reminder xmlns=\"Calendar:\">%d</Reminder>", (int)delta];
|
||||
if ([parent isKindOfClass: [iCalEvent class]])
|
||||
{
|
||||
// don't send negative reminder - not supported
|
||||
if (delta > 0)
|
||||
[s appendFormat: @"<Reminder xmlns=\"Calendar:\">%d</Reminder>", (int)delta];
|
||||
}
|
||||
else
|
||||
{
|
||||
[s appendFormat: @"<ReminderTime xmlns=\"Task:\">%@</ReminderTime>", [nextAlarmDate activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
@@ -67,37 +77,47 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
iCalTrigger *trigger;
|
||||
id o;
|
||||
|
||||
o = [theValues objectForKey: @"Reminder"];
|
||||
|
||||
// Outlook: if reminder is set to 0 minutes before start save it as 1 minute since -> 0 minutes in not accepted by SOGo
|
||||
if ([o isEqualToString: @"0"])
|
||||
o = @"1";
|
||||
|
||||
trigger = [iCalTrigger elementWithTag: @"TRIGGER"];
|
||||
[trigger setValueType: @"DURATION"];
|
||||
[self setTrigger: trigger];
|
||||
[self setAction: @"DISPLAY"];
|
||||
|
||||
// SOGo web ui only supports 1w but not 2w (custom reminder only supports min/hours/days)
|
||||
// 1week = -P1W
|
||||
// 2weeks > -PxD
|
||||
// xdays > -PxD
|
||||
// xhours -> -PTxH
|
||||
// xmin -> -PTxM
|
||||
if ([o intValue] == 10080)
|
||||
[trigger setSingleValue: [NSString stringWithFormat: @"-P1W" ] forKey: @""];
|
||||
else
|
||||
if ((o = [theValues objectForKey: @"Reminder"]))
|
||||
{
|
||||
if (([o intValue] % 1440) == 0)
|
||||
[trigger setSingleValue: [NSString stringWithFormat: @"-P%dD", ([o intValue] / 1440)] forKey: @""];
|
||||
// Outlook: if reminder is set to 0 minutes before starttime, save it as 1 minute since -> 0 minutes in not accepted by SOGo
|
||||
if ([o isEqualToString: @"0"])
|
||||
o = @"1";
|
||||
|
||||
trigger = [iCalTrigger elementWithTag: @"TRIGGER"];
|
||||
[trigger setValueType: @"DURATION"];
|
||||
[self setTrigger: trigger];
|
||||
[self setAction: @"DISPLAY"];
|
||||
|
||||
// SOGo web ui only supports 1w but not 2w (custom reminder only supports min/hours/days)
|
||||
// 1week = -P1W
|
||||
// 2weeks > -PxD
|
||||
// xdays > -PxD
|
||||
// xhours -> -PTxH
|
||||
// xmin -> -PTxM
|
||||
if ([o intValue] == 10080)
|
||||
[trigger setSingleValue: [NSString stringWithFormat: @"-P1W" ] forKey: @""];
|
||||
else
|
||||
{
|
||||
if (([o intValue] % 60) == 0)
|
||||
[trigger setSingleValue: [NSString stringWithFormat: @"-PT%dH", ([o intValue] / 60)] forKey: @""];
|
||||
if (([o intValue] % 1440) == 0)
|
||||
[trigger setSingleValue: [NSString stringWithFormat: @"-P%dD", ([o intValue] / 1440)] forKey: @""];
|
||||
else
|
||||
[trigger setSingleValue: [NSString stringWithFormat: @"-PT%@M", o] forKey: @""];
|
||||
{
|
||||
if (([o intValue] % 60) == 0)
|
||||
[trigger setSingleValue: [NSString stringWithFormat: @"-PT%dH", ([o intValue] / 60)] forKey: @""];
|
||||
else
|
||||
[trigger setSingleValue: [NSString stringWithFormat: @"-PT%@M", o] forKey: @""];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((o = [theValues objectForKey: @"ReminderTime"]))
|
||||
{
|
||||
o = [o calendarDate];
|
||||
trigger = [iCalTrigger elementWithTag: @"TRIGGER"];
|
||||
[trigger setValueType: @"DATE-TIME"];
|
||||
[trigger setSingleValue: [NSString stringWithFormat: @"%@Z", [o iCalFormattedDateTimeString]] forKey: @""];
|
||||
[self setTrigger: trigger];
|
||||
[self setAction: @"DISPLAY"];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -231,9 +231,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's a normal event (ie, with no organizer/attendee) or we are the organizer to an event
|
||||
// invitation, we set the busy status to 2 (Busy)
|
||||
[s appendFormat: @"<BusyStatus xmlns=\"Calendar:\">%d</BusyStatus>", 2];
|
||||
// If it's a normal event (i.e. with no organizer/attendee) or we are the organizer of an event
|
||||
// invitation, we set the busy status depending on TRANSP.
|
||||
[s appendFormat: @"<BusyStatus xmlns=\"Calendar:\">%d</BusyStatus>", (([self isOpaque]) ? 2 : 0)];
|
||||
}
|
||||
|
||||
[s appendFormat: @"<MeetingStatus xmlns=\"Calendar:\">%d</MeetingStatus>", meetingStatus];
|
||||
@@ -474,7 +474,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
if ((o = [theValues objectForKey: @"BusyStatus"]))
|
||||
{
|
||||
[o intValue];
|
||||
if ([o boolValue])
|
||||
[self setTransparency: @"OPAQUE"];
|
||||
else
|
||||
[self setTransparency: @"TRANSPARENT"];
|
||||
}
|
||||
|
||||
//
|
||||
@@ -602,7 +605,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
}
|
||||
|
||||
// Recurrence
|
||||
if ((o = [theValues objectForKey: @"Recurrence"]))
|
||||
if ((o = [theValues objectForKey: @"Recurrence"]) && [o isKindOfClass: [NSDictionary class]])
|
||||
{
|
||||
iCalRecurrenceRule *rule;
|
||||
|
||||
@@ -855,7 +858,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
person = [iCalPerson elementWithTag: @"attendee"];
|
||||
[person setCn: [attendee objectForKey: @"Attendee_Name"]];
|
||||
[person setEmail: [attendee objectForKey: @"Attendee_Email"]];
|
||||
|
||||
|
||||
status = [[attendee objectForKey: @"Attendee_Status"] intValue];
|
||||
|
||||
switch (status)
|
||||
@@ -872,7 +875,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
case 0:
|
||||
case 5:
|
||||
default:
|
||||
[person setPartStat: @"NEEDS-ACTION"];
|
||||
{
|
||||
[person setPartStat: @"NEEDS-ACTION"];
|
||||
[person setRsvp: @"TRUE"];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -884,6 +890,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[self setAttendees: attendees];
|
||||
}
|
||||
}
|
||||
|
||||
[self setLastModified: [NSCalendarDate calendarDate]];
|
||||
}
|
||||
|
||||
- (void) changeParticipationStatus: (NSDictionary *) theValues
|
||||
|
||||
@@ -134,6 +134,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"%@:\">%d</Recurrence_DayOfWeek>", t, (1 << [dm firstDay])];
|
||||
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"%@:\">%d</Recurrence_WeekOfMonth>", t, firstOccurrence];
|
||||
[s appendFormat: @"<Recurrence_Interval xmlns=\"%@:\">%d</Recurrence_Interval>", t, [self repeatInterval]];
|
||||
}
|
||||
else if ([[self byMonthDay] count])
|
||||
{
|
||||
@@ -149,6 +150,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
dm = [self byDayMask];
|
||||
[s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"%@:\">%d</Recurrence_DayOfWeek>", t, (1 << [dm firstDay])];
|
||||
[s appendFormat: @"<Recurrence_WeekOfMonth xmlns=\"%@:\">%d</Recurrence_WeekOfMonth>", t, 5];
|
||||
[s appendFormat: @"<Recurrence_Interval xmlns=\"%@:\">%d</Recurrence_Interval>", t, [self repeatInterval]];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -43,9 +43,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#import <NGCards/iCalDateTime.h>
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
|
||||
#import <Appointments/iCalEntityObject+SOGo.h>
|
||||
|
||||
#include "NSDate+ActiveSync.h"
|
||||
#include "NSString+ActiveSync.h"
|
||||
#include "iCalRecurrenceRule+ActiveSync.h"
|
||||
#include "iCalAlarm+ActiveSync.h"
|
||||
|
||||
@implementation iCalToDo (ActiveSync)
|
||||
|
||||
@@ -95,8 +98,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
v = 1;
|
||||
[s appendFormat: @"<Importance xmlns=\"Tasks:\">%d</Importance>", v];
|
||||
|
||||
// Reminder - FIXME
|
||||
[s appendFormat: @"<ReminderSet xmlns=\"Tasks:\">%d</ReminderSet>", 0];
|
||||
// Reminder
|
||||
if ([self hasAlarms])
|
||||
{
|
||||
iCalAlarm *alarm;
|
||||
|
||||
alarm = [self firstDisplayOrAudioAlarm];
|
||||
[s appendFormat: @"<ReminderSet xmlns=\"Tasks:\">%d</ReminderSet>", 1];
|
||||
[s appendString: [alarm activeSyncRepresentationInContext: context]];
|
||||
}
|
||||
else
|
||||
{
|
||||
[s appendFormat: @"<ReminderSet xmlns=\"Tasks:\">%d</ReminderSet>", 0];
|
||||
}
|
||||
|
||||
// Sensitivity
|
||||
if ([[self accessClass] isEqualToString: @"PRIVATE"])
|
||||
@@ -145,7 +159,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[s appendString: @"</Body>"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -249,6 +263,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
if ((o = [theValues objectForKey: @"ReminderTime"]))
|
||||
{
|
||||
iCalAlarm *alarm;
|
||||
|
||||
alarm = [[iCalAlarm alloc] init];
|
||||
[alarm takeActiveSyncValues: theValues inContext: context];
|
||||
|
||||
[self removeAllAlarms];
|
||||
[self addToAlarms: alarm];
|
||||
RELEASE(alarm);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,11 @@ http://trochette.github.io/Angular-Design-Patterns-Best-Practices/
|
||||
* Move business logic into models and share them.
|
||||
* Keep it simple, separate server interaction and error handling from the model. That way model only handle data processing and code is easier to maintain.
|
||||
|
||||
Controllers
|
||||
^^^^^^^^^^^
|
||||
|
||||
* Functions not exposed in the controller must be prefixed with an underscore.
|
||||
|
||||
SASS/CSS
|
||||
~~~~~~~~
|
||||
|
||||
@@ -133,11 +138,6 @@ SASS/CSS
|
||||
A `@mixin` is like a stamp: it creates a duplicated version of the property block (optionally) with arguments provided. An `@extend` appends the element you are extending to the property block. It is your "yes, and ___" statement.
|
||||
|
||||
* For documentation, we follow http://sassdoc.com/[SassDoc] annotations.
|
||||
* We need the SASS files of Angular Material to build our CSS. The git repository of Angular Material is included as a submodule of SOGo:
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
* FlexBox compatibility http://caniuse.com/#feat=flexbox
|
||||
|
||||
Fonts
|
||||
@@ -155,10 +155,16 @@ Building frontend
|
||||
npm install -g grunt-cli
|
||||
npm install -g bower
|
||||
|
||||
* Generate JavaScript files
|
||||
* We need the SASS files of Angular Material to build our CSS. The git repository of Angular Material is included as a submodule of SOGo:
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
* Generate the JavaScript and CSS files
|
||||
|
||||
cd UI/WebServerResources
|
||||
npm install
|
||||
bower install
|
||||
grunt build
|
||||
|
||||
Version Control
|
||||
|
||||
@@ -238,6 +238,14 @@ sources, install the following package:
|
||||
rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
|
||||
----
|
||||
|
||||
SOGo relies on the GNUstep packages provided by Inverse and must not use the
|
||||
packages from EPEL. Adjust the repository definition to exclude those packages:
|
||||
|
||||
----
|
||||
sed -i '/enabled=1/a \
|
||||
exclude=gnustep*' /etc/yum.repos.d/epel.repo
|
||||
----
|
||||
|
||||
For more information on EPEL, visit http://fedoraproject.org/wiki/EPEL/.
|
||||
|
||||
Software Installation
|
||||
@@ -391,9 +399,14 @@ internet connection could be killed prematurely.
|
||||
|Parameter used to set the maximum allowed size for content being
|
||||
sent to SOGo using a PUT or a POST call. This can also limit the file
|
||||
attachment size being uploaded to SOGo when composing a mail. The
|
||||
value is in kilobyte. By default, the value is 0, or disabled so no
|
||||
value is in kilobytes. By default, the value is 0, or disabled so no
|
||||
limit will be set.
|
||||
|
||||
|S |SOGoMaximumMessageSizeLimit
|
||||
|Parameter used to set the maximum allowed email message size when
|
||||
composing a mail. The value is in kilobytes. By default, the value is 0,
|
||||
or disabled so no limit will be set.
|
||||
|
||||
|S |SxVMemLimit
|
||||
|Parameter used to set the maximum amount of memory (in
|
||||
megabytes) that a child can use. Reaching that value will force children
|
||||
@@ -501,7 +514,7 @@ SOGoSAML2LogoutEnabled must be set to YES. If unset, the user will be
|
||||
redirected to a blank page.
|
||||
|
||||
|D |SOGoTimeZone
|
||||
|Parameter used to set a default time zone for users. The default
|
||||
|Mandatory parameter used to set a default time zone for users. The default
|
||||
timezone is set to UTC. The Olson database is a standard database that
|
||||
takes all the time zones around the world into account and represents
|
||||
them along with their history. On GNU/Linux systems, time zone
|
||||
@@ -2721,6 +2734,12 @@ have unexpected behaviour with various ActiveSync clients.
|
||||
EAS command.
|
||||
|
||||
Defaults to `NO`, which means no logging is performed.
|
||||
|
||||
|S |SOGoMaximumPictureSize
|
||||
|Parameter used to overwrite the maximum number of bytes returned in the picture
|
||||
for EAS Search operations in the GAL.
|
||||
|
||||
If not set, it defaults to `102400` bytes, or 100 KB.
|
||||
|=======================================================================
|
||||
|
||||
Please be aware of the following limitations:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- TODO have the build system take care of this -->
|
||||
<releaseinfo>Version 3.2.3 - November 2016</releaseinfo>
|
||||
<subtitle>for version 3.2.3</subtitle>
|
||||
<date>2016-11-25</date>
|
||||
<releaseinfo>Version 3.2.9 - May 2017</releaseinfo>
|
||||
<subtitle>for version 3.2.9</subtitle>
|
||||
<date>2017-05-09</date>
|
||||
|
||||
<legalnotice>
|
||||
<para>Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".</para>
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
Authors:
|
||||
- Inverse inc. <info@inverse.ca>
|
||||
|
||||
Copyright (C) 2008-2016 Inverse inc.
|
||||
Copyright (C) 2008-2017 Inverse inc.
|
||||
License: GFDL 1.2 or later. http://www.gnu.org/licenses/fdl.html
|
||||
|
||||
////
|
||||
|
||||
// TODO have the build system take care of this
|
||||
|
||||
:release_version: 3.2.3
|
||||
:release_version: 3.2.9
|
||||
|
||||
// vim: set syntax=asciidoc tabstop=2 shiftwidth=2 expandtab:
|
||||
+16
-5
@@ -27,6 +27,7 @@
|
||||
#import <GDLContentStore/GCSAlarmsFolder.h>
|
||||
#import <GDLContentStore/GCSSessionsFolder.h>
|
||||
|
||||
#import <NGObjWeb/NSException+HTTP.h>
|
||||
#import <NGObjWeb/SoClassSecurityInfo.h>
|
||||
#import <NGObjWeb/WOContext.h>
|
||||
#import <NGObjWeb/WORequest+So.h>
|
||||
@@ -114,7 +115,7 @@ static BOOL debugLeaks;
|
||||
vMemSizeLimit = [defaults vmemLimit];
|
||||
if (vMemSizeLimit > 0)
|
||||
[self logWithFormat: @"vmem size check enabled: shutting down app when "
|
||||
@"vmem > %d MB", vMemSizeLimit];
|
||||
@"vmem > %d MB. Currently at %d MB", vMemSizeLimit, [[NSProcessInfo processInfo] virtualMemorySize]/1048576];
|
||||
|
||||
/* SoClass security declarations */
|
||||
sInfo = [self soClassSecurityInfo];
|
||||
@@ -137,6 +138,8 @@ static BOOL debugLeaks;
|
||||
|
||||
/* load products */
|
||||
[[SOGoProductLoader productLoader] loadAllProducts: YES];
|
||||
if (vMemSizeLimit > 0)
|
||||
[self logWithFormat: @"All products loaded - current memory usage at %d MB", [[NSProcessInfo processInfo] virtualMemorySize]/1048576];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
@@ -418,8 +421,12 @@ static BOOL debugLeaks;
|
||||
"GET" if no method was provided in the query path.
|
||||
*/
|
||||
if ([_key length] > 0 && ![_key isEqualToString:@"favicon.ico"])
|
||||
obj = [self lookupUser: _key inContext: _ctx];
|
||||
}
|
||||
{
|
||||
obj = [self lookupUser: _key inContext: _ctx];
|
||||
if (!obj && ![_key isEqualToString: @"public"])
|
||||
obj = [self lookupUser: @"anonymous" inContext: _ctx];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
obj = nil;
|
||||
@@ -445,8 +452,12 @@ static BOOL debugLeaks;
|
||||
- (WOResponse *) handleException: (NSException *) _exc
|
||||
inContext: (WOContext *) _ctx
|
||||
{
|
||||
printf("EXCEPTION: %s\n", [[_exc description] cString]);
|
||||
abort();
|
||||
WOResponse *resp;
|
||||
|
||||
NSLog(@"EXCEPTION: %s\n", [[_exc description] cString]);
|
||||
resp = [WOResponse responseWithRequest: [_ctx request]];
|
||||
[resp setStatus: 501];
|
||||
return resp;
|
||||
}
|
||||
|
||||
/* runtime maintenance */
|
||||
|
||||
@@ -1,3 +1,186 @@
|
||||
3.2.9 (2017-05-09)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- [core] email alarms now have pretty formatting (#805)
|
||||
|
||||
Enhancements
|
||||
- [core] improved event invitation for all day events (#4145)
|
||||
- [web] improved interface refresh time with external IMAP accounts
|
||||
- [eas] added photo support for GAL search operations
|
||||
|
||||
Bug fixes
|
||||
- [web] fixed attachment path when inside multiple body parts
|
||||
- [web] fixed email reminder with attendees (#4115)
|
||||
- [web] prevented form to be marked dirty when changing password (#4138)
|
||||
- [web] restored support for SOGoLDAPContactInfoAttribute
|
||||
- [web] avoid duplicated email addresses in LDAP-based addressbook (#4129)
|
||||
- [web] fixed mail delegation of pristine user accounts (#4160)
|
||||
- [core] cherry-picked comma escaping fix from v2 (#3296)
|
||||
- [core] fix sogo-tool restore potentially crashing on corrupted data (#4048)
|
||||
- [core] handle properly mails using windows-1255 charset (#4124)
|
||||
- [core] fixed email reminders sent multiple times (#4100)
|
||||
- [core] fixed LDIF to vCard conversion for non-handled multi-value attributes (#4086)
|
||||
- [core] properly honor the "include in freebusy" setting (#3354)
|
||||
- [core] make sure to use crypt scheme when encoding md5/sha256/sha512 (#4137)
|
||||
- [eas] set reply/forwarded flags when ReplaceMime is set (#4133)
|
||||
- [eas] remove alarms over EAS if we don't want them (#4059)
|
||||
- [eas] correctly set RSVP on event invitations
|
||||
- [eas] avoid sending IMIP request/update messages for all EAS clients (#4022)
|
||||
|
||||
3.2.8 (2017-03-24)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- [core] new sogo-tool manage-acl command to manage calendar/address book ACLs
|
||||
|
||||
Enhancements
|
||||
- [web] constrain event/task reminder to a positive number
|
||||
- [web] display year in day and week views
|
||||
- [web] split string on comma and semicolon when pasting multiple addresses (#4097)
|
||||
- [web] restrict Draft/Sent/Trash/Junk mailboxes to the top level
|
||||
- [web] animations are automatically disabled under IE11
|
||||
- [web] updated Angular Material to version 1.1.3
|
||||
|
||||
Bug fixes
|
||||
- [core] handle broken CalDAV clients sending bogus SENT-BY (#3992)
|
||||
- [core] fixed handling of exdates and proper intersection for fbinfo (#4051)
|
||||
- [core] remove attendees that have the same identity as the organizer (#3905)
|
||||
- [web] fixed ACL editor in admin module for Safari (#4036)
|
||||
- [web] fixed function call when removing contact category (#4039)
|
||||
- [web] localized mailbox names everywhere (#4040, #4041)
|
||||
- [web] hide fab button when printing (#4038)
|
||||
- [web] SOGoCalendarWeekdays must now be defined before saving preferences
|
||||
- [web] fixed CAS session timeout handling during XHR requests (#1456)
|
||||
- [web] exposed default value of SOGoMailAutoSave (#4053)
|
||||
- [web] exposed default value of SOGoMailAddOutgoingAddresses (#4064)
|
||||
- [web] fixed handling of contact organizations (#4028)
|
||||
- [web] fixed handling of attachments in mail editor (#4058, #4063)
|
||||
- [web] fixed saving draft outside Mail module (#4071)
|
||||
- [web] fixed SCAYT automatic language selection in HTML editor
|
||||
- [web] fixed task sorting on multiple categories
|
||||
- [web] fixed sanitisation of flags in Sieve filters (#4087)
|
||||
- [web] fixed missing CC or BCC when specified before sending message (#3944)
|
||||
- [web] enabled Save button after deleting attributes from a card (#4095)
|
||||
- [web] don't show Copy To and Move To menu options when user has a single address book
|
||||
- [web] fixed display of category colors in events and tasks lists
|
||||
- [eas] fixed opacity in EAS freebusy (#4033)
|
||||
|
||||
3.2.7 (2017-02-14)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- [core] new sogo-tool checkup command to make sure user's data is sane
|
||||
|
||||
Enhancements
|
||||
- [web] added Hebrew (he) translation - thanks to Raz Aidlitz
|
||||
|
||||
Bug fixes
|
||||
- [core] generalized the bcc handling code
|
||||
- [web] saving the preferences was not possible when Mail module is disabled
|
||||
- [web] ignore mouse events in scrollbars of Month view (#3990)
|
||||
- [web] fixed public URL with special characters (#3993)
|
||||
- [web] keep the fab button visible when the center list is hidden
|
||||
- [web] localized mail, phone, url and address types (#4030)
|
||||
- [eas] improved EAS parameters parsing (#4003)
|
||||
- [eas] properly handle canceled appointments
|
||||
|
||||
3.2.6a (2017-01-26)
|
||||
-------------------
|
||||
|
||||
Bug fixes
|
||||
- [core] fixed "include in freebusy" (reverts #3354)
|
||||
- [web] improved ACLs handling of inactive users
|
||||
|
||||
3.2.6 (2017-01-23)
|
||||
------------------
|
||||
|
||||
Enhancements
|
||||
- [web] show locale codes beside language names in Preferences module
|
||||
- [web] fixed visual glitches in Month view with Firefox
|
||||
- [web] mail editor can now be expanded horizontally and automatically expands vertically
|
||||
- [web] compose a new message inline or in a popup window
|
||||
- [web] allow to select multiple files when uploading attachments (#3999)
|
||||
- [web] use "date" extension of Sieve to enable/disable vacation auto-reply (#1530, #1949)
|
||||
- [web] updated Angular to version 1.6.1
|
||||
- [web] updated CKEditor to version 4.6.2
|
||||
|
||||
Bug fixes
|
||||
- [core] remove all alarms before sending IMIP replies (#3925)
|
||||
- [web] fixed rendering of forwared HTML message with inline images (#3981)
|
||||
- [web] fixed pasting images in CKEditor using Chrome (#3986)
|
||||
- [eas] make sure we trigger a download of service-side changed events
|
||||
- [eas] now strip attendees with no email during MeetingResponse calls
|
||||
|
||||
3.2.5 (2017-01-10)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- [web] download attachments of a message as a zip archive
|
||||
|
||||
Enhancements
|
||||
- [core] improved IMIP handling from Exchange/Outlook clients
|
||||
- [web] prevent using localhost on additional IMAP accounts
|
||||
- [web] renamed buttons of alarm toast (#3945)
|
||||
- [web] load photos of LDAP-based address books in contacts list (#3942)
|
||||
- [web] added SOGoMaximumMessageSizeLimit to limit webmail message size
|
||||
- [web] added photo support for LDIF import (#1084)
|
||||
- [web] updated CKEditor to version 4.6.1
|
||||
|
||||
Bug fixes
|
||||
- [core] honor blocking wrong login attempts within time interval (#2850)
|
||||
- [core] better support for RFC 6638 (schedule-agent)
|
||||
- [core] use source's domain when none defined and trying to match users (#3523)
|
||||
- [core] handle delegation with no SENT-BY set (#3368)
|
||||
- [core] properly honor the "include in freebusy" setting (#3354)
|
||||
- [core] properly save next email alarm in the database (#3949)
|
||||
- [core] fix events in floating time during CalDAV's PUT operation (#2865)
|
||||
- [core] handle rounds in sha512-crypt password hashes
|
||||
- [web] fixed confusion between owner and active user in ACLs management of Administration module
|
||||
- [web] fixed JavaScript exception after renaming an address book
|
||||
- [web] fixed Sieve folder encoding support (#3904)
|
||||
- [web] fixed ordering of calendars when renaming or adding a calendar (#3931)
|
||||
- [web] use the organizer's alarm by default when accepting IMIP messages (#3934)
|
||||
- [web] switch on "Remember username" when cookie username is set
|
||||
- [web] return login page for unknown users (#2135)
|
||||
- [web] fixed saving monthly recurrence rule with "by day" condition (#3948)
|
||||
- [web] fixed display of message content when enabling auto-reply (#3940)
|
||||
- [web] don't allow to create lists in a remote address book (not yet supported)
|
||||
- [web] fixed attached links in task viewer (#3963)
|
||||
- [web] avoid duplicate mail entries in contact of LDAP-based address book (#3941)
|
||||
- [web] append ics file extension when importing events (#2308)
|
||||
- [web] handle URI in vCard photos (#2683)
|
||||
- [web] handle semicolon in values during LDIF import (#1760)
|
||||
- [web] fixed computation of week number (#3973, #3976)
|
||||
- [web] fixed saving of inactive calendars (#3862, #3980)
|
||||
- [web] fixed public URLs to Calendars (#3974)
|
||||
- [web] fixed hotkeys in Mail module when a dialog is active (#3983)
|
||||
- [eas] properly skip folders we don't want to synchronize (#3943)
|
||||
- [eas] fixed 30 mins freebusy offset with S Planner
|
||||
- [eas] now correctly handles reminders on tasks (#3964)
|
||||
- [eas] always force save events creation over EAS (#3958)
|
||||
- [eas] do not decode from hex the event's UID (#3965)
|
||||
- [eas] add support for "other addresses" (#3966)
|
||||
- [eas] provide correct response status when sending too big mails (#3956)
|
||||
|
||||
3.2.4 (2016-12-01)
|
||||
------------------
|
||||
|
||||
New features
|
||||
- [core] new sogo-tool cleanup user feature
|
||||
|
||||
Enhancements
|
||||
- [core] added handling of BYSETPOS for BYDAY in recurrence rules
|
||||
- [web] added sort by start date for tasks (#3840)
|
||||
|
||||
Bug fixes
|
||||
- [web] fixed JavaScript exception when SOGo is launched from an external link (#3900)
|
||||
- [web] restored fetching of freebusy information of MS Exchange contacts
|
||||
- [web] fixed mail attribute when importing an LDIF file (#3878)
|
||||
- [web] don't save empty custom auto-reply subject
|
||||
- [web] fixed detection of session expiration
|
||||
- [eas] properly escape all GAL responses (#3923)
|
||||
|
||||
3.2.3 (2016-11-25)
|
||||
------------------
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ SOGo and its associated components are available in various languages. The follo
|
||||
* [fi] Finnish - Kari Salmu
|
||||
* [fr] French - [Inverse](http://www.inverse.ca/)
|
||||
* [de] German - Alexander Greiner-Baer
|
||||
* [he] Hebrew - Raz Aidlitz
|
||||
* [hu] Hungarian - Sándor Kuti
|
||||
* [is] Icelandic - Anna Jonna Armannsdottir
|
||||
* [it] Italian - Alessio Fattorini
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
|
||||
- (NSException *) deleteContentWithName: (NSString *) _name;
|
||||
- (NSException *) deleteAllContent;
|
||||
- (NSException *) purgeDeletedRecordsBefore: (unsigned int) days;
|
||||
- (NSException *) touchContentWithName: (NSString *) _name;
|
||||
|
||||
- (NSException *) deleteFolder;
|
||||
@@ -144,6 +145,7 @@
|
||||
- (void) deleteAclWithSpecification: (EOFetchSpecification *) _fs;
|
||||
|
||||
- (unsigned int) recordsCountByExcludingDeleted: (BOOL) includeDeleted;
|
||||
- (unsigned int) recordsCountDeletedBefore: (unsigned int) days;
|
||||
|
||||
- (NSCalendarDate *) lastModificationDate;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
+ (void) initialize
|
||||
{
|
||||
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
|
||||
debugOn = [ud boolForKey:@"GCSFolderDebugEnabled"];
|
||||
doLogStore = [ud boolForKey:@"GCSFolderStoreDebugEnabled"];
|
||||
|
||||
@@ -91,7 +91,7 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
NSEnumerator *fields;
|
||||
GCSFieldInfo *field;
|
||||
NSString *fieldName;
|
||||
|
||||
|
||||
if ((self = [super init])) {
|
||||
folderManager = [_fm retain];
|
||||
folderInfo = [_ftype retain];
|
||||
@@ -114,7 +114,7 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
if (![fieldName isEqualToString: @"c_name"])
|
||||
[contentFieldNames addObject: fieldName];
|
||||
}
|
||||
|
||||
|
||||
folderId = [_folderId copy];
|
||||
folderName = [[_path lastPathComponent] copy];
|
||||
path = [_path copy];
|
||||
@@ -124,7 +124,7 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
folderTypeName = [_ftname copy];
|
||||
|
||||
ofFlags.requiresFolderSelect = 0;
|
||||
ofFlags.sameTableForQuick =
|
||||
ofFlags.sameTableForQuick =
|
||||
[location isEqualTo:quickLocation] ? 1 : 0;
|
||||
}
|
||||
return self;
|
||||
@@ -133,7 +133,7 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
- (id) init
|
||||
{
|
||||
return [self initWithPath:nil primaryKey:nil
|
||||
folderTypeName:nil folderType:nil
|
||||
folderTypeName:nil folderType:nil
|
||||
location:nil quickLocation:nil
|
||||
aclLocation:nil
|
||||
folderManager:nil];
|
||||
@@ -271,13 +271,13 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
NSDictionary *ui;
|
||||
|
||||
ui = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithUnsignedInt:_base],
|
||||
[NSNumber numberWithUnsignedInt:_base],
|
||||
@"GCSExpectedVersion",
|
||||
[NSNumber numberWithUnsignedInt:_store],
|
||||
@"GCSStoredVersion",
|
||||
self, @"GCSFolder",
|
||||
nil];
|
||||
|
||||
|
||||
return [NSException exceptionWithName:@"GCSVersionMismatch"
|
||||
reason:@"Transaction conflict during a GCS modification."
|
||||
userInfo:ui];
|
||||
@@ -369,7 +369,7 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
requirement: (GCSTableRequirement) requirement
|
||||
{
|
||||
NSString *selectedFields;
|
||||
|
||||
|
||||
if (requirement == bothTableRequired && [fields containsObject: @"c_name"])
|
||||
selectedFields = [self _dottedFields: fields];
|
||||
else
|
||||
@@ -381,7 +381,7 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
- (NSString *) _sqlForQualifier: (EOQualifier *) qualifier
|
||||
{
|
||||
NSMutableString *ms;
|
||||
|
||||
|
||||
if (qualifier)
|
||||
{
|
||||
ms = [NSMutableString stringWithCapacity:32];
|
||||
@@ -399,7 +399,7 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
|
||||
if ((count = [_so count]) == 0)
|
||||
return nil;
|
||||
|
||||
|
||||
sql = [NSMutableString stringWithCapacity:(count * 16)];
|
||||
for (i = 0; i < count; i++) {
|
||||
EOSortOrdering *so;
|
||||
@@ -409,9 +409,9 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
so = [_so objectAtIndex:i];
|
||||
sel = [so selector];
|
||||
column = [so key];
|
||||
|
||||
|
||||
if (i > 0) [sql appendString:@", "];
|
||||
|
||||
|
||||
if (sel_eq(sel, EOCompareAscending)) {
|
||||
[sql appendString:column];
|
||||
[sql appendString:@" ASC"];
|
||||
@@ -558,21 +558,21 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
error = [channel evaluateExpressionX:sql];
|
||||
if (error)
|
||||
{
|
||||
[self errorWithFormat:@"%s: cannot execute quick-fetch SQL '%@': %@",
|
||||
[self errorWithFormat:@"%s: cannot execute quick-fetch SQL '%@': %@",
|
||||
__PRETTY_FUNCTION__, sql, error];
|
||||
results = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fetch results */
|
||||
|
||||
|
||||
results = [NSMutableArray arrayWithCapacity: 64];
|
||||
attrs = [channel describeResults: NO /* do not beautify names */];
|
||||
while ((row = [channel fetchAttributes: attrs withZone: NULL]))
|
||||
[results addObject: row];
|
||||
|
||||
/* release channels */
|
||||
|
||||
|
||||
}
|
||||
[self releaseChannel: channel];
|
||||
// NSLog(@"/running query");
|
||||
@@ -582,7 +582,7 @@ static GCSStringFormatter *stringFormatter = nil;
|
||||
[self errorWithFormat:@" could not open storage channel!"];
|
||||
results = nil;
|
||||
}
|
||||
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -764,7 +764,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
EOAttribute *attribute;
|
||||
id value;
|
||||
unsigned i, count;
|
||||
|
||||
|
||||
if (_row == nil || _table == nil)
|
||||
return nil;
|
||||
|
||||
@@ -774,7 +774,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
[sql appendString:@"UPDATE "];
|
||||
[sql appendString:_table];
|
||||
[sql appendString:@" SET "];
|
||||
|
||||
|
||||
for (i = 0, count = [keys count]; i < count; i++) {
|
||||
fieldName = [keys objectAtIndex:i];
|
||||
|
||||
@@ -823,7 +823,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
{
|
||||
EOAttribute *attribute;
|
||||
EOEntity *entity;
|
||||
|
||||
|
||||
entity = AUTORELEASE([[EOEntity alloc] init]);
|
||||
[entity setName: _name];
|
||||
[entity setExternalName: _name];
|
||||
@@ -841,7 +841,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
EOAttribute *attribute;
|
||||
EOEntity *entity;
|
||||
|
||||
entity = [self _entityWithName: [self storeTableName]];
|
||||
entity = [self _entityWithName: [self storeTableName]];
|
||||
|
||||
attribute = AUTORELEASE([[EOAttribute alloc] init]);
|
||||
[attribute setName: @"c_version"];
|
||||
@@ -873,7 +873,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
|
||||
- (EOSQLQualifier *) _qualifierUsingWhereColumn:(NSString *)_colname
|
||||
isEqualTo:(id)_value
|
||||
andColumn:(NSString *)_colname2
|
||||
andColumn:(NSString *)_colname2
|
||||
isEqualTo:(id)_value2
|
||||
entity: (EOEntity *)_entity
|
||||
withAdaptor: (EOAdaptor *)_adaptor
|
||||
@@ -970,7 +970,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
NSArray *rows;
|
||||
NSException *error;
|
||||
|
||||
/* check preconditions */
|
||||
/* check preconditions */
|
||||
if (_name)
|
||||
{
|
||||
if (_content)
|
||||
@@ -979,10 +979,10 @@ andAttribute: (EOAttribute *)_attribute
|
||||
error = nil;
|
||||
nowDate = [NSCalendarDate date];
|
||||
now = [NSNumber numberWithUnsignedInt:[nowDate timeIntervalSince1970]];
|
||||
|
||||
|
||||
if (doLogStore)
|
||||
[self logWithFormat:@"should store content: '%@'\n%@", _name, _content];
|
||||
|
||||
|
||||
rows = [self fetchFields: [NSArray arrayWithObjects:
|
||||
@"c_version",
|
||||
@"c_deleted",
|
||||
@@ -1021,6 +1021,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
NSInvocation *anInvocation;
|
||||
SEL aSelector;
|
||||
|
||||
quickRow = nil;
|
||||
aSelector = @selector(quickRecordFromContent:container:nameInContainer:);
|
||||
aSignature = [[theComponent class] instanceMethodSignatureForSelector: aSelector];
|
||||
anInvocation = [NSInvocation invocationWithMethodSignature:aSignature];
|
||||
@@ -1035,16 +1036,16 @@ andAttribute: (EOAttribute *)_attribute
|
||||
if (quickRow)
|
||||
{
|
||||
[quickRow setObject:_name forKey:@"c_name"];
|
||||
|
||||
|
||||
if (doLogStore)
|
||||
[self logWithFormat:@" store quick: %@", quickRow];
|
||||
|
||||
|
||||
/* make content row */
|
||||
contentRow = [NSMutableDictionary dictionaryWithCapacity:16];
|
||||
|
||||
|
||||
if (ofFlags.sameTableForQuick)
|
||||
[contentRow addEntriesFromDictionary:quickRow];
|
||||
|
||||
|
||||
[contentRow setObject:_name forKey:@"c_name"];
|
||||
[contentRow setObject:now forKey:@"c_lastmodified"];
|
||||
if (isNewRecord)
|
||||
@@ -1058,7 +1059,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
[NSNumber numberWithInt:([storedVersion intValue] + 1)]
|
||||
forKey:@"c_version"];
|
||||
[contentRow setObject:_content forKey:@"c_content"];
|
||||
|
||||
|
||||
/* open channels */
|
||||
storeChannel = [self acquireStoreChannel];
|
||||
if (storeChannel)
|
||||
@@ -1080,14 +1081,14 @@ andAttribute: (EOAttribute *)_attribute
|
||||
/* we check if we can call directly methods on our adaptor
|
||||
channel delegate. If not, we generate SQL ourself since it'll
|
||||
be a little bit faster and less complex than using GDL to do so */
|
||||
hasInsertDelegate = [[storeChannel delegate]
|
||||
hasInsertDelegate = [[storeChannel delegate]
|
||||
respondsToSelector: @selector(adaptorChannel:willInsertRow:forEntity:)];
|
||||
hasUpdateDelegate = [[storeChannel delegate]
|
||||
respondsToSelector: @selector(adaptorChannel:willUpdateRow:describedByQualifier:)];
|
||||
|
||||
[[quickChannel adaptorContext] beginTransaction];
|
||||
[[storeChannel adaptorContext] beginTransaction];
|
||||
|
||||
|
||||
quickTableEntity = [self _quickTableEntity];
|
||||
storeTableEntity = [self _storeTableEntity];
|
||||
|
||||
@@ -1097,10 +1098,10 @@ andAttribute: (EOAttribute *)_attribute
|
||||
error = (hasInsertDelegate
|
||||
? [quickChannel insertRowX: quickRow forEntity: quickTableEntity]
|
||||
: [quickChannel
|
||||
evaluateExpressionX: [self _generateInsertStatementForRow: quickRow
|
||||
evaluateExpressionX: [self _generateInsertStatementForRow: quickRow
|
||||
adaptor: [[quickChannel adaptorContext] adaptor]
|
||||
tableName: [self quickTableName]]]);
|
||||
|
||||
|
||||
if (!error)
|
||||
error = (hasInsertDelegate
|
||||
? [storeChannel insertRowX: contentRow forEntity: storeTableEntity]
|
||||
@@ -1138,7 +1139,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
andColumn: (*_baseVersion != 0 ? (id)@"c_version" : (id)nil)
|
||||
isEqualTo: (*_baseVersion != 0 ? [NSNumber numberWithUnsignedInt: *_baseVersion] : (NSNumber *)nil)]]);
|
||||
}
|
||||
|
||||
|
||||
if (error)
|
||||
{
|
||||
[[storeChannel adaptorContext] rollbackTransaction];
|
||||
@@ -1193,19 +1194,19 @@ andAttribute: (EOAttribute *)_attribute
|
||||
NSException *error;
|
||||
NSString *delsql;
|
||||
NSCalendarDate *nowDate;
|
||||
|
||||
|
||||
/* check preconditions */
|
||||
if (_name == nil) {
|
||||
return [NSException exceptionWithName:@"GCSDeleteException"
|
||||
reason:@"no content filename was provided"
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
|
||||
if (doLogStore)
|
||||
[self logWithFormat:@"should delete content: '%@'", _name];
|
||||
|
||||
|
||||
/* open channels */
|
||||
|
||||
|
||||
if ((storeChannel = [self acquireStoreChannel]) == nil) {
|
||||
[self errorWithFormat:@"could not open storage channel!"];
|
||||
return nil;
|
||||
@@ -1242,7 +1243,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
delsql = [delsql stringByAppendingFormat:@" AND c_folder_id = %@", folderId];
|
||||
if ((error = [storeChannel evaluateExpressionX:delsql]) != nil) {
|
||||
[self errorWithFormat:
|
||||
@"%s: cannot delete content '%@': %@",
|
||||
@"%s: cannot delete content '%@': %@",
|
||||
__PRETTY_FUNCTION__, delsql, error];
|
||||
}
|
||||
else if (!ofFlags.sameTableForQuick) {
|
||||
@@ -1256,19 +1257,19 @@ andAttribute: (EOAttribute *)_attribute
|
||||
delsql = [delsql stringByAppendingFormat:@" AND c_folder_id = %@", folderId];
|
||||
if ((error = [quickChannel evaluateExpressionX:delsql]) != nil) {
|
||||
[self errorWithFormat:
|
||||
@"%s: cannot delete quick row '%@': %@",
|
||||
@"%s: cannot delete quick row '%@': %@",
|
||||
__PRETTY_FUNCTION__, delsql, error];
|
||||
/*
|
||||
/*
|
||||
Note: we now have a "broken" record, needs to be periodically GCed by
|
||||
a script!
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* release channels and return */
|
||||
[adaptorCtx commitTransaction];
|
||||
[self releaseChannel:storeChannel];
|
||||
|
||||
|
||||
if (!ofFlags.sameTableForQuick) {
|
||||
[[quickChannel adaptorContext] commitTransaction];
|
||||
[self releaseChannel:quickChannel];
|
||||
@@ -1307,7 +1308,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
query = [NSString stringWithFormat: @"DELETE FROM %@", [self storeTableName]];
|
||||
error = [storeChannel evaluateExpressionX:query];
|
||||
if (error)
|
||||
[self errorWithFormat: @"%s: cannot delete content '%@': %@",
|
||||
[self errorWithFormat: @"%s: cannot delete content '%@': %@",
|
||||
__PRETTY_FUNCTION__, query, error];
|
||||
else if (!ofFlags.sameTableForQuick) {
|
||||
/* content row deleted, now delete the quick row */
|
||||
@@ -1317,7 +1318,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
query = [NSString stringWithFormat: @"DELETE FROM %@", [self quickTableName]];
|
||||
error = [quickChannel evaluateExpressionX: query];
|
||||
if (error)
|
||||
[self errorWithFormat: @"%s: cannot delete quick row '%@': %@",
|
||||
[self errorWithFormat: @"%s: cannot delete quick row '%@': %@",
|
||||
__PRETTY_FUNCTION__, query, error];
|
||||
}
|
||||
|
||||
@@ -1333,6 +1334,49 @@ andAttribute: (EOAttribute *)_attribute
|
||||
return error;
|
||||
}
|
||||
|
||||
- (NSException *) purgeDeletedRecordsBefore: (unsigned int) days
|
||||
{
|
||||
NSString *delSql, *table;
|
||||
EOAdaptorContext *adaptorCtx;
|
||||
EOAdaptorChannel *channel;
|
||||
NSCalendarDate *nowDate;
|
||||
unsigned int delta;
|
||||
|
||||
channel = [self acquireStoreChannel];
|
||||
|
||||
if ((channel = [self acquireStoreChannel]) == nil)
|
||||
return [NSException exceptionWithName: @"GCSChannelException"
|
||||
reason: @"could not open storage channel!"
|
||||
userInfo: nil];
|
||||
|
||||
adaptorCtx = [channel adaptorContext];
|
||||
[adaptorCtx beginTransaction];
|
||||
|
||||
table = [self storeTableName];
|
||||
nowDate = [NSCalendarDate date];
|
||||
delta = days * 24 * 60 * 60;
|
||||
if (delta > [nowDate timeIntervalSince1970])
|
||||
return [NSException exceptionWithName: @"GCSArgumentException"
|
||||
reason: @"number of days is too high!"
|
||||
userInfo: nil];
|
||||
delta = [nowDate timeIntervalSince1970] - delta;
|
||||
|
||||
if ([GCSFolderManager singleStoreMode])
|
||||
delSql = [NSString stringWithFormat: @"DELETE FROM %@"
|
||||
@" WHERE c_folder_id = %@ AND c_deleted = 1 AND c_lastmodified < %u",
|
||||
table, folderId, delta];
|
||||
else
|
||||
delSql = [NSString stringWithFormat: @"DELETE FROM %@"
|
||||
@" WHERE c_deleted = 1 AND c_lastmodified < %u",
|
||||
table, delta];
|
||||
[channel evaluateExpressionX: delSql];
|
||||
|
||||
[[channel adaptorContext] commitTransaction];
|
||||
[self releaseChannel: channel];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSException *) touchContentWithName: (NSString *) _name
|
||||
{
|
||||
NSString *touchSql, *table;
|
||||
@@ -1389,14 +1433,14 @@ andAttribute: (EOAttribute *)_attribute
|
||||
EOAdaptorChannel *channel;
|
||||
NSString *delsql;
|
||||
NSString *table;
|
||||
|
||||
|
||||
/* open channels */
|
||||
|
||||
|
||||
if ((channel = [self acquireStoreChannel]) == nil) {
|
||||
[self errorWithFormat:@"could not open channel!"];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
/* delete rows */
|
||||
[[channel adaptorContext] beginTransaction];
|
||||
table = [self storeTableName];
|
||||
@@ -1423,7 +1467,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
delsql = [@"DROP TABLE " stringByAppendingString: table];
|
||||
[channel evaluateExpressionX:delsql];
|
||||
}
|
||||
|
||||
|
||||
[[channel adaptorContext] commitTransaction];
|
||||
[self releaseChannel:channel];
|
||||
|
||||
@@ -1437,7 +1481,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
EOAdaptorChannel *quickChannel;
|
||||
EOAdaptorContext *adaptorCtx;
|
||||
NSException *error;
|
||||
|
||||
|
||||
quickChannel = [self acquireQuickChannel];
|
||||
adaptorCtx = [quickChannel adaptorContext];
|
||||
[adaptorCtx beginTransaction];
|
||||
@@ -1500,15 +1544,15 @@ andAttribute: (EOAttribute *)_attribute
|
||||
NSArray *attrs;
|
||||
NSMutableArray *results;
|
||||
NSDictionary *row;
|
||||
|
||||
|
||||
qualifier = [_fs qualifier];
|
||||
sortOrderings = [_fs sortOrderings];
|
||||
|
||||
|
||||
#if 0
|
||||
[self logWithFormat:@"FETCH: %@", _flds];
|
||||
[self logWithFormat:@" MATCH: %@", _q];
|
||||
#endif
|
||||
|
||||
|
||||
/* generate SQL */
|
||||
|
||||
sql = [NSMutableString stringWithCapacity:256];
|
||||
@@ -1536,34 +1580,34 @@ andAttribute: (EOAttribute *)_attribute
|
||||
[sql appendString:@" LIMIT "]; // count
|
||||
[sql appendString:@" OFFSET "]; // index from 0
|
||||
#endif
|
||||
|
||||
|
||||
/* open channel */
|
||||
|
||||
if ((channel = [self acquireAclChannel]) == nil) {
|
||||
[self errorWithFormat:@"could not open acl channel!"];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
/* run SQL */
|
||||
|
||||
if ((error = [channel evaluateExpressionX:sql]) != nil) {
|
||||
[self errorWithFormat:@"%s: cannot execute acl-fetch SQL '%@': %@",
|
||||
[self errorWithFormat:@"%s: cannot execute acl-fetch SQL '%@': %@",
|
||||
__PRETTY_FUNCTION__, sql, error];
|
||||
[self releaseChannel:channel];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
/* fetch results */
|
||||
|
||||
|
||||
results = [NSMutableArray arrayWithCapacity:64];
|
||||
attrs = [channel describeResults:NO /* do not beautify names */];
|
||||
while ((row = [channel fetchAttributes:attrs withZone:NULL]) != nil)
|
||||
[results addObject:row];
|
||||
|
||||
|
||||
/* release channels */
|
||||
|
||||
|
||||
[self releaseChannel: channel];
|
||||
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -1602,7 +1646,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
NSException *error;
|
||||
NSMutableString *sql;
|
||||
NSString *qSql;
|
||||
|
||||
|
||||
sql = [NSMutableString stringWithCapacity:256];
|
||||
[sql appendString:@"DELETE FROM "];
|
||||
[sql appendString:[self aclTableName]];
|
||||
@@ -1620,16 +1664,16 @@ andAttribute: (EOAttribute *)_attribute
|
||||
[self errorWithFormat:@"could not open acl channel!"];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* run SQL */
|
||||
[[channel adaptorContext] beginTransaction];
|
||||
if ((error = [channel evaluateExpressionX:sql]) != nil) {
|
||||
[self errorWithFormat:@"%s: cannot execute acl-fetch SQL '%@': %@",
|
||||
[self errorWithFormat:@"%s: cannot execute acl-fetch SQL '%@': %@",
|
||||
__PRETTY_FUNCTION__, sql, error];
|
||||
[self releaseChannel:channel];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
[[channel adaptorContext] commitTransaction];
|
||||
[self releaseChannel:channel];
|
||||
}
|
||||
@@ -1647,11 +1691,11 @@ andAttribute: (EOAttribute *)_attribute
|
||||
|
||||
if ([GCSFolderManager singleStoreMode])
|
||||
sqlString = [NSMutableString stringWithFormat:
|
||||
@"SELECT COUNT(*) AS CNT FROM %@ WHERE c_folder_id = %@",
|
||||
@"SELECT COUNT(*) AS cnt FROM %@ WHERE c_folder_id = %@",
|
||||
[self storeTableName], folderId];
|
||||
else
|
||||
sqlString = [NSMutableString stringWithFormat:
|
||||
@"SELECT COUNT(*) AS CNT FROM %@",
|
||||
@"SELECT COUNT(*) AS cnt FROM %@",
|
||||
[self storeTableName]];
|
||||
if (excludeDeleted)
|
||||
{
|
||||
@@ -1666,7 +1710,56 @@ andAttribute: (EOAttribute *)_attribute
|
||||
{
|
||||
error = [channel evaluateExpressionX: sqlString];
|
||||
if (error)
|
||||
[self errorWithFormat: @"%s: cannot execute SQL '%@': %@",
|
||||
[self errorWithFormat: @"%s: cannot execute SQL '%@': %@",
|
||||
__PRETTY_FUNCTION__, sqlString, error];
|
||||
else
|
||||
{
|
||||
attrs = [channel describeResults: NO];
|
||||
row = [channel fetchAttributes: attrs withZone: NULL];
|
||||
count = [[row objectForKey: @"cnt"] unsignedIntValue];
|
||||
[channel cancelFetch];
|
||||
}
|
||||
[self releaseChannel: channel];
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
- (unsigned int) recordsCountDeletedBefore: (unsigned int) days
|
||||
{
|
||||
EOAdaptorChannel *channel;
|
||||
NSArray *attrs;
|
||||
NSCalendarDate *nowDate;
|
||||
NSDictionary *row;
|
||||
NSException *error;
|
||||
NSMutableString *sqlString;
|
||||
unsigned int delta, count;
|
||||
|
||||
count = 0;
|
||||
nowDate = [NSCalendarDate date];
|
||||
delta = days * 24 * 60 * 60;
|
||||
if (delta < [nowDate timeIntervalSince1970])
|
||||
delta = [nowDate timeIntervalSince1970] - delta;
|
||||
else
|
||||
delta = 0;
|
||||
|
||||
if ([GCSFolderManager singleStoreMode])
|
||||
sqlString = [NSMutableString stringWithFormat:
|
||||
@"SELECT COUNT(*) AS cnt FROM %@"
|
||||
@" WHERE c_folder_id = %@ AND c_lastmodified < %u AND c_deleted = 1",
|
||||
[self storeTableName], folderId, delta];
|
||||
else
|
||||
sqlString = [NSMutableString stringWithFormat:
|
||||
@"SELECT COUNT(*) AS cnt FROM %@"
|
||||
@" WHERE c_lastmodified < %u AND c_deleted = 1",
|
||||
[self storeTableName], delta];
|
||||
|
||||
channel = [self acquireStoreChannel];
|
||||
if (channel)
|
||||
{
|
||||
error = [channel evaluateExpressionX: sqlString];
|
||||
if (error)
|
||||
[self errorWithFormat: @"%s: cannot execute SQL '%@': %@",
|
||||
__PRETTY_FUNCTION__, sqlString, error];
|
||||
else
|
||||
{
|
||||
@@ -1716,7 +1809,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
- (NSString *)description {
|
||||
NSMutableString *ms;
|
||||
id tmp;
|
||||
|
||||
|
||||
ms = [NSMutableString stringWithCapacity:256];
|
||||
[ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
|
||||
|
||||
@@ -1729,7 +1822,7 @@ andAttribute: (EOAttribute *)_attribute
|
||||
if ((tmp = [self folderTypeName])) [ms appendFormat:@" type=%@", tmp];
|
||||
if ((tmp = [self location]))
|
||||
[ms appendFormat:@" loc=%@", [tmp absoluteString]];
|
||||
|
||||
|
||||
[ms appendString:@">"];
|
||||
return ms;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
- (BOOL)folderExistsAtPath:(NSString *)_path;
|
||||
- (NSArray *)listSubFoldersAtPath:(NSString *)_path recursive:(BOOL)_flag;
|
||||
|
||||
- (NSDictionary *) recordAtPath: (NSString *) _path;
|
||||
- (GCSFolder *)folderAtPath:(NSString *)_path;
|
||||
|
||||
- (NSException *)createFolderOfType:(NSString *)_type withName:(NSString *)_name atPath:(NSString *)_path;
|
||||
|
||||
@@ -784,7 +784,7 @@ static BOOL _singleStoreMode = NO;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (GCSFolder *) folderAtPath: (NSString *) _path
|
||||
- (NSDictionary *) recordAtPath: (NSString *) _path
|
||||
{
|
||||
NSMutableString *sql;
|
||||
NSArray *fnames, *records;
|
||||
@@ -841,8 +841,13 @@ static BOOL _singleStoreMode = NO;
|
||||
[self debugWithFormat:@"found no record for path: '%@'", _path];
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [self folderForRecord:record];
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
- (GCSFolder *) folderAtPath: (NSString *) _path
|
||||
{
|
||||
return [self folderForRecord: [self recordAtPath: _path]];
|
||||
}
|
||||
|
||||
- (NSString *) baseTableNameWithUID: (NSString *) _uid
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* CardElement.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006-2014 Inverse inc.
|
||||
* Copyright (C) 2006-2017 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
|
||||
@@ -64,7 +64,7 @@
|
||||
- (NSMutableDictionary *) values;
|
||||
|
||||
/* ELEM:...;value1,value2,...;... */
|
||||
- (void) setValues: (NSMutableArray *) newValues
|
||||
- (void) setValues: (id) newValues
|
||||
atIndex: (NSUInteger) idx
|
||||
forKey: (NSString *) key;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* CardElement.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006-2014 Inverse inc.
|
||||
* Copyright (C) 2006-2017 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
|
||||
@@ -130,12 +130,17 @@
|
||||
return values;
|
||||
}
|
||||
|
||||
- (void) setValues: (NSMutableArray *) newValues
|
||||
- (void) setValues: (id) newValues
|
||||
atIndex: (NSUInteger) idx
|
||||
forKey: (NSString *) key
|
||||
{
|
||||
NSMutableArray *oldValues, *subValues;
|
||||
|
||||
if (newValues && [newValues isKindOfClass: [NSString class]])
|
||||
return [self setSingleValue: (NSString *)newValues
|
||||
atIndex: idx
|
||||
forKey: key];
|
||||
|
||||
oldValues = [self valuesForKey: key];
|
||||
if (!oldValues)
|
||||
{
|
||||
|
||||
@@ -51,10 +51,10 @@
|
||||
[aString appendString: @","];
|
||||
subValue = [self objectAtIndex: count];
|
||||
|
||||
/* We MUST quote attribute values that have a ":" in them
|
||||
/* We MUST quote attribute values that have a ":" or "," in them
|
||||
and that not already quoted */
|
||||
if (asAttributes && [subValue length] > 2
|
||||
&& [subValue rangeOfString: @":"].length
|
||||
&& ([subValue rangeOfString: @":"].length || [subValue rangeOfString: @","].length)
|
||||
&& [subValue characterAtIndex: 0] != '"'
|
||||
&& ![subValue hasSuffix: @"\""])
|
||||
subValue = [NSString stringWithFormat: @"\"%@\"", subValue];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Abidjan
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Accra
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Addis_Ababa
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Algiers
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Asmara
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Bamako
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Bangui
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Banjul
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Bissau
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Blantyre
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Brazzaville
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Bujumbura
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Cairo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Casablanca
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Ceuta
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Conakry
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Dakar
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Dar_es_Salaam
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Djibouti
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Douala
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/El_Aaiun
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Freetown
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Gaborone
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Harare
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Johannesburg
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Juba
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Kampala
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Khartoum
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Kigali
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Kinshasa
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Lagos
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Libreville
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Lome
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Luanda
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Lubumbashi
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Lusaka
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Malabo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Maputo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Maseru
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Mbabane
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Mogadishu
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Monrovia
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Nairobi
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Ndjamena
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Niamey
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Nouakchott
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Ouagadougou
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Porto-Novo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Sao_Tome
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Tripoli
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Tunis
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Windhoek
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Adak
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Anchorage
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Anguilla
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Antigua
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Araguaina
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Araguaina
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:BRT
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/Buenos_Aires
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/Buenos_Aires
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/Catamarca
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/Catamarca
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/Cordoba
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/Cordoba
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/Jujuy
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/Jujuy
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/La_Rioja
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/La_Rioja
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/Mendoza
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/Mendoza
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/Rio_Gallegos
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/Rio_Gallegos
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/Salta
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/Salta
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/San_Juan
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/San_Juan
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/San_Luis
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/San_Luis
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/Tucuman
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/Tucuman
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Argentina/Ushuaia
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Argentina/Ushuaia
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:ART
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Aruba
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Asuncion
|
||||
@@ -7,14 +7,14 @@ X-LIC-LOCATION:America/Asuncion
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:-0400
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:PYST
|
||||
TZNAME:-03
|
||||
DTSTART:19701004T000000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0400
|
||||
TZNAME:PYT
|
||||
TZNAME:-04
|
||||
DTSTART:19700322T000000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=4SU
|
||||
END:STANDARD
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Atikokan
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Bahia
|
||||
@@ -7,7 +7,7 @@ X-LIC-LOCATION:America/Bahia
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:BRT
|
||||
TZNAME:-03
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2016h//EN
|
||||
PRODID:-//Inverse inc.//NONSGML IANA 2017b//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Bahia_Banderas
|
||||
|
||||
Loaded 100 of 900 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user