aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorOren Hurvitz2012-04-23 17:26:37 +0300
committerJustin Clark-Casey (justincc)2012-04-26 22:49:14 +0100
commit0da8fe3124402581883f87b2f7036727905038db (patch)
tree9f8d42b76595236307a82c7c3c25b286e644795a
parentWhen creating an OAR, objects where the user is the Creator are always includ... (diff)
downloadopensim-SC-0da8fe3124402581883f87b2f7036727905038db.zip
opensim-SC-0da8fe3124402581883f87b2f7036727905038db.tar.gz
opensim-SC-0da8fe3124402581883f87b2f7036727905038db.tar.bz2
opensim-SC-0da8fe3124402581883f87b2f7036727905038db.tar.xz
Refactored how asset/inventory types are associated with content types: gathered all the knowledge into a single class. Added the Mesh content type.
-rw-r--r--OpenSim/Framework/SLUtil.cs382
-rw-r--r--OpenSim/Framework/Tests/UtilTest.cs23
2 files changed, 177 insertions, 228 deletions
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index db4541e..537de7a 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -38,239 +38,189 @@ namespace OpenSim.Framework
38 public static class SLUtil 38 public static class SLUtil
39 { 39 {
40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 41
42 #region SL / file extension / content-type conversions 42 #region SL / file extension / content-type conversions
43 43
44 public static string SLAssetTypeToContentType(int assetType) 44 private class TypeMapping
45 { 45 {
46 switch ((AssetType)assetType) 46 private sbyte assetType;
47 private InventoryType inventoryType;
48 private string contentType;
49 private string contentType2;
50 private string extension;
51
52 public sbyte AssetTypeCode
53 {
54 get { return assetType; }
55 }
56
57 public object AssetType
58 {
59 get {
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else
63 return OpenMetaverse.AssetType.Unknown;
64 }
65 }
66
67 public InventoryType InventoryType
68 {
69 get { return inventoryType; }
70 }
71
72 public string ContentType
73 {
74 get { return contentType; }
75 }
76
77 public string ContentType2
78 {
79 get { return contentType2; }
80 }
81
82 public string Extension
83 {
84 get { return extension; }
85 }
86
87 private TypeMapping(sbyte assetType, InventoryType inventoryType, string contentType, string contentType2, string extension)
88 {
89 this.assetType = assetType;
90 this.inventoryType = inventoryType;
91 this.contentType = contentType;
92 this.contentType2 = contentType2;
93 this.extension = extension;
94 }
95
96 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string contentType2, string extension)
97 : this((sbyte)assetType, inventoryType, contentType, contentType2, extension)
98 {
99 }
100
101 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string extension)
102 : this((sbyte)assetType, inventoryType, contentType, null, extension)
47 { 103 {
48 case AssetType.Texture:
49 return "image/x-j2c";
50 case AssetType.Sound:
51 return "audio/ogg";
52 case AssetType.CallingCard:
53 return "application/vnd.ll.callingcard";
54 case AssetType.Landmark:
55 return "application/vnd.ll.landmark";
56 case AssetType.Clothing:
57 return "application/vnd.ll.clothing";
58 case AssetType.Object:
59 return "application/vnd.ll.primitive";
60 case AssetType.Notecard:
61 return "application/vnd.ll.notecard";
62 case AssetType.Folder:
63 return "application/vnd.ll.folder";
64 case AssetType.RootFolder:
65 return "application/vnd.ll.rootfolder";
66 case AssetType.LSLText:
67 return "application/vnd.ll.lsltext";
68 case AssetType.LSLBytecode:
69 return "application/vnd.ll.lslbyte";
70 case AssetType.TextureTGA:
71 case AssetType.ImageTGA:
72 return "image/tga";
73 case AssetType.Bodypart:
74 return "application/vnd.ll.bodypart";
75 case AssetType.TrashFolder:
76 return "application/vnd.ll.trashfolder";
77 case AssetType.SnapshotFolder:
78 return "application/vnd.ll.snapshotfolder";
79 case AssetType.LostAndFoundFolder:
80 return "application/vnd.ll.lostandfoundfolder";
81 case AssetType.SoundWAV:
82 return "audio/x-wav";
83 case AssetType.ImageJPEG:
84 return "image/jpeg";
85 case AssetType.Animation:
86 return "application/vnd.ll.animation";
87 case AssetType.Gesture:
88 return "application/vnd.ll.gesture";
89 case AssetType.Simstate:
90 return "application/x-metaverse-simstate";
91 case AssetType.FavoriteFolder:
92 return "application/vnd.ll.favoritefolder";
93 case AssetType.Link:
94 return "application/vnd.ll.link";
95 case AssetType.LinkFolder:
96 return "application/vnd.ll.linkfolder";
97 case AssetType.CurrentOutfitFolder:
98 return "application/vnd.ll.currentoutfitfolder";
99 case AssetType.OutfitFolder:
100 return "application/vnd.ll.outfitfolder";
101 case AssetType.MyOutfitsFolder:
102 return "application/vnd.ll.myoutfitsfolder";
103 case AssetType.Unknown:
104 default:
105 return "application/octet-stream";
106 } 104 }
107 } 105 }
108 106
109 public static string SLInvTypeToContentType(int invType) 107 /// <summary>
108 /// Maps between AssetType, InventoryType and Content-Type.
109 /// Where more than one possibility exists, the first one takes precedence. E.g.:
110 /// AssetType "AssetType.Texture" -> Content-Type "image-xj2c"
111 /// Content-Type "image/x-j2c" -> InventoryType "InventoryType.Texture"
112 /// </summary>
113 private static TypeMapping[] MAPPINGS = new TypeMapping[] {
114 new TypeMapping(AssetType.Unknown, InventoryType.Unknown, "application/octet-stream", "bin"),
115 new TypeMapping(AssetType.Texture, InventoryType.Texture, "image/x-j2c", "image/jp2", "j2c"),
116 new TypeMapping(AssetType.Texture, InventoryType.Snapshot, "image/x-j2c", "image/jp2", "j2c"),
117 new TypeMapping(AssetType.TextureTGA, InventoryType.Texture, "image/tga", "tga"),
118 new TypeMapping(AssetType.ImageTGA, InventoryType.Texture, "image/tga", "tga"),
119 new TypeMapping(AssetType.ImageJPEG, InventoryType.Texture, "image/jpeg", "jpg"),
120 new TypeMapping(AssetType.Sound, InventoryType.Sound, "audio/ogg", "application/ogg", "ogg"),
121 new TypeMapping(AssetType.SoundWAV, InventoryType.Sound, "audio/x-wav", "wav"),
122 new TypeMapping(AssetType.CallingCard, InventoryType.CallingCard, "application/vnd.ll.callingcard", "application/x-metaverse-callingcard", "callingcard"),
123 new TypeMapping(AssetType.Landmark, InventoryType.Landmark, "application/vnd.ll.landmark", "application/x-metaverse-landmark", "landmark"),
124 new TypeMapping(AssetType.Clothing, InventoryType.Wearable, "application/vnd.ll.clothing", "application/x-metaverse-clothing", "clothing"),
125 new TypeMapping(AssetType.Object, InventoryType.Object, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
126 new TypeMapping(AssetType.Object, InventoryType.Attachment, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
127 new TypeMapping(AssetType.Notecard, InventoryType.Notecard, "application/vnd.ll.notecard", "application/x-metaverse-notecard", "notecard"),
128 new TypeMapping(AssetType.Folder, InventoryType.Folder, "application/vnd.ll.folder", "folder"),
129 new TypeMapping(AssetType.RootFolder, InventoryType.RootCategory, "application/vnd.ll.rootfolder", "rootfolder"),
130 new TypeMapping(AssetType.LSLText, InventoryType.LSL, "application/vnd.ll.lsltext", "application/x-metaverse-lsl", "lsl"),
131 new TypeMapping(AssetType.LSLBytecode, InventoryType.LSL, "application/vnd.ll.lslbyte", "application/x-metaverse-lso", "lso"),
132 new TypeMapping(AssetType.Bodypart, InventoryType.Wearable, "application/vnd.ll.bodypart", "application/x-metaverse-bodypart", "bodypart"),
133 new TypeMapping(AssetType.TrashFolder, InventoryType.Folder, "application/vnd.ll.trashfolder", "trashfolder"),
134 new TypeMapping(AssetType.SnapshotFolder, InventoryType.Folder, "application/vnd.ll.snapshotfolder", "snapshotfolder"),
135 new TypeMapping(AssetType.LostAndFoundFolder, InventoryType.Folder, "application/vnd.ll.lostandfoundfolder", "lostandfoundfolder"),
136 new TypeMapping(AssetType.Animation, InventoryType.Animation, "application/vnd.ll.animation", "application/x-metaverse-animation", "animation"),
137 new TypeMapping(AssetType.Gesture, InventoryType.Gesture, "application/vnd.ll.gesture", "application/x-metaverse-gesture", "gesture"),
138 new TypeMapping(AssetType.Simstate, InventoryType.Snapshot, "application/x-metaverse-simstate", "simstate"),
139 new TypeMapping(AssetType.FavoriteFolder, InventoryType.Unknown, "application/vnd.ll.favoritefolder", "favoritefolder"),
140 new TypeMapping(AssetType.Link, InventoryType.Unknown, "application/vnd.ll.link", "link"),
141 new TypeMapping(AssetType.LinkFolder, InventoryType.Unknown, "application/vnd.ll.linkfolder", "linkfolder"),
142 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
143 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"),
144 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
145 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm")
146 };
147
148 private static Dictionary<sbyte, string> asset2Content;
149 private static Dictionary<sbyte, string> asset2Extension;
150 private static Dictionary<InventoryType, string> inventory2Content;
151 private static Dictionary<string, sbyte> content2Asset;
152 private static Dictionary<string, InventoryType> content2Inventory;
153
154 static SLUtil()
110 { 155 {
111 switch ((InventoryType)invType) 156 asset2Content = new Dictionary<sbyte, string>();
157 asset2Extension = new Dictionary<sbyte, string>();
158 inventory2Content = new Dictionary<InventoryType, string>();
159 content2Asset = new Dictionary<string, sbyte>();
160 content2Inventory = new Dictionary<string, InventoryType>();
161
162 foreach (TypeMapping mapping in MAPPINGS)
112 { 163 {
113 case InventoryType.Animation: 164 sbyte assetType = mapping.AssetTypeCode;
114 return "application/vnd.ll.animation"; 165 if (!asset2Content.ContainsKey(assetType))
115 case InventoryType.CallingCard: 166 asset2Content.Add(assetType, mapping.ContentType);
116 return "application/vnd.ll.callingcard"; 167 if (!asset2Extension.ContainsKey(assetType))
117 case InventoryType.Folder: 168 asset2Extension.Add(assetType, mapping.Extension);
118 return "application/vnd.ll.folder"; 169 if (!inventory2Content.ContainsKey(mapping.InventoryType))
119 case InventoryType.Gesture: 170 inventory2Content.Add(mapping.InventoryType, mapping.ContentType);
120 return "application/vnd.ll.gesture"; 171 if (!content2Asset.ContainsKey(mapping.ContentType))
121 case InventoryType.Landmark: 172 content2Asset.Add(mapping.ContentType, assetType);
122 return "application/vnd.ll.landmark"; 173 if (!content2Inventory.ContainsKey(mapping.ContentType))
123 case InventoryType.LSL: 174 content2Inventory.Add(mapping.ContentType, mapping.InventoryType);
124 return "application/vnd.ll.lsltext"; 175
125 case InventoryType.Notecard: 176 if (mapping.ContentType2 != null)
126 return "application/vnd.ll.notecard"; 177 {
127 case InventoryType.Attachment: 178 if (!content2Asset.ContainsKey(mapping.ContentType2))
128 case InventoryType.Object: 179 content2Asset.Add(mapping.ContentType2, assetType);
129 return "application/vnd.ll.primitive"; 180 if (!content2Inventory.ContainsKey(mapping.ContentType2))
130 case InventoryType.Sound: 181 content2Inventory.Add(mapping.ContentType2, mapping.InventoryType);
131 return "audio/ogg"; 182 }
132 case InventoryType.Snapshot:
133 case InventoryType.Texture:
134 return "image/x-j2c";
135 case InventoryType.Wearable:
136 return "application/vnd.ll.clothing";
137 default:
138 return "application/octet-stream";
139 } 183 }
140 } 184 }
185
186 public static string SLAssetTypeToContentType(int assetType)
187 {
188 string contentType;
189 if (!asset2Content.TryGetValue((sbyte)assetType, out contentType))
190 contentType = asset2Content[(sbyte)AssetType.Unknown];
191 return contentType;
192 }
193
194 public static string SLInvTypeToContentType(int invType)
195 {
196 string contentType;
197 if (!inventory2Content.TryGetValue((InventoryType)invType, out contentType))
198 contentType = inventory2Content[InventoryType.Unknown];
199 return contentType;
200 }
141 201
142 public static sbyte ContentTypeToSLAssetType(string contentType) 202 public static sbyte ContentTypeToSLAssetType(string contentType)
143 { 203 {
144 switch (contentType) 204 sbyte assetType;
145 { 205 if (!content2Asset.TryGetValue(contentType, out assetType))
146 case "image/x-j2c": 206 assetType = (sbyte)AssetType.Unknown;
147 case "image/jp2": 207 return (sbyte)assetType;
148 return (sbyte)AssetType.Texture;
149 case "application/ogg":
150 case "audio/ogg":
151 return (sbyte)AssetType.Sound;
152 case "application/vnd.ll.callingcard":
153 case "application/x-metaverse-callingcard":
154 return (sbyte)AssetType.CallingCard;
155 case "application/vnd.ll.landmark":
156 case "application/x-metaverse-landmark":
157 return (sbyte)AssetType.Landmark;
158 case "application/vnd.ll.clothing":
159 case "application/x-metaverse-clothing":
160 return (sbyte)AssetType.Clothing;
161 case "application/vnd.ll.primitive":
162 case "application/x-metaverse-primitive":
163 return (sbyte)AssetType.Object;
164 case "application/vnd.ll.notecard":
165 case "application/x-metaverse-notecard":
166 return (sbyte)AssetType.Notecard;
167 case "application/vnd.ll.folder":
168 return (sbyte)AssetType.Folder;
169 case "application/vnd.ll.rootfolder":
170 return (sbyte)AssetType.RootFolder;
171 case "application/vnd.ll.lsltext":
172 case "application/x-metaverse-lsl":
173 return (sbyte)AssetType.LSLText;
174 case "application/vnd.ll.lslbyte":
175 case "application/x-metaverse-lso":
176 return (sbyte)AssetType.LSLBytecode;
177 case "image/tga":
178 // Note that AssetType.TextureTGA will be converted to AssetType.ImageTGA
179 return (sbyte)AssetType.ImageTGA;
180 case "application/vnd.ll.bodypart":
181 case "application/x-metaverse-bodypart":
182 return (sbyte)AssetType.Bodypart;
183 case "application/vnd.ll.trashfolder":
184 return (sbyte)AssetType.TrashFolder;
185 case "application/vnd.ll.snapshotfolder":
186 return (sbyte)AssetType.SnapshotFolder;
187 case "application/vnd.ll.lostandfoundfolder":
188 return (sbyte)AssetType.LostAndFoundFolder;
189 case "audio/x-wav":
190 return (sbyte)AssetType.SoundWAV;
191 case "image/jpeg":
192 return (sbyte)AssetType.ImageJPEG;
193 case "application/vnd.ll.animation":
194 case "application/x-metaverse-animation":
195 return (sbyte)AssetType.Animation;
196 case "application/vnd.ll.gesture":
197 case "application/x-metaverse-gesture":
198 return (sbyte)AssetType.Gesture;
199 case "application/x-metaverse-simstate":
200 return (sbyte)AssetType.Simstate;
201 case "application/vnd.ll.favoritefolder":
202 return (sbyte)AssetType.FavoriteFolder;
203 case "application/vnd.ll.link":
204 return (sbyte)AssetType.Link;
205 case "application/vnd.ll.linkfolder":
206 return (sbyte)AssetType.LinkFolder;
207 case "application/vnd.ll.currentoutfitfolder":
208 return (sbyte)AssetType.CurrentOutfitFolder;
209 case "application/vnd.ll.outfitfolder":
210 return (sbyte)AssetType.OutfitFolder;
211 case "application/vnd.ll.myoutfitsfolder":
212 return (sbyte)AssetType.MyOutfitsFolder;
213 case "application/octet-stream":
214 default:
215 return (sbyte)AssetType.Unknown;
216 }
217 } 208 }
218 209
219 public static sbyte ContentTypeToSLInvType(string contentType) 210 public static sbyte ContentTypeToSLInvType(string contentType)
220 { 211 {
221 switch (contentType) 212 InventoryType invType;
222 { 213 if (!content2Inventory.TryGetValue(contentType, out invType))
223 case "image/x-j2c": 214 invType = InventoryType.Unknown;
224 case "image/jp2": 215 return (sbyte)invType;
225 case "image/tga": 216 }
226 case "image/jpeg": 217
227 return (sbyte)InventoryType.Texture; 218 public static string SLAssetTypeToExtension(int assetType)
228 case "application/ogg": 219 {
229 case "audio/ogg": 220 string extension;
230 case "audio/x-wav": 221 if (!asset2Extension.TryGetValue((sbyte)assetType, out extension))
231 return (sbyte)InventoryType.Sound; 222 extension = asset2Extension[(sbyte)AssetType.Unknown];
232 case "application/vnd.ll.callingcard": 223 return extension;
233 case "application/x-metaverse-callingcard":
234 return (sbyte)InventoryType.CallingCard;
235 case "application/vnd.ll.landmark":
236 case "application/x-metaverse-landmark":
237 return (sbyte)InventoryType.Landmark;
238 case "application/vnd.ll.clothing":
239 case "application/x-metaverse-clothing":
240 case "application/vnd.ll.bodypart":
241 case "application/x-metaverse-bodypart":
242 return (sbyte)InventoryType.Wearable;
243 case "application/vnd.ll.primitive":
244 case "application/x-metaverse-primitive":
245 return (sbyte)InventoryType.Object;
246 case "application/vnd.ll.notecard":
247 case "application/x-metaverse-notecard":
248 return (sbyte)InventoryType.Notecard;
249 case "application/vnd.ll.folder":
250 return (sbyte)InventoryType.Folder;
251 case "application/vnd.ll.rootfolder":
252 return (sbyte)InventoryType.RootCategory;
253 case "application/vnd.ll.lsltext":
254 case "application/x-metaverse-lsl":
255 case "application/vnd.ll.lslbyte":
256 case "application/x-metaverse-lso":
257 return (sbyte)InventoryType.LSL;
258 case "application/vnd.ll.trashfolder":
259 case "application/vnd.ll.snapshotfolder":
260 case "application/vnd.ll.lostandfoundfolder":
261 return (sbyte)InventoryType.Folder;
262 case "application/vnd.ll.animation":
263 case "application/x-metaverse-animation":
264 return (sbyte)InventoryType.Animation;
265 case "application/vnd.ll.gesture":
266 case "application/x-metaverse-gesture":
267 return (sbyte)InventoryType.Gesture;
268 case "application/x-metaverse-simstate":
269 return (sbyte)InventoryType.Snapshot;
270 case "application/octet-stream":
271 default:
272 return (sbyte)InventoryType.Unknown;
273 }
274 } 224 }
275 225
276 #endregion SL / file extension / content-type conversions 226 #endregion SL / file extension / content-type conversions
@@ -377,4 +327,4 @@ namespace OpenSim.Framework
377 return output; 327 return output;
378 } 328 }
379 } 329 }
380} \ No newline at end of file 330}
diff --git a/OpenSim/Framework/Tests/UtilTest.cs b/OpenSim/Framework/Tests/UtilTest.cs
index 1ca35df..f0d2a3f 100644
--- a/OpenSim/Framework/Tests/UtilTest.cs
+++ b/OpenSim/Framework/Tests/UtilTest.cs
@@ -214,16 +214,13 @@ namespace OpenSim.Framework.Tests
214 214
215 for (int i = 0; i < contenttypes.Length; i++) 215 for (int i = 0; i < contenttypes.Length; i++)
216 { 216 {
217 if (SLUtil.ContentTypeToSLAssetType(contenttypes[i]) == 18) 217 int expected;
218 { 218 if (contenttypes[i] == "image/tga")
219 Assert.That(contenttypes[i] == "image/tga"); 219 expected = 12; // if we know only the content-type "image/tga", then we assume the asset type is TextureTGA; not ImageTGA
220 }
221 else 220 else
222 { 221 expected = assettypes[i];
223 Assert.That(SLUtil.ContentTypeToSLAssetType(contenttypes[i]) == assettypes[i], 222 Assert.AreEqual(expected, SLUtil.ContentTypeToSLAssetType(contenttypes[i]),
224 "Expecting {0} but got {1}", assettypes[i], 223 String.Format("Incorrect AssetType mapped from Content-Type {0}", contenttypes[i]));
225 SLUtil.ContentTypeToSLAssetType(contenttypes[i]));
226 }
227 } 224 }
228 225
229 int[] inventorytypes = new int[] {-1,0,1,2,3,6,7,8,9,10,15,17,18,20}; 226 int[] inventorytypes = new int[] {-1,0,1,2,3,6,7,8,9,10,15,17,18,20};
@@ -237,7 +234,7 @@ namespace OpenSim.Framework.Tests
237 "application/vnd.ll.primitive", 234 "application/vnd.ll.primitive",
238 "application/vnd.ll.notecard", 235 "application/vnd.ll.notecard",
239 "application/vnd.ll.folder", 236 "application/vnd.ll.folder",
240 "application/octet-stream", 237 "application/vnd.ll.rootfolder",
241 "application/vnd.ll.lsltext", 238 "application/vnd.ll.lsltext",
242 "image/x-j2c", 239 "image/x-j2c",
243 "application/vnd.ll.primitive", 240 "application/vnd.ll.primitive",
@@ -247,7 +244,8 @@ namespace OpenSim.Framework.Tests
247 244
248 for (int i=0;i<inventorytypes.Length;i++) 245 for (int i=0;i<inventorytypes.Length;i++)
249 { 246 {
250 Assert.That(SLUtil.SLInvTypeToContentType(inventorytypes[i]) == invcontenttypes[i], "Expected {0}, Got {1}", invcontenttypes[i], SLUtil.SLInvTypeToContentType(inventorytypes[i])); 247 Assert.AreEqual(invcontenttypes[i], SLUtil.SLInvTypeToContentType(inventorytypes[i]),
248 String.Format("Incorrect Content-Type mapped from InventoryType {0}", inventorytypes[i]));
251 } 249 }
252 250
253 invcontenttypes = new string[] 251 invcontenttypes = new string[]
@@ -280,7 +278,8 @@ namespace OpenSim.Framework.Tests
280 278
281 for (int i = 0; i < invtypes.Length; i++) 279 for (int i = 0; i < invtypes.Length; i++)
282 { 280 {
283 Assert.That(SLUtil.ContentTypeToSLInvType(invcontenttypes[i]) == invtypes[i], "Expected {0}, Got {1}", invtypes[i], SLUtil.ContentTypeToSLInvType(invcontenttypes[i])); 281 Assert.AreEqual(invtypes[i], SLUtil.ContentTypeToSLInvType(invcontenttypes[i]),
282 String.Format("Incorrect InventoryType mapped from Content-Type {0}", invcontenttypes[i]));
284 } 283 }
285 } 284 }
286 } 285 }