Browse code

FEATBL-828 Feat: im-export ICS with attachments

Thomas Fricker authored on 24/07/2019 15:55:24
Showing 27 changed files
... ...
@@ -33,6 +33,7 @@ import java.time.ZonedDateTime;
33 33
 import java.util.ArrayList;
34 34
 import java.util.HashSet;
35 35
 import java.util.List;
36
+import java.util.Optional;
36 37
 import java.util.Set;
37 38
 import java.util.TimeZone;
38 39
 
... ...
@@ -65,7 +66,7 @@ public class VEventServiceHelperTest {
65 66
 				.getResourceAsStream("event_multiplevcalendar.ics");
66 67
 		String ics = FileUtils.streamString(in, true);
67 68
 		in.close();
68
-		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics);
69
+		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
69 70
 		assertEquals(2, events.size());
70 71
 
71 72
 	}
... ...
@@ -75,7 +76,7 @@ public class VEventServiceHelperTest {
75 76
 		InputStream in = VEventServiceHelperTest.class.getClassLoader().getResourceAsStream("invite.ics");
76 77
 		String ics = IOUtils.toString(in);
77 78
 		in.close();
78
-		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics);
79
+		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
79 80
 
80 81
 		assertEquals(1, events.size());
81 82
 
... ...
@@ -92,7 +93,7 @@ public class VEventServiceHelperTest {
92 93
 		InputStream in = VEventServiceHelperTest.class.getClassLoader().getResourceAsStream("unknowntz.ics");
93 94
 		String ics = IOUtils.toString(in);
94 95
 		in.close();
95
-		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics);
96
+		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
96 97
 
97 98
 		assertEquals(2, events.size());
98 99
 
... ...
@@ -113,7 +114,7 @@ public class VEventServiceHelperTest {
113 114
 		InputStream in = VEventServiceHelperTest.class.getClassLoader().getResourceAsStream("event2.ics");
114 115
 		String ics = IOUtils.toString(in);
115 116
 		in.close();
116
-		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics);
117
+		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
117 118
 
118 119
 		assertEquals(2, events.size());
119 120
 
... ...
@@ -140,7 +141,7 @@ public class VEventServiceHelperTest {
140 141
 		String ics = IOUtils.toString(in);
141 142
 		in.close();
142 143
 
143
-		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics);
144
+		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
144 145
 
145 146
 		assertEquals(1, events.size());
146 147
 
... ...
@@ -348,7 +349,7 @@ public class VEventServiceHelperTest {
348 349
 		InputStream in = VEventServiceHelperTest.class.getClassLoader().getResourceAsStream("not_absolute_uri.ics");
349 350
 		String ics = IOUtils.toString(in);
350 351
 		in.close();
351
-		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics);
352
+		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
352 353
 
353 354
 		assertEquals(1, events.size());
354 355
 		ItemValue<VEventSeries> event = events.get(0);
... ...
@@ -434,7 +435,7 @@ public class VEventServiceHelperTest {
434 435
 		try (InputStream in = VEventServiceHelperTest.class.getClassLoader()
435 436
 				.getResourceAsStream("event_invalid_geo.ics")) {
436 437
 			String ics = IOUtils.toString(in);
437
-			VEventServiceHelper.convertToVEventList(ics);
438
+			VEventServiceHelper.convertToVEventList(ics, Optional.empty());
438 439
 		} catch (Exception e) {
439 440
 			fail("should not fail " + e.getMessage());
440 441
 		}
... ...
@@ -453,7 +454,7 @@ public class VEventServiceHelperTest {
453 454
 		String ics = IOUtils.toString(in);
454 455
 		in.close();
455 456
 
456
-		VEventServiceHelper.convertToVEventList(ics);
457
+		VEventServiceHelper.convertToVEventList(ics, Optional.empty());
457 458
 
458 459
 		assertEquals(rawOffset, ICal4jHelper.getTimeZoneRegistry().getTimeZone("Europe/Paris").getRawOffset());
459 460
 	}
... ...
@@ -17,7 +17,8 @@ Require-Bundle: org.freemarker.freemarker;bundle-version="2.3.20",
17 17
  net.bluemind.reminder.mail,
18 18
  net.bluemind.common.freemarker;bundle-version="4.1.0",
19 19
  org.apache.commons.lang,
20
- net.bluemind.icalendar.parser
20
+ net.bluemind.icalendar.parser,
21
+ net.bluemind.attachment.api
21 22
 Export-Package: net.bluemind.calendar.helper.ical4j,
22 23
  net.bluemind.calendar.helper.mail
23 24
 Import-Package: net.bluemind.icalendar.parser
... ...
@@ -31,6 +31,7 @@ import java.util.HashMap;
31 31
 import java.util.HashSet;
32 32
 import java.util.Iterator;
33 33
 import java.util.List;
34
+import java.util.Optional;
34 35
 import java.util.Set;
35 36
 import java.util.stream.Collectors;
36 37
 
... ...
@@ -43,6 +44,7 @@ import net.bluemind.calendar.api.VEventSeries;
43 44
 import net.bluemind.core.api.date.BmDateTimeWrapper;
44 45
 import net.bluemind.core.api.fault.ServerFault;
45 46
 import net.bluemind.core.container.model.ItemValue;
47
+import net.bluemind.icalendar.parser.CalendarOwner;
46 48
 import net.bluemind.icalendar.parser.ICal4jEventHelper;
47 49
 import net.bluemind.icalendar.parser.ICal4jHelper;
48 50
 import net.bluemind.lib.ical4j.data.CalendarBuilder;
... ...
@@ -133,7 +135,6 @@ public class VEventServiceHelper extends ICal4jEventHelper<VEvent> {
133 135
 				if (method != null) {
134 136
 					icalEvent.getAlarms().clear();
135 137
 				}
136
-
137 138
 				// BM-10430
138 139
 				if (method != Method.REPLY) {
139 140
 					PropertyList listAttendees = icalEvent.getProperties(Property.ATTENDEE);
... ...
@@ -182,15 +183,17 @@ public class VEventServiceHelper extends ICal4jEventHelper<VEvent> {
182 183
 
183 184
 	/**
184 185
 	 * @param ics
186
+	 * @param owner
185 187
 	 * @return
186 188
 	 * @throws ServerFault
187 189
 	 */
188
-	public static List<ItemValue<VEventSeries>> convertToVEventList(String ics) throws ServerFault {
190
+	public static List<ItemValue<VEventSeries>> convertToVEventList(String ics, Optional<CalendarOwner> owner)
191
+			throws ServerFault {
189 192
 
190 193
 		List<String> icsCalendarList = splitIcs(ics);
191 194
 		List<ItemValue<VEventSeries>> ret = new ArrayList<>();
192 195
 		for (String cal : icsCalendarList) {
193
-			ret.addAll(parseCalendar(cal));
196
+			ret.addAll(parseCalendar(cal, owner));
194 197
 
195 198
 		}
196 199
 		return ret;
... ...
@@ -215,7 +218,8 @@ public class VEventServiceHelper extends ICal4jEventHelper<VEvent> {
215 218
 		return cals;
216 219
 	}
217 220
 
218
-	private static <T extends VEvent> List<ItemValue<VEventSeries>> parseCalendar(String ics) throws ServerFault {
221
+	private static <T extends VEvent> List<ItemValue<VEventSeries>> parseCalendar(String ics,
222
+			Optional<CalendarOwner> owner) throws ServerFault {
219 223
 		CalendarParser parser = CalendarParserFactory.getInstance().createParser();
220 224
 		PropertyFactoryRegistry propertyFactory = new PropertyFactoryRegistry();
221 225
 		ParameterFactoryRegistry parameterFactory = new ParameterFactoryRegistry();
... ...
@@ -264,7 +268,8 @@ public class VEventServiceHelper extends ICal4jEventHelper<VEvent> {
264 268
 					.next();
265 269
 
266 270
 			@SuppressWarnings("unchecked")
267
-			ItemValue<T> vevent = (ItemValue<T>) new ICal4jEventHelper<>().parseIcs(new VEvent(), ical4j, globalTZ);
271
+			ItemValue<T> vevent = (ItemValue<T>) new ICal4jEventHelper<>().parseIcs(new VEvent(), ical4j, globalTZ,
272
+					owner);
268 273
 			if (ical4j.getCreated() != null) {
269 274
 				vevent.created = ical4j.getCreated().getDate();
270 275
 			}
... ...
@@ -37,6 +37,7 @@ import java.util.Arrays;
37 37
 import java.util.Collections;
38 38
 import java.util.HashSet;
39 39
 import java.util.List;
40
+import java.util.Optional;
40 41
 import java.util.Set;
41 42
 import java.util.UUID;
42 43
 
... ...
@@ -687,7 +688,7 @@ public class IcsHookTests {
687 688
 		String ics = getIcsPartAsText(m);
688 689
 		String method = getIcsPartMethod(m);
689 690
 		assertEquals("REQUEST", method);
690
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
691
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
691 692
 
692 693
 		assertEquals(1, seriesList.size());
693 694
 
... ...
@@ -721,7 +722,7 @@ public class IcsHookTests {
721 722
 		String ics = getIcsPartAsText(m);
722 723
 		String method = getIcsPartMethod(m);
723 724
 		assertEquals("REQUEST", method);
724
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
725
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
725 726
 
726 727
 		assertEquals(1, seriesList.size());
727 728
 
... ...
@@ -751,7 +752,7 @@ public class IcsHookTests {
751 752
 		String ics = getIcsPartAsText(m);
752 753
 		String method = getIcsPartMethod(m);
753 754
 		assertEquals("REQUEST", method);
754
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
755
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
755 756
 
756 757
 		assertEquals(1, seriesList.size());
757 758
 
... ...
@@ -781,7 +782,7 @@ public class IcsHookTests {
781 782
 		String ics = getIcsPartAsText(m);
782 783
 		String method = getIcsPartMethod(m);
783 784
 		assertEquals("REQUEST", method);
784
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
785
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
785 786
 
786 787
 		assertEquals(1, seriesList.size());
787 788
 
... ...
@@ -814,7 +815,7 @@ public class IcsHookTests {
814 815
 		String ics = getIcsPartAsText(m);
815 816
 		String method = getIcsPartMethod(m);
816 817
 		assertEquals("CANCEL", method);
817
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
818
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
818 819
 
819 820
 		assertEquals(1, seriesList.size());
820 821
 
... ...
@@ -847,7 +848,7 @@ public class IcsHookTests {
847 848
 		String ics = getIcsPartAsText(m);
848 849
 		String method = getIcsPartMethod(m);
849 850
 		assertEquals("CANCEL", method);
850
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
851
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
851 852
 
852 853
 		assertEquals(1, seriesList.size());
853 854
 
... ...
@@ -881,7 +882,7 @@ public class IcsHookTests {
881 882
 		String ics = getIcsPartAsText(m);
882 883
 		String method = getIcsPartMethod(m);
883 884
 		assertEquals("REQUEST", method);
884
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
885
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
885 886
 
886 887
 		assertEquals(1, seriesList.size());
887 888
 
... ...
@@ -918,7 +919,7 @@ public class IcsHookTests {
918 919
 		String ics = getIcsPartAsText(m);
919 920
 		String method = getIcsPartMethod(m);
920 921
 		assertEquals("REQUEST", method);
921
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
922
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
922 923
 
923 924
 		assertEquals(1, seriesList.size());
924 925
 
... ...
@@ -963,7 +964,7 @@ public class IcsHookTests {
963 964
 		String ics = getIcsPartAsText(m);
964 965
 		String method = getIcsPartMethod(m);
965 966
 		assertEquals("REQUEST", method);
966
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
967
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
967 968
 
968 969
 		assertEquals(1, seriesList.size());
969 970
 
... ...
@@ -1000,7 +1001,7 @@ public class IcsHookTests {
1000 1001
 		String ics = getIcsPartAsText(m);
1001 1002
 		String method = getIcsPartMethod(m);
1002 1003
 		assertEquals("CANCEL", method);
1003
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1004
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1004 1005
 
1005 1006
 		assertEquals(1, seriesList.size());
1006 1007
 
... ...
@@ -1037,7 +1038,7 @@ public class IcsHookTests {
1037 1038
 		String ics = getIcsPartAsText(m);
1038 1039
 		String method = getIcsPartMethod(m);
1039 1040
 		assertEquals("CANCEL", method);
1040
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1041
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1041 1042
 
1042 1043
 		assertEquals(1, seriesList.size());
1043 1044
 
... ...
@@ -1074,7 +1075,7 @@ public class IcsHookTests {
1074 1075
 		String ics = getIcsPartAsText(m);
1075 1076
 		String method = getIcsPartMethod(m);
1076 1077
 		assertEquals("CANCEL", method);
1077
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1078
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1078 1079
 
1079 1080
 		assertEquals(1, seriesList.size());
1080 1081
 
... ...
@@ -1111,7 +1112,7 @@ public class IcsHookTests {
1111 1112
 
1112 1113
 		String method = getIcsPartMethod(m);
1113 1114
 		assertEquals("REQUEST", method);
1114
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1115
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1115 1116
 
1116 1117
 		assertEquals(1, seriesList.size());
1117 1118
 
... ...
@@ -1176,7 +1177,7 @@ public class IcsHookTests {
1176 1177
 		String method = getIcsPartMethod(m);
1177 1178
 
1178 1179
 		assertEquals("CANCEL", method);
1179
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1180
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1180 1181
 
1181 1182
 		assertEquals(1, seriesList.size());
1182 1183
 
... ...
@@ -1212,7 +1213,7 @@ public class IcsHookTests {
1212 1213
 		String ics = getIcsPartAsText(m);
1213 1214
 		String method = getIcsPartMethod(m);
1214 1215
 		assertEquals("REQUEST", method); // or ADD ?
1215
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1216
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1216 1217
 
1217 1218
 		assertEquals(1, seriesList.size());
1218 1219
 
... ...
@@ -1242,7 +1243,7 @@ public class IcsHookTests {
1242 1243
 		String ics = getIcsPartAsText(m);
1243 1244
 		String method = getIcsPartMethod(m);
1244 1245
 		assertEquals("CANCEL", method);
1245
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1246
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1246 1247
 
1247 1248
 		assertEquals(1, seriesList.size());
1248 1249
 
... ...
@@ -1287,7 +1288,7 @@ public class IcsHookTests {
1287 1288
 		String ics = getIcsPartAsText(m);
1288 1289
 		String method = getIcsPartMethod(m);
1289 1290
 		assertEquals("CANCEL", method);
1290
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1291
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1291 1292
 
1292 1293
 		assertEquals(1, seriesList.size());
1293 1294
 
... ...
@@ -1318,7 +1319,7 @@ public class IcsHookTests {
1318 1319
 		String ics = getIcsPartAsText(m);
1319 1320
 		String method = getIcsPartMethod(m);
1320 1321
 		assertEquals("CANCEL", method);
1321
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1322
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1322 1323
 
1323 1324
 		assertEquals(1, seriesList.size());
1324 1325
 
... ...
@@ -1349,7 +1350,7 @@ public class IcsHookTests {
1349 1350
 		String ics = getIcsPartAsText(m);
1350 1351
 		String method = getIcsPartMethod(m);
1351 1352
 		assertEquals("CANCEL", method);
1352
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1353
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1353 1354
 
1354 1355
 		assertEquals(1, seriesList.size());
1355 1356
 
... ...
@@ -1385,7 +1386,7 @@ public class IcsHookTests {
1385 1386
 		String ics = getIcsPartAsText(m);
1386 1387
 		String method = getIcsPartMethod(m);
1387 1388
 		assertEquals("REPLY", method);
1388
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1389
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1389 1390
 
1390 1391
 		assertEquals(1, seriesList.size());
1391 1392
 
... ...
@@ -1426,7 +1427,7 @@ public class IcsHookTests {
1426 1427
 		String ics = getIcsPartAsText(m);
1427 1428
 		String method = getIcsPartMethod(m);
1428 1429
 		assertEquals("REPLY", method);
1429
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1430
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1430 1431
 
1431 1432
 		assertEquals(1, seriesList.size());
1432 1433
 
... ...
@@ -1463,7 +1464,7 @@ public class IcsHookTests {
1463 1464
 		String ics = getIcsPartAsText(m);
1464 1465
 		String method = getIcsPartMethod(m);
1465 1466
 		assertEquals("REPLY", method);
1466
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1467
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1467 1468
 
1468 1469
 		assertEquals(1, seriesList.size());
1469 1470
 
... ...
@@ -1501,7 +1502,7 @@ public class IcsHookTests {
1501 1502
 		String ics = getIcsPartAsText(m);
1502 1503
 		String method = getIcsPartMethod(m);
1503 1504
 		assertEquals("REPLY", method);
1504
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1505
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1505 1506
 
1506 1507
 		assertEquals(1, seriesList.size());
1507 1508
 
... ...
@@ -1536,7 +1537,7 @@ public class IcsHookTests {
1536 1537
 		String ics = getIcsPartAsText(m);
1537 1538
 		String method = getIcsPartMethod(m);
1538 1539
 		assertEquals("REPLY", method);
1539
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1540
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1540 1541
 
1541 1542
 		assertEquals(1, seriesList.size());
1542 1543
 
... ...
@@ -1574,7 +1575,7 @@ public class IcsHookTests {
1574 1575
 		String ics = getIcsPartAsText(m);
1575 1576
 		String method = getIcsPartMethod(m);
1576 1577
 		assertEquals("REPLY", method);
1577
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1578
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1578 1579
 
1579 1580
 		assertEquals(1, seriesList.size());
1580 1581
 
... ...
@@ -1593,7 +1594,7 @@ public class IcsHookTests {
1593 1594
 		ics = getIcsPartAsText(m);
1594 1595
 		method = getIcsPartMethod(m);
1595 1596
 		assertEquals("REPLY", method);
1596
-		seriesList = VEventServiceHelper.convertToVEventList(ics);
1597
+		seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1597 1598
 
1598 1599
 		assertEquals(1, seriesList.size());
1599 1600
 
... ...
@@ -1624,7 +1625,7 @@ public class IcsHookTests {
1624 1625
 		String ics = getIcsPartAsText(m);
1625 1626
 		String method = getIcsPartMethod(m);
1626 1627
 		assertEquals("REPLY", method);
1627
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1628
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1628 1629
 
1629 1630
 		assertEquals(1, seriesList.size());
1630 1631
 
... ...
@@ -1659,7 +1660,7 @@ public class IcsHookTests {
1659 1660
 		String ics = getIcsPartAsText(m);
1660 1661
 		String method = getIcsPartMethod(m);
1661 1662
 		assertEquals("REPLY", method);
1662
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1663
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1663 1664
 
1664 1665
 		assertEquals(1, seriesList.size());
1665 1666
 
... ...
@@ -1707,7 +1708,7 @@ public class IcsHookTests {
1707 1708
 		String ics = getIcsPartAsText(m);
1708 1709
 		String method = getIcsPartMethod(m);
1709 1710
 		assertEquals("REPLY", method);
1710
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1711
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1711 1712
 
1712 1713
 		assertEquals(1, seriesList.size());
1713 1714
 
... ...
@@ -1789,7 +1790,7 @@ public class IcsHookTests {
1789 1790
 
1790 1791
 		String method = getIcsPartMethod(m);
1791 1792
 		assertEquals("REQUEST", method);
1792
-		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics);
1793
+		List<ItemValue<VEventSeries>> seriesList = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1793 1794
 
1794 1795
 		assertEquals(1, seriesList.size());
1795 1796
 
... ...
@@ -34,5 +34,8 @@ Require-Bundle: org.junit,
34 34
  net.bluemind.externaluser.service;bundle-version="4.1.0",
35 35
  net.bluemind.externaluser.api,
36 36
  net.bluemind.backend.cyrus,
37
- net.bluemind.resource.service;bundle-version="4.1.0"
37
+ net.bluemind.resource.service;bundle-version="4.1.0",
38
+ net.bluemind.filehosting.filesystem.service;bundle-version="4.1.0",
39
+ net.bluemind.attachment.service;bundle-version="4.1.0",
40
+ net.bluemind.dockerclient
38 41
 
39 42
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+BEGIN:VCALENDAR
2
+PRODID:-//BlueMind//BlueMind Calendar//FR
3
+VERSION:2.0
4
+CALSCALE:GREGORIAN
5
+BEGIN:VEVENT
6
+DTSTAMP:20140627T074110Z
7
+VERSION:2.0
8
+UID:95c659b1-eaf8-4145-a314-9cb4566636b8
9
+DTSTART;TZID=Pacific/Noumea:19830213T020000
10
+SUMMARY:TestAttachmentImport
11
+ATTACH;X-FILE-NAME=test.gif:http://somewhere/1
12
+ATTACH;X-FILE-NAME=test.png:http://somewhere/2
13
+END:VEVENT
14
+END:VCALENDAR
0 15
\ No newline at end of file
1 16
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+BEGIN:VCALENDAR
2
+PRODID:-//BlueMind//BlueMind Calendar//FR
3
+VERSION:2.0
4
+CALSCALE:GREGORIAN
5
+BEGIN:VEVENT
6
+DTSTAMP:20140627T074110Z
7
+VERSION:2.0
8
+UID:95c659b1-eaf8-4145-a314-9cb4566636b8
9
+DTSTART;TZID=Pacific/Noumea:19830213T020000
10
+SUMMARY:TestAttachmentImport
11
+ATTACH;X-FILE-NAME=test.gif:http://somewhere/1
12
+ATTACH;FMTTYPE=text/plain;ENCODING=BASE64;VALUE=BINARY:Y291Y291LCB0dSB2ZXV4Li4u
13
+END:VEVENT
14
+END:VCALENDAR
0 15
\ No newline at end of file
... ...
@@ -9,5 +9,7 @@ UID:95c659b1-eaf8-4145-a314-9cb4566636b8
9 9
 DTSTART;TZID=Pacific/Noumea:19830213T020000
10 10
 SUMMARY:TestSimpleImport
11 11
 RECURRENCE-ID;TZID=Pacific/Noumea:19830213T000000
12
+ATTACH;X-FILE-NAME=test.gif:http://somewhere/1
13
+ATTACH;X-FILE-NAME=test.png:http://somewhere/2
12 14
 END:VEVENT
13 15
 END:VCALENDAR
14 16
\ No newline at end of file
... ...
@@ -6,4 +6,6 @@
6 6
  },
7 7
  {
8 8
     "name":"bluemind/imap-role"
9
+},{
10
+ 	"name":"bluemind/node-tests"
9 11
 }]
... ...
@@ -48,6 +48,7 @@ import net.bluemind.addressbook.api.VCard.Kind;
48 48
 import net.bluemind.addressbook.domainbook.DomainAddressBook;
49 49
 import net.bluemind.addressbook.persistance.VCardIndexStore;
50 50
 import net.bluemind.addressbook.persistance.VCardStore;
51
+import net.bluemind.attachment.api.AttachedFile;
51 52
 import net.bluemind.calendar.api.ICalendar;
52 53
 import net.bluemind.calendar.api.ICalendarUids;
53 54
 import net.bluemind.calendar.api.IFreebusyUids;
... ...
@@ -80,6 +81,7 @@ import net.bluemind.core.tests.BmTestContext;
80 81
 import net.bluemind.core.utils.UIDGenerator;
81 82
 import net.bluemind.directory.api.DirEntry;
82 83
 import net.bluemind.directory.service.DirEntryHandlers;
84
+import net.bluemind.dockerclient.DockerEnv;
83 85
 import net.bluemind.domain.api.Domain;
84 86
 import net.bluemind.group.api.Group;
85 87
 import net.bluemind.group.persistance.GroupStore;
... ...
@@ -88,6 +90,7 @@ import net.bluemind.mailbox.api.Mailbox;
88 90
 import net.bluemind.mailbox.api.Mailbox.Routing;
89 91
 import net.bluemind.mailbox.api.Mailbox.Type;
90 92
 import net.bluemind.mailbox.service.internal.MailboxStoreService;
93
+import net.bluemind.pool.impl.docker.DockerContainer;
91 94
 import net.bluemind.server.api.Server;
92 95
 import net.bluemind.tag.api.ITagUids;
93 96
 import net.bluemind.tag.api.Tag;
... ...
@@ -179,7 +182,11 @@ public abstract class AbstractCalendarTests {
179 182
 		esServer.ip = ElasticsearchTestHelper.getInstance().getHost();
180 183
 		esServer.tags = Lists.newArrayList("bm/es");
181 184
 
182
-		PopulateHelper.initGlobalVirt(esServer);
185
+		Server nodeServer = new Server();
186
+		nodeServer.ip = DockerEnv.getIp(DockerContainer.NODE.getName());
187
+		nodeServer.tags = Lists.newArrayList("filehosting/data");
188
+
189
+		PopulateHelper.initGlobalVirt(esServer, nodeServer);
183 190
 
184 191
 		domainUid = "bm.lan";
185 192
 		datalocation = PopulateHelper.FAKE_CYRUS_IP;
... ...
@@ -412,6 +419,16 @@ public abstract class AbstractCalendarTests {
412 419
 		event.status = VEvent.Status.Confirmed;
413 420
 		event.priority = 3;
414 421
 
422
+		event.attachments = new ArrayList<>();
423
+		AttachedFile attachment1 = new AttachedFile();
424
+		attachment1.publicUrl = "http://somewhere/1";
425
+		attachment1.name = "test.gif";
426
+		event.attachments.add(attachment1);
427
+		AttachedFile attachment2 = new AttachedFile();
428
+		attachment2.publicUrl = "http://somewhere/2";
429
+		attachment2.name = "test.png";
430
+		event.attachments.add(attachment2);
431
+
415 432
 		event.organizer = new VEvent.Organizer(testUser.value.login + "@bm.lan");
416 433
 
417 434
 		List<VEvent.Attendee> attendees = new ArrayList<>(1);
... ...
@@ -38,6 +38,7 @@ import java.util.Set;
38 38
 import org.junit.Test;
39 39
 import org.slf4j.LoggerFactory;
40 40
 
41
+import net.bluemind.attachment.api.AttachedFile;
41 42
 import net.bluemind.calendar.api.IVEvent;
42 43
 import net.bluemind.calendar.api.VEvent;
43 44
 import net.bluemind.calendar.api.VEvent.Transparency;
... ...
@@ -229,6 +230,9 @@ public class VEventServiceTests extends AbstractCalendarTests {
229 230
 		assertTrue(export.contains("X-MICROSOFT-CDO-BUSYSTATUS:BUSY"));
230 231
 		assertTrue(export.contains("X-MOZ-LASTACK:"));
231 232
 
233
+		assertTrue(export.contains("ATTACH;X-FILE-NAME=test.gif:http://somewhere/1"));
234
+		assertTrue(export.contains("ATTACH;X-FILE-NAME=test.png:http://somewhere/2"));
235
+
232 236
 	}
233 237
 
234 238
 	@Test
... ...
@@ -468,6 +472,70 @@ public class VEventServiceTests extends AbstractCalendarTests {
468 472
 	}
469 473
 
470 474
 	@Test
475
+	public void testAttachmentImport() throws ServerFault, IOException {
476
+		Stream ics = getIcsFromFile("testAttachmentImport.ics");
477
+
478
+		TaskRef taskRef = getVEventService(userSecurityContext, userCalendarContainer).importIcs(ics);
479
+		ImportStats stats = waitImportEnd(taskRef);
480
+		assertNotNull(stats);
481
+		assertEquals(1, stats.importedCount());
482
+
483
+		ItemValue<VEventSeries> item = getCalendarService(userSecurityContext, userCalendarContainer)
484
+				.getComplete("95c659b1-eaf8-4145-a314-9cb4566636b8");
485
+
486
+		VEvent vevent = item.value.main;
487
+		assertNotNull(vevent);
488
+
489
+		assertEquals("TestAttachmentImport", vevent.summary);
490
+		assertEquals(2, vevent.attachments.size());
491
+
492
+		List<AttachedFile> attachments = vevent.attachments;
493
+		int checked = 0;
494
+		for (AttachedFile attachedFile : attachments) {
495
+			if (attachedFile.name.equals("test.gif")) {
496
+				assertEquals("http://somewhere/1", attachedFile.publicUrl);
497
+				checked++;
498
+			} else if (attachedFile.name.equals("test.png")) {
499
+				assertEquals("http://somewhere/2", attachedFile.publicUrl);
500
+				checked++;
501
+			}
502
+		}
503
+		assertEquals(2, checked);
504
+	}
505
+
506
+	@Test
507
+	public void testBinaryAttachmentImport() throws ServerFault, IOException {
508
+		Stream ics = getIcsFromFile("testBinaryAttachmentImport.ics");
509
+
510
+		TaskRef taskRef = getVEventService(userSecurityContext, userCalendarContainer).importIcs(ics);
511
+		ImportStats stats = waitImportEnd(taskRef);
512
+		assertNotNull(stats);
513
+		assertEquals(1, stats.importedCount());
514
+
515
+		ItemValue<VEventSeries> item = getCalendarService(userSecurityContext, userCalendarContainer)
516
+				.getComplete("95c659b1-eaf8-4145-a314-9cb4566636b8");
517
+
518
+		VEvent vevent = item.value.main;
519
+		assertNotNull(vevent);
520
+
521
+		assertEquals("TestAttachmentImport", vevent.summary);
522
+		assertEquals(2, vevent.attachments.size());
523
+
524
+		List<AttachedFile> attachments = vevent.attachments;
525
+		int checked = 0;
526
+		for (AttachedFile attachedFile : attachments) {
527
+			if (attachedFile.name.equals("test.gif")) {
528
+				assertEquals("http://somewhere/1", attachedFile.publicUrl);
529
+				checked++;
530
+			} else if (attachedFile.name.equals("attachment_1.txt")) {
531
+				assertTrue(attachedFile.publicUrl.startsWith("https://"));
532
+				checked++;
533
+			}
534
+		}
535
+		assertEquals(2, checked);
536
+	}
537
+
538
+	@Test
471 539
 	public void testImport() throws ServerFault, IOException {
472 540
 		Stream ics = getIcsFromFile("testImport.ics");
473 541
 
... ...
@@ -50,7 +50,8 @@ Require-Bundle: net.bluemind.calendar.api;bundle-version="1.0.0",
50 50
  net.bluemind.server.api,
51 51
  net.bluemind.resource.api,
52 52
  net.bluemind.resource.helper,
53
- net.bluemind.attachment.api
53
+ net.bluemind.attachment.api,
54
+ net.bluemind.icalendar.parser
54 55
 Export-Package: net.bluemind.calendar.service,
55 56
  net.bluemind.calendar.service.internal
56 57
 Bundle-Activator: net.bluemind.calendar.service.CalendarActivator
... ...
@@ -20,6 +20,7 @@ package net.bluemind.calendar.service.internal;
20 20
 
21 21
 import java.util.ArrayList;
22 22
 import java.util.List;
23
+import java.util.Optional;
23 24
 import java.util.UUID;
24 25
 
25 26
 import org.slf4j.Logger;
... ...
@@ -38,24 +39,27 @@ import net.bluemind.core.container.model.ItemValue;
38 39
 import net.bluemind.core.task.service.IServerTask;
39 40
 import net.bluemind.core.task.service.IServerTaskMonitor;
40 41
 import net.bluemind.core.utils.JsonUtils;
42
+import net.bluemind.icalendar.parser.CalendarOwner;
41 43
 
42 44
 public class ICSImportTask implements IServerTask {
43 45
 
44 46
 	private static final Logger logger = LoggerFactory.getLogger(ICSImportTask.class);
45 47
 
46
-	private String ics;
47
-	private ICalendar calendarService;
48
+	private final String ics;
49
+	private final ICalendar calendarService;
50
+	private final Optional<CalendarOwner> owner;
48 51
 
49
-	public ICSImportTask(ICalendar calendar, String ics) {
52
+	public ICSImportTask(ICalendar calendar, String ics, Optional<CalendarOwner> owner) {
50 53
 		this.calendarService = calendar;
51 54
 		this.ics = ics;
55
+		this.owner = owner;
52 56
 	}
53 57
 
54 58
 	@Override
55 59
 	public void run(IServerTaskMonitor monitor) throws Exception {
56 60
 		monitor.begin(3, "Begin import");
57 61
 
58
-		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics);
62
+		List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(ics, owner);
59 63
 		monitor.progress(1, "ICS parsed ( " + events.size() + " events )");
60 64
 		ImportStats ret = importEvents(events, monitor.subWork("", 2));
61 65
 		// FIXME ret should be returned as ImportStats
... ...
@@ -19,6 +19,7 @@
19 19
 package net.bluemind.calendar.service.internal;
20 20
 
21 21
 import java.util.List;
22
+import java.util.Optional;
22 23
 import java.util.concurrent.atomic.AtomicInteger;
23 24
 
24 25
 import org.slf4j.Logger;
... ...
@@ -42,6 +43,7 @@ import net.bluemind.core.rest.base.GenericStream;
42 43
 import net.bluemind.core.rest.vertx.VertxStream;
43 44
 import net.bluemind.core.task.api.TaskRef;
44 45
 import net.bluemind.core.task.service.ITasksManager;
46
+import net.bluemind.icalendar.parser.CalendarOwner;
45 47
 
46 48
 public class VEventService implements IVEvent {
47 49
 
... ...
@@ -53,8 +55,11 @@ public class VEventService implements IVEvent {
53 55
 
54 56
 	private RBACManager rbacManager;
55 57
 
58
+	private Container container;
59
+
56 60
 	public VEventService(BmContext context, Container container) throws ServerFault {
57 61
 		this.context = context;
62
+		this.container = container;
58 63
 		this.calendarService = context.provider().instance(ICalendar.class, container.uid);
59 64
 		rbacManager = RBACManager.forContext(context).forContainer(container);
60 65
 	}
... ...
@@ -77,7 +82,8 @@ public class VEventService implements IVEvent {
77 82
 	public TaskRef importIcs(Stream stream) throws ServerFault {
78 83
 		rbacManager.check(Verb.Write.name());
79 84
 		String ics = GenericStream.streamToString(stream);
80
-		return context.provider().instance(ITasksManager.class).run(new ICSImportTask(calendarService, ics));
85
+		return context.provider().instance(ITasksManager.class).run(new ICSImportTask(calendarService, ics,
86
+				Optional.of(new CalendarOwner(container.domainUid, container.owner))));
81 87
 	}
82 88
 
83 89
 	@Override
... ...
@@ -16,4 +16,5 @@ Require-Bundle: net.bluemind.core.container.sync,
16 16
  net.bluemind.calendar.helper,
17 17
  net.bluemind.slf4j;bundle-version="4.1.0",
18 18
  net.bluemind.core.task.service,
19
- bcprov
19
+ bcprov,
20
+ net.bluemind.icalendar.parser
... ...
@@ -34,6 +34,7 @@ import java.util.ArrayList;
34 34
 import java.util.Date;
35 35
 import java.util.List;
36 36
 import java.util.Map;
37
+import java.util.Optional;
37 38
 import java.util.UUID;
38 39
 
39 40
 import javax.net.ssl.HttpsURLConnection;
... ...
@@ -123,7 +124,7 @@ public class CalendarContainerSync implements ISyncableContainer {
123 124
 		if (data.ics != null && !data.ics.isEmpty()) {
124 125
 			List<ItemValue<VEventSeries>> events = new ArrayList<>();
125 126
 			try {
126
-				events = VEventServiceHelper.convertToVEventList(data.ics);
127
+				events = VEventServiceHelper.convertToVEventList(data.ics, Optional.empty());
127 128
 			} catch (ServerFault sf) {
128 129
 				logger.error(sf.getMessage(), sf);
129 130
 				return ret;
... ...
@@ -13,5 +13,11 @@ Require-Bundle: net.bluemind.calendar.api,
13 13
  slf4j.api,
14 14
  net.bluemind.lib.ical4j,
15 15
  net.bluemind.core.container.api;bundle-version="4.1.0",
16
- org.apache.commons.lang
16
+ org.apache.commons.lang,
17
+ net.bluemind.attachment.api,
18
+ net.bluemind.core.context,
19
+ net.bluemind.core.rest,
20
+ net.bluemind.user.api,
21
+ net.bluemind.core.sessions,
22
+ com.google.guava
17 23
 Export-Package: net.bluemind.icalendar.parser
18 24
new file mode 100644
... ...
@@ -0,0 +1,29 @@
1
+/* BEGIN LICENSE
2
+ * Copyright © Blue Mind SAS, 2012-2018
3
+ *
4
+ * This file is part of BlueMind. BlueMind is a messaging and collaborative
5
+ * solution.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of either the GNU Affero General Public License as
9
+ * published by the Free Software Foundation (version 3 of the License).
10
+ *
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
+ *
16
+ * See LICENSE.txt
17
+ * END LICENSE
18
+ */
19
+package net.bluemind.icalendar.parser;
20
+
21
+public class CalendarOwner {
22
+	public final String domainUid;
23
+	public final String userUid;
24
+
25
+	public CalendarOwner(String domainUid, String userUid) {
26
+		this.domainUid = domainUid;
27
+		this.userUid = userUid;
28
+	}
29
+}
... ...
@@ -18,6 +18,8 @@
18 18
  */
19 19
 package net.bluemind.icalendar.parser;
20 20
 
21
+import java.util.Optional;
22
+
21 23
 import net.bluemind.calendar.api.VEvent;
22 24
 import net.bluemind.calendar.api.VEventOccurrence;
23 25
 import net.bluemind.core.api.date.BmDateTime;
... ...
@@ -30,8 +32,9 @@ public class ICal4jEventHelper<T extends VEvent> extends ICal4jHelper<T> {
30 32
 
31 33
 	@SuppressWarnings("unchecked")
32 34
 	@Override
33
-	public ItemValue<T> parseIcs(T iCalendarElement, CalendarComponent cc, String globalTZ) {
34
-		ItemValue<T> parseIcs = super.parseIcs(iCalendarElement, cc, globalTZ);
35
+	public ItemValue<T> parseIcs(T iCalendarElement, CalendarComponent cc, String globalTZ,
36
+			Optional<CalendarOwner> owner) {
37
+		ItemValue<T> parseIcs = super.parseIcs(iCalendarElement, cc, globalTZ, owner);
35 38
 
36 39
 		// RECCURID
37 40
 		if (cc.getProperty(Property.RECURRENCE_ID) != null) {
... ...
@@ -26,6 +26,7 @@ import java.util.Collections;
26 26
 import java.util.HashSet;
27 27
 import java.util.Iterator;
28 28
 import java.util.List;
29
+import java.util.Optional;
29 30
 import java.util.Set;
30 31
 import java.util.UUID;
31 32
 
... ...
@@ -33,11 +34,16 @@ import org.apache.commons.lang.StringUtils;
33 34
 import org.slf4j.Logger;
34 35
 import org.slf4j.LoggerFactory;
35 36
 
37
+import net.bluemind.attachment.api.AttachedFile;
38
+import net.bluemind.attachment.api.IAttachment;
36 39
 import net.bluemind.calendar.api.VEventOccurrence;
37 40
 import net.bluemind.core.api.date.BmDateTime;
38 41
 import net.bluemind.core.api.date.BmDateTime.Precision;
39 42
 import net.bluemind.core.api.date.BmDateTimeWrapper;
43
+import net.bluemind.core.api.fault.ServerFault;
40 44
 import net.bluemind.core.container.model.ItemValue;
45
+import net.bluemind.core.rest.ServerSideServiceProvider;
46
+import net.bluemind.core.rest.base.GenericStream;
41 47
 import net.bluemind.core.utils.DateTimeComparator;
42 48
 import net.bluemind.icalendar.api.ICalendarElement;
43 49
 import net.bluemind.icalendar.api.ICalendarElement.Classification;
... ...
@@ -78,6 +84,7 @@ import net.fortuna.ical4j.model.parameter.SentBy;
78 84
 import net.fortuna.ical4j.model.parameter.Value;
79 85
 import net.fortuna.ical4j.model.parameter.XParameter;
80 86
 import net.fortuna.ical4j.model.property.Action;
87
+import net.fortuna.ical4j.model.property.Attach;
81 88
 import net.fortuna.ical4j.model.property.Attendee;
82 89
 import net.fortuna.ical4j.model.property.Categories;
83 90
 import net.fortuna.ical4j.model.property.Clazz;
... ...
@@ -110,7 +117,8 @@ public class ICal4jHelper<T extends ICalendarElement> {
110 117
 	static ZoneId utcTz = ZoneId.of("UTC");
111 118
 
112 119
 	// ICS -> BM
113
-	public ItemValue<T> parseIcs(T iCalendarElement, CalendarComponent cc, String globalTZ) {
120
+	public ItemValue<T> parseIcs(T iCalendarElement, CalendarComponent cc, String globalTZ,
121
+			Optional<CalendarOwner> owner) {
114 122
 
115 123
 		// UID
116 124
 		String uid = parseIcsUid(cc.getProperty(Property.UID));
... ...
@@ -284,9 +292,69 @@ public class ICal4jHelper<T extends ICalendarElement> {
284 292
 			iCalendarElement.rrule = rrule;
285 293
 		}
286 294
 
295
+		// ATTACH
296
+		iCalendarElement.attachments = parseAttachments(cc.getProperties(Property.ATTACH), owner);
297
+
287 298
 		return ItemValue.create(uid, iCalendarElement);
288 299
 	}
289 300
 
301
+	private List<AttachedFile> parseAttachments(PropertyList attachments, Optional<CalendarOwner> owner) {
302
+		List<AttachedFile> atts = new ArrayList<>();
303
+
304
+		for (int i = 0; i < attachments.size(); i++) {
305
+			Attach prop = (Attach) attachments.get(i);
306
+			byte[] binary = prop.getBinary();
307
+			if (binary == null && prop.getUri() != null) {
308
+				atts.add(addUriAttachment(prop));
309
+			} else if (binary != null && owner.isPresent()) {
310
+				AttachedFile addBinaryAttachment = addBinaryAttachment(prop, binary, i, owner);
311
+				if (addBinaryAttachment != null) {
312
+					atts.add(addBinaryAttachment);
313
+				}
314
+			}
315
+		}
316
+
317
+		return atts;
318
+
319
+	}
320
+
321
+	private AttachedFile addBinaryAttachment(Attach prop, byte[] binary, int index, Optional<CalendarOwner> owner) {
322
+		String extension = "data";
323
+		Parameter fmtType = prop.getParameter(Parameter.FMTTYPE);
324
+		if (fmtType != null) {
325
+			extension = Mime.getExtension(fmtType.getValue());
326
+		}
327
+		String b64 = new String(binary);
328
+		String filename = "attachment_" + index + "." + extension;
329
+		CalendarOwner calOwner = owner.get();
330
+		try (Sudo asUser = new Sudo(calOwner.userUid, calOwner.domainUid)) {
331
+			try {
332
+				IAttachment service = ServerSideServiceProvider.getProvider(asUser.context).instance(IAttachment.class,
333
+						calOwner.domainUid);
334
+				AttachedFile att = service.share(filename, GenericStream.simpleValue(b64, b -> b.getBytes()));
335
+				return att;
336
+			} catch (ServerFault e) {
337
+				logger.info("Cannot attach binary file as attachment: {}", e.getMessage());
338
+			}
339
+		}
340
+		return null;
341
+	}
342
+
343
+	private AttachedFile addUriAttachment(Attach prop) {
344
+		String url = prop.getUri().toString();
345
+		String filename = null;
346
+		if (prop.getParameter("X-FILE-NAME") != null) {
347
+			filename = prop.getParameter("X-FILE-NAME").getValue();
348
+		} else {
349
+			filename = prop.getUri().getPath();
350
+		}
351
+		AttachedFile att = new AttachedFile();
352
+		att.expirationDate = 0l;
353
+		att.name = filename;
354
+		att.publicUrl = url;
355
+		return att;
356
+	}
357
+
290 358
 	/**
291 359
 	 * @param categoriesPropList
292 360
 	 * @return
... ...
@@ -838,9 +906,28 @@ public class ICal4jHelper<T extends ICalendarElement> {
838 906
 				logger.warn("url is not valid", e);
839 907
 			}
840 908
 		}
909
+
910
+		// ATTACH
911
+		parseICalendarElementAttachments(properties, iCalendarElement);
912
+
841 913
 		return properties;
842 914
 	}
843 915
 
916
+	private static void parseICalendarElementAttachments(PropertyList properties, ICalendarElement iCalendarElement) {
917
+		if (iCalendarElement.attachments != null && !iCalendarElement.attachments.isEmpty()) {
918
+			for (AttachedFile attachment : iCalendarElement.attachments) {
919
+				ParameterList params = new ParameterList();
920
+				params.add(new XParameter("X-FILE-NAME", attachment.name));
921
+				try {
922
+					Attach attach = new Attach(params, attachment.publicUrl);
923
+					properties.add(attach);
924
+				} catch (Exception e) {
925
+					logger.warn("Attachment is not valid", e);
926
+				}
927
+			}
928
+		}
929
+	}
930
+
844 931
 	private static void parseICalendarElementReccurId(PropertyList properties, ICalendarElement iCalendarElement) {
845 932
 		if ((iCalendarElement instanceof VEventOccurrence) && ((VEventOccurrence) iCalendarElement).recurid != null) {
846 933
 			RecurrenceId recurId = new RecurrenceId(convertToIcsDate(((VEventOccurrence) iCalendarElement).recurid));
847 934
new file mode 100644
... ...
@@ -0,0 +1,259 @@
1
+/* BEGIN LICENSE
2
+ * Copyright © Blue Mind SAS, 2012-2018
3
+ *
4
+ * This file is part of BlueMind. BlueMind is a messaging and collaborative
5
+ * solution.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of either the GNU Affero General Public License as
9
+ * published by the Free Software Foundation (version 3 of the License).
10
+ *
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
+ *
16
+ * See LICENSE.txt
17
+ * END LICENSE
18
+ */
19
+package net.bluemind.icalendar.parser;
20
+
21
+import java.util.HashMap;
22
+
23
+public class Mime {
24
+
25
+	private static final String APPLICATION_ANDREW_INSET = "application/andrew-inset";
26
+	private static final String APPLICATION_JSON = "application/json";
27
+	private static final String APPLICATION_ZIP = "application/zip";
28
+	private static final String APPLICATION_X_GZIP = "application/x-gzip";
29
+	private static final String APPLICATION_TGZ = "application/tgz";
30
+	private static final String APPLICATION_MSWORD = "application/msword";
31
+	private static final String APPLICATION_MSWORD_2007 = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
32
+	private static final String APPLICATION_VND_TEXT = "application/vnd.oasis.opendocument.text";
33
+	private static final String APPLICATION_POSTSCRIPT = "application/postscript";
34
+	private static final String APPLICATION_PDF = "application/pdf";
35
+	private static final String APPLICATION_JNLP = "application/jnlp";
36
+	private static final String APPLICATION_MAC_BINHEX40 = "application/mac-binhex40";
37
+	private static final String APPLICATION_MAC_COMPACTPRO = "application/mac-compactpro";
38
+	private static final String APPLICATION_MATHML_XML = "application/mathml+xml";
39
+	private static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
40
+	private static final String APPLICATION_ODA = "application/oda";
41
+	private static final String APPLICATION_RDF_XML = "application/rdf+xml";
42
+	private static final String APPLICATION_JAVA_ARCHIVE = "application/java-archive";
43
+	private static final String APPLICATION_RDF_SMIL = "application/smil";
44
+	private static final String APPLICATION_SRGS = "application/srgs";
45
+	private static final String APPLICATION_SRGS_XML = "application/srgs+xml";
46
+	private static final String APPLICATION_VND_MIF = "application/vnd.mif";
47
+	private static final String APPLICATION_VND_MSEXCEL = "application/vnd.ms-excel";
48
+	private static final String APPLICATION_VND_MSEXCEL_2007 = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
49
+	private static final String APPLICATION_VND_SPREADSHEET = "application/vnd.oasis.opendocument.spreadsheet";
50
+	private static final String APPLICATION_VND_MSPOWERPOINT = "application/vnd.ms-powerpoint";
51
+	private static final String APPLICATION_VND_RNREALMEDIA = "application/vnd.rn-realmedia";
52
+	private static final String APPLICATION_X_BCPIO = "application/x-bcpio";
53
+	private static final String APPLICATION_X_CDLINK = "application/x-cdlink";
54
+	private static final String APPLICATION_X_CHESS_PGN = "application/x-chess-pgn";
55
+	private static final String APPLICATION_X_CPIO = "application/x-cpio";
56
+	private static final String APPLICATION_X_CSH = "application/x-csh";
57
+	private static final String APPLICATION_X_DIRECTOR = "application/x-director";
58
+	private static final String APPLICATION_X_DVI = "application/x-dvi";
59
+	private static final String APPLICATION_X_FUTURESPLASH = "application/x-futuresplash";
60
+	private static final String APPLICATION_X_GTAR = "application/x-gtar";
61
+	private static final String APPLICATION_X_HDF = "application/x-hdf";
62
+	private static final String APPLICATION_X_JAVASCRIPT = "application/x-javascript";
63
+	private static final String APPLICATION_X_KOAN = "application/x-koan";
64
+	private static final String APPLICATION_X_LATEX = "application/x-latex";
65
+	private static final String APPLICATION_X_NETCDF = "application/x-netcdf";
66
+	private static final String APPLICATION_X_OGG = "application/x-ogg";
67
+	private static final String APPLICATION_X_SH = "application/x-sh";
68
+	private static final String APPLICATION_X_SHAR = "application/x-shar";
69
+	private static final String APPLICATION_X_SHOCKWAVE_FLASH = "application/x-shockwave-flash";
70
+	private static final String APPLICATION_X_STUFFIT = "application/x-stuffit";
71
+	private static final String APPLICATION_X_SV4CPIO = "application/x-sv4cpio";
72
+	private static final String APPLICATION_X_SV4CRC = "application/x-sv4crc";
73
+	private static final String APPLICATION_X_TAR = "application/x-tar";
74
+	private static final String APPLICATION_X_RAR_COMPRESSED = "application/x-rar-compressed";
75
+	private static final String APPLICATION_X_TCL = "application/x-tcl";
76
+	private static final String APPLICATION_X_TEX = "application/x-tex";
77
+	private static final String APPLICATION_X_TEXINFO = "application/x-texinfo";
78
+	private static final String APPLICATION_X_TROFF = "application/x-troff";
79
+	private static final String APPLICATION_X_TROFF_MAN = "application/x-troff-man";
80
+	private static final String APPLICATION_X_TROFF_ME = "application/x-troff-me";
81
+	private static final String APPLICATION_X_TROFF_MS = "application/x-troff-ms";
82
+	private static final String APPLICATION_X_USTAR = "application/x-ustar";
83
+	private static final String APPLICATION_X_WAIS_SOURCE = "application/x-wais-source";
84
+	private static final String APPLICATION_VND_MOZZILLA_XUL_XML = "application/vnd.mozilla.xul+xml";
85
+	private static final String APPLICATION_XHTML_XML = "application/xhtml+xml";
86
+	private static final String APPLICATION_XSLT_XML = "application/xslt+xml";
87
+	private static final String APPLICATION_XML = "application/xml";
88
+	private static final String APPLICATION_XML_DTD = "application/xml-dtd";
89
+	private static final String IMAGE_BMP = "image/bmp";
90
+	private static final String IMAGE_CGM = "image/cgm";
91
+	private static final String IMAGE_GIF = "image/gif";
92
+	private static final String IMAGE_IEF = "image/ief";
93
+	private static final String IMAGE_JPEG = "image/jpeg";
94
+	private static final String IMAGE_TIFF = "image/tiff";
95
+	private static final String IMAGE_PNG = "image/png";
96
+	private static final String IMAGE_SVG_XML = "image/svg+xml";
97
+	private static final String IMAGE_VND_DJVU = "image/vnd.djvu";
98
+	private static final String IMAGE_WAP_WBMP = "image/vnd.wap.wbmp";
99
+	private static final String IMAGE_X_CMU_RASTER = "image/x-cmu-raster";
100
+	private static final String IMAGE_X_ICON = "image/x-icon";
101
+	private static final String IMAGE_X_PORTABLE_ANYMAP = "image/x-portable-anymap";
102
+	private static final String IMAGE_X_PORTABLE_BITMAP = "image/x-portable-bitmap";
103
+	private static final String IMAGE_X_PORTABLE_GRAYMAP = "image/x-portable-graymap";
104
+	private static final String IMAGE_X_PORTABLE_PIXMAP = "image/x-portable-pixmap";
105
+	private static final String IMAGE_X_RGB = "image/x-rgb";
106
+	private static final String AUDIO_BASIC = "audio/basic";
107
+	private static final String AUDIO_MIDI = "audio/midi";
108
+	private static final String AUDIO_MPEG = "audio/mpeg";
109
+	private static final String AUDIO_X_AIFF = "audio/x-aiff";
110
+	private static final String AUDIO_X_MPEGURL = "audio/x-mpegurl";
111
+	private static final String AUDIO_X_PN_REALAUDIO = "audio/x-pn-realaudio";
112
+	private static final String AUDIO_X_WAV = "audio/x-wav";
113
+	private static final String CHEMICAL_X_PDB = "chemical/x-pdb";
114
+	private static final String CHEMICAL_X_XYZ = "chemical/x-xyz";
115
+	private static final String MODEL_IGES = "model/iges";
116
+	private static final String MODEL_MESH = "model/mesh";
117
+	private static final String MODEL_VRLM = "model/vrml";
118
+	private static final String TEXT_PLAIN = "text/plain";
119
+	private static final String TEXT_RICHTEXT = "text/richtext";
120
+	private static final String TEXT_RTF = "text/rtf";
121
+	private static final String TEXT_HTML = "text/html";
122
+	private static final String TEXT_CALENDAR = "text/calendar";
123
+	private static final String TEXT_CSS = "text/css";
124
+	private static final String TEXT_SGML = "text/sgml";
125
+	private static final String TEXT_TAB_SEPARATED_VALUES = "text/tab-separated-values";
126
+	private static final String TEXT_VND_WAP_XML = "text/vnd.wap.wml";
127
+	private static final String TEXT_VND_WAP_WMLSCRIPT = "text/vnd.wap.wmlscript";
128
+	private static final String TEXT_X_SETEXT = "text/x-setext";
129
+	private static final String TEXT_X_COMPONENT = "text/x-component";
130
+	private static final String VIDEO_QUICKTIME = "video/quicktime";
131
+	private static final String VIDEO_MPEG = "video/mpeg";
132
+	private static final String VIDEO_VND_MPEGURL = "video/vnd.mpegurl";
133
+	private static final String VIDEO_X_MSVIDEO = "video/x-msvideo";
134
+	private static final String VIDEO_X_MS_WMV = "video/x-ms-wmv";
135
+	private static final String VIDEO_X_SGI_MOVIE = "video/x-sgi-movie";
136
+	private static final String X_CONFERENCE_X_COOLTALK = "x-conference/x-cooltalk";
137
+
138
+	private static HashMap<String, String> mapping;
139
+
140
+	static {
141
+		mapping = new HashMap<String, String>(200);
142
+
143
+		mapping.put(APPLICATION_VND_MOZZILLA_XUL_XML, "xul");
144
+		mapping.put(APPLICATION_JSON, "json");
145
+		mapping.put(X_CONFERENCE_X_COOLTALK, "ice");
146
+		mapping.put(VIDEO_X_SGI_MOVIE, "movie");
147
+		mapping.put(VIDEO_X_MSVIDEO, "avi");
148
+		mapping.put(VIDEO_X_MS_WMV, "wmv");
149
+		mapping.put(VIDEO_VND_MPEGURL, "m4u");
150
+		mapping.put(TEXT_X_COMPONENT, "htc");
151
+		mapping.put(TEXT_X_SETEXT, "etx");
152
+		mapping.put(TEXT_VND_WAP_WMLSCRIPT, "wmls");
153
+		mapping.put(TEXT_VND_WAP_XML, "wml");
154
+		mapping.put(TEXT_TAB_SEPARATED_VALUES, "tsv");
155
+		mapping.put(TEXT_SGML, "sgml");
156
+		mapping.put(TEXT_CSS, "css");
157
+		mapping.put(TEXT_CALENDAR, "ics");
158
+		mapping.put(MODEL_VRLM, "vrlm");
159
+		mapping.put(MODEL_MESH, "mesh");
160
+		mapping.put(MODEL_IGES, "iges");
161
+		mapping.put(IMAGE_X_RGB, "rgb");
162
+		mapping.put(IMAGE_X_PORTABLE_PIXMAP, "ppm");
163
+		mapping.put(IMAGE_X_PORTABLE_GRAYMAP, "pgm");
164
+		mapping.put(IMAGE_X_PORTABLE_BITMAP, "pbm");
165
+		mapping.put(IMAGE_X_PORTABLE_ANYMAP, "pnm");
166
+		mapping.put(IMAGE_X_ICON, "ico");
167
+		mapping.put(IMAGE_X_CMU_RASTER, "ras");
168
+		mapping.put(IMAGE_WAP_WBMP, "wbmp");
169
+		mapping.put(IMAGE_VND_DJVU, "djvu");
170
+		mapping.put(IMAGE_SVG_XML, "svg");
171
+		mapping.put(IMAGE_IEF, "ief");
172
+		mapping.put(IMAGE_CGM, "cgm");
173
+		mapping.put(IMAGE_BMP, "bmp");
174
+		mapping.put(CHEMICAL_X_XYZ, "xyz");
175
+		mapping.put(CHEMICAL_X_PDB, "pdb");
176
+		mapping.put(AUDIO_X_PN_REALAUDIO, "ra");
177
+		mapping.put(AUDIO_X_MPEGURL, "m3u");
178
+		mapping.put(AUDIO_X_AIFF, "aiff");
179
+		mapping.put(AUDIO_MPEG, "mp3");
180
+		mapping.put(AUDIO_MIDI, "midi");
181
+		mapping.put(APPLICATION_XML_DTD, "dtd");
182
+		mapping.put(APPLICATION_XML, "xml");
183
+		mapping.put(APPLICATION_XSLT_XML, "xslt");
184
+		mapping.put(APPLICATION_XHTML_XML, "xhtml");
185
+		mapping.put(APPLICATION_X_WAIS_SOURCE, "src");
186
+		mapping.put(APPLICATION_X_USTAR, "ustar");
187
+		mapping.put(APPLICATION_X_TROFF_MS, "ms");
188
+		mapping.put(APPLICATION_X_TROFF_ME, "me");
189
+		mapping.put(APPLICATION_X_TROFF_MAN, "man");
190
+		mapping.put(APPLICATION_X_TROFF, "roff");
191
+		mapping.put(APPLICATION_X_TEXINFO, "texi");
192
+		mapping.put(APPLICATION_X_TEX, "tex");
193
+		mapping.put(APPLICATION_X_TCL, "tcl");
194
+		mapping.put(APPLICATION_X_SV4CRC, "sv4crc");
195
+		mapping.put(APPLICATION_X_SV4CPIO, "sv4cpio");
196
+		mapping.put(APPLICATION_X_STUFFIT, "sit");
197
+		mapping.put(APPLICATION_X_SHOCKWAVE_FLASH, "swf");
198
+		mapping.put(APPLICATION_X_SHAR, "shar");
199
+		mapping.put(APPLICATION_X_SH, "sh");
200
+		mapping.put(APPLICATION_X_NETCDF, "cdf");
201
+		mapping.put(APPLICATION_X_LATEX, "latex");
202
+		mapping.put(APPLICATION_X_KOAN, "skm");
203
+		mapping.put(APPLICATION_X_JAVASCRIPT, "js");
204
+		mapping.put(APPLICATION_X_HDF, "hdf");
205
+		mapping.put(APPLICATION_X_GTAR, "gtar");
206
+		mapping.put(APPLICATION_X_FUTURESPLASH, "spl");
207
+		mapping.put(APPLICATION_X_DVI, "dvi");
208
+		mapping.put(APPLICATION_X_DIRECTOR, "dir");
209
+		mapping.put(APPLICATION_X_CSH, "csh");
210
+		mapping.put(APPLICATION_X_CPIO, "cpio");
211
+		mapping.put(APPLICATION_X_CHESS_PGN, "pgn");
212
+		mapping.put(APPLICATION_X_CDLINK, "vcd");
213
+		mapping.put(APPLICATION_X_BCPIO, "bcpio");
214
+		mapping.put(APPLICATION_VND_RNREALMEDIA, "rm");
215
+		mapping.put(APPLICATION_VND_MSPOWERPOINT, "ppt");
216
+		mapping.put(APPLICATION_VND_MIF, "mif");
217
+		mapping.put(APPLICATION_SRGS_XML, "grxml");
218
+		mapping.put(APPLICATION_SRGS, "gram");
219
+		mapping.put(APPLICATION_RDF_SMIL, "smil");
220
+		mapping.put(APPLICATION_RDF_XML, "rdf");
221
+		mapping.put(APPLICATION_X_OGG, "ogg");
222
+		mapping.put(APPLICATION_ODA, "oda");
223
+		mapping.put(APPLICATION_MATHML_XML, "mathml");
224
+		mapping.put(APPLICATION_MAC_COMPACTPRO, "cpt");
225
+		mapping.put(APPLICATION_MAC_BINHEX40, "hqx");
226
+		mapping.put(APPLICATION_JNLP, "jnlp");
227
+		mapping.put(APPLICATION_ANDREW_INSET, "ez");
228
+		mapping.put(TEXT_PLAIN, "txt");
229
+		mapping.put(TEXT_RTF, "rtf");
230
+		mapping.put(TEXT_RICHTEXT, "rtx");
231
+		mapping.put(TEXT_HTML, "html");
232
+		mapping.put(APPLICATION_ZIP, "zip");
233
+		mapping.put(APPLICATION_X_RAR_COMPRESSED, "rar");
234
+		mapping.put(APPLICATION_X_GZIP, "gzip");
235
+		mapping.put(APPLICATION_TGZ, "tgz");
236
+		mapping.put(APPLICATION_X_TAR, "tar");
237
+		mapping.put(IMAGE_GIF, "gif");
238
+		mapping.put(IMAGE_JPEG, "jpg");
239
+		mapping.put(IMAGE_TIFF, "tiff");
240
+		mapping.put(IMAGE_PNG, "png");
241
+		mapping.put(AUDIO_BASIC, "au");
242
+		mapping.put(AUDIO_X_WAV, "wav");
243
+		mapping.put(VIDEO_QUICKTIME, "mov");
244
+		mapping.put(VIDEO_MPEG, "mpg");
245
+		mapping.put(APPLICATION_MSWORD, "doc");
246
+		mapping.put(APPLICATION_MSWORD_2007, "docx");
247
+		mapping.put(APPLICATION_VND_TEXT, "odt");
248
+		mapping.put(APPLICATION_VND_MSEXCEL, "xls");
249
+		mapping.put(APPLICATION_VND_SPREADSHEET, "ods");
250
+		mapping.put(APPLICATION_POSTSCRIPT, "ps");
251
+		mapping.put(APPLICATION_PDF, "pdf");
252
+		mapping.put(APPLICATION_OCTET_STREAM, "exe");
253
+		mapping.put(APPLICATION_JAVA_ARCHIVE, "jar");
254
+	}
255
+
256
+	public static String getExtension(String mimeType) {
257
+		return mapping.getOrDefault(mimeType, "data");
258
+	}
259
+}
0 260
new file mode 100644
... ...
@@ -0,0 +1,62 @@
1
+/* BEGIN LICENSE
2
+ * Copyright © Blue Mind SAS, 2012-2016
3
+ *
4
+ * This file is part of BlueMind. BlueMind is a messaging and collaborative
5
+ * solution.
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of either the GNU Affero General Public License as
9
+ * published by the Free Software Foundation (version 3 of the License).
10
+ *
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
+ *
16
+ * See LICENSE.txt
17
+ * END LICENSE
18
+ */
19
+
20
+package net.bluemind.icalendar.parser;
21
+
22
+import java.util.Arrays;
23
+import java.util.Collections;
24
+import java.util.UUID;
25
+
26
+import org.slf4j.Logger;
27
+import org.slf4j.LoggerFactory;
28
+
29
+import net.bluemind.core.api.fault.ServerFault;
30
+import net.bluemind.core.container.model.ItemValue;
31
+import net.bluemind.core.context.SecurityContext;
32
+import net.bluemind.core.rest.ServerSideServiceProvider;
33
+import net.bluemind.core.sessions.Sessions;
34
+import net.bluemind.user.api.IUser;
35
+import net.bluemind.user.api.User;
36
+
37
+public final class Sudo implements AutoCloseable {
38
+	private static final Logger logger = LoggerFactory.getLogger(Sudo.class);
39
+
40
+	public final SecurityContext context;
41
+
42
+	public Sudo(String uid, String domainContainerUid) throws ServerFault {
43
+		IUser u = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class,
44
+				domainContainerUid);
45
+		ItemValue<User> theUser = u.getComplete(uid);
46
+		if (theUser == null) {
47
+			throw ServerFault.notFound("UID for " + uid + " in " + domainContainerUid + " not found.");
48
+		}
49
+		logger.debug("[{}] sudo login {} has uid {}", domainContainerUid, uid, theUser.uid);
50
+		SecurityContext userContext = new SecurityContext(UUID.randomUUID().toString(), theUser.uid,
51
+				Arrays.<String>asList(), Arrays.<String>asList(), Collections.emptyMap(), domainContainerUid, "en",
52
+				"Sudo", false);
53
+		Sessions.get().put(userContext.getSessionId(), userContext);
54
+		this.context = userContext;
55
+	}
56
+
57
+	@Override
58
+	public void close() {
59
+		Sessions.get().invalidate(context.getSessionId());
60
+	}
61
+
62
+}
... ...
@@ -9,5 +9,6 @@ Require-Bundle: net.bluemind.slf4j;bundle-version="1.0.0",
9 9
  net.bluemind.todolist.api;bundle-version="1.0.0",
10 10
  net.bluemind.core.commons;bundle-version="1.0.0",
11 11
  net.bluemind.core.container.api;bundle-version="1.0.0",
12
- net.bluemind.icalendar.parser;visibility:=reexport
12
+ net.bluemind.icalendar.parser;visibility:=reexport,
13
+ net.bluemind.attachment.api
13 14
 Export-Package: net.bluemind.todolist.adapter
... ...
@@ -8,6 +8,7 @@ import java.io.Reader;
8 8
 import java.util.ArrayList;
9 9
 import java.util.Iterator;
10 10
 import java.util.List;
11
+import java.util.Optional;
11 12
 
12 13
 import net.bluemind.core.api.date.BmDateTimeWrapper;
13 14
 import net.bluemind.core.api.fault.ServerFault;
... ...
@@ -59,11 +60,10 @@ public class VTodoAdapter extends ICal4jHelper<VTodo> {
59 60
 	 * Create an iCalendar {@link VToDo} component from a {@link VTodo} object.
60 61
 	 * 
61 62
 	 * @param BlueMind
62
-	 *            Vtodo
63
+	 *                     Vtodo
63 64
 	 * @return ICalendar VToDo
64 65
 	 */
65 66
 	public static VToDo adaptTodo(String uid, VTodo vtodo) {
66
-
67 67
 		VToDo ret = new VToDo();
68 68
 
69 69
 		parseICalendarElement(uid, ret, vtodo);
... ...
@@ -180,7 +180,7 @@ public class VTodoAdapter extends ICal4jHelper<VTodo> {
180 180
 			}
181 181
 
182 182
 			VTodo vtodo = new VTodo();
183
-			vtodo = parseIcs(vtodo, ical4j, globalTZ).value;
183
+			vtodo = parseIcs(vtodo, ical4j, globalTZ, Optional.empty()).value;
184 184
 
185 185
 			// DUE
186 186
 			vtodo.due = parseIcsDate(ical4j.getDue(), globalTZ);
... ...
@@ -20,6 +20,7 @@ package net.bluemind.dav.server.proto.put;
20 20
 
21 21
 import java.util.Arrays;
22 22
 import java.util.List;
23
+import java.util.Optional;
23 24
 
24 25
 import org.slf4j.Logger;
25 26
 import org.slf4j.LoggerFactory;
... ...
@@ -126,7 +127,8 @@ abstract class CreateEntity {
126 127
 		public void create(LoggedCore lc, PutQuery query, PutResponse pr, ContainerDescriptor cal) throws ServerFault {
127 128
 			String itemUid = query.getExtId();
128 129
 			logger.info("[{}] VEvent uid from query is {}", cal.uid, itemUid);
129
-			List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(query.getCalendar());
130
+			List<ItemValue<VEventSeries>> events = VEventServiceHelper.convertToVEventList(query.getCalendar(),
131
+					Optional.empty());
130 132
 			ICalendar calApi = lc.getCore().instance(ICalendar.class, cal.uid);
131 133
 			if (events.size() != 1) {
132 134
 				throw new ServerFault("woop");
... ...
@@ -27,6 +27,7 @@ import java.text.SimpleDateFormat;
27 27
 import java.util.Date;
28 28
 import java.util.Iterator;
29 29
 import java.util.List;
30
+import java.util.Optional;
30 31
 
31 32
 import org.apache.james.mime4j.dom.Entity;
32 33
 import org.apache.james.mime4j.dom.TextBody;
... ...
@@ -102,7 +103,8 @@ public class ITIPPartParser {
102 103
 				orga = icalVEvent.getOrganizer();
103 104
 				seq = icalVEvent.getSequence();
104 105
 				VEvent calElement = new VEvent();
105
-				calElement = new ICal4jEventHelper<VEvent>().parseIcs(calElement, part, globalTZ).value;
106
+				calElement = new ICal4jEventHelper<VEvent>().parseIcs(calElement, part, globalTZ,
107
+						Optional.empty()).value;
106 108
 
107 109
 				// DTEND
108 110
 				calElement.dtend = IcalConverter.convertToDateTime(icalVEvent.getEndDate(), globalTZ);
... ...
@@ -140,7 +142,7 @@ public class ITIPPartParser {
140 142
 				orga = icalVTodo.getOrganizer();
141 143
 				seq = icalVTodo.getSequence();
142 144
 				VTodo calElement = new VTodo();
143
-				new ICal4jHelper<VTodo>().parseIcs(calElement, part, globalTZ);
145
+				new ICal4jHelper<VTodo>().parseIcs(calElement, part, globalTZ, Optional.empty());
144 146
 
145 147
 				// DUE
146 148
 				calElement.due = IcalConverter.convertToDateTime(icalVTodo.getDue(), globalTZ);
... ...
@@ -31,6 +31,7 @@ import java.time.ZonedDateTime;
31 31
 import java.util.ArrayList;
32 32
 import java.util.Arrays;
33 33
 import java.util.List;
34
+import java.util.Optional;
34 35
 import java.util.UUID;
35 36
 import java.util.concurrent.CountDownLatch;
36 37
 import java.util.stream.Collectors;
... ...
@@ -1137,7 +1138,7 @@ public class ImipFilterVEventTests {
1137 1138
 		InputStream in = this.getClass().getClassLoader().getResourceAsStream("ics/" + filename);
1138 1139
 		String ics = FileUtils.streamString(in, true);
1139 1140
 		in.close();
1140
-		List<ItemValue<VEventSeries>> vevents = VEventServiceHelper.convertToVEventList(ics);
1141
+		List<ItemValue<VEventSeries>> vevents = VEventServiceHelper.convertToVEventList(ics, Optional.empty());
1141 1142
 		return vevents;
1142 1143
 	}
1143 1144