1 var REST = function()
  2 {
  3 	var REST = {};
  4 	var myResult = [];
  5 	var myHasErrors = false;
  6 	logRequest();
  7 
  8 	//Field PropertyWrappers to collect the version number and the replaced date
  9 	var kReplaceDate = new Property("http://mediabeacon.com/ns/default/1.0/", "replaceDate");
 10 
 11 	/**
 12 	 * the callback for the REST call (savedSelections.js, directories.js, etc)
 13 	 * @type {null}
 14 	 */
 15 	var myCallback = null;
 16 
 17 	/**
 18 	 * All of the parameters given in the request
 19 	 * @type {{}}
 20 	 */
 21 	var myRequestParameters = getParameters();
 22 
 23 	/**
 24 	 * Enable or disable adding data like name, path, height, etc...
 25 	 * @type {boolean}
 26 	 */
 27 	var myVerbose = !!myRequestParameters.verbose ? myRequestParameters.verbose: false;
 28 
 29 	/**
 30 	 * add the mtime to the response if the mtime parameter is set to true
 31 	 * @type {boolean}
 32 	 */
 33 	var myMtime = !!myRequestParameters.mtime ? myRequestParameters.mtime: false;
 34 
 35 	/**
 36 	 * Parameter to collect the document report.
 37 	 * this is slow so we should exclude by default
 38 	 * @type {boolean}
 39 	 */
 40 	var myCollectDocumentReport = !!myRequestParameters.documentLinks ? myRequestParameters.documentLinks: false;
 41 
 42 	/**
 43 	 * Controls whether processing will stop on the first error.  (Default:  true.)
 44 	 * @type {boolean}
 45 	 */
 46 	var myStopOnFirstError = true;
 47 
 48 	/**
 49 	 * Adds an error object to the response
 50 	 *
 51 	 * @param theHttpCode
 52 	 * @param theErrorMessage
 53 	 * @param theException
 54 	 */
 55 	REST.pushError = function(theHttpCode, theErrorMessage, theException)
 56 	{
 57 		// If an error is not provided then we should just make it a 500 error.
 58 		if (!theHttpCode)
 59 		{
 60 			theHttpCode = REST.errors.e500;
 61 		}
 62 
 63 		if (!!theException)
 64 		{
 65 			logger.error(stack(theException));
 66 		}
 67 		myHasErrors = true;
 68 
 69 		// Set the code in the header.
 70 		context.setResponseHeader('status', theHttpCode.code);
 71 
 72 		REST.push(null, {
 73 			error: {
 74 				message: theErrorMessage,
 75 				http: theHttpCode,
 76 			}
 77 		});
 78 	};
 79 
 80 	/**
 81 	 * Returns true if we have encountered an error
 82 	 */
 83 	REST.hasErrors = function()
 84 	{
 85 		return myHasErrors;
 86 	};
 87 
 88 	/**
 89 	 * Push an object into the response
 90 	 */
 91 	REST.push = function(theFileOrFolder, theJSON, theDoFilter)
 92 	{
 93 		if (!!theFileOrFolder)
 94 		{
 95 			theJSON = REST.getInfo(theFileOrFolder, theJSON);
 96 		}
 97 		if (theDoFilter && !!theJSON && !REST.filterMatch(theJSON))
 98 		{
 99 			return;
100 		}
101 		myResult[myResult.length] = theJSON;
102 	};
103 
104 	/**
105 	 * Remove the last added object to myResult.
106 	 * Not commonly used.
107 	 *
108 	 * Helpful for delete because we can add the file/folder to myResult with all of its asset info, then delete it.
109 	 * if we fail to delete the item, we still need to manually pop the object from myResult.
110 	 */
111 	REST.pop = function()
112 	{
113 		myResult.length --;
114 	};
115 
116 	/**
117 	 * Set the callback
118 	 * @param theCallback a function that takes in a managed file and pushes objects to the response object
119 	 */
120 	REST.setCallback = function(theCallback)
121 	{
122 		myCallback = theCallback;
123 	};
124 
125 	/**
126 	 * Sets whether to stop processing the REST call on the first error.  (Default is true.)
127 	 * @param theStop true if so, false if no.
128 	 */
129 	REST.setStopOnFirstError = function (theStop)
130 	{
131 		myStopOnFirstError = theStop;
132 	};
133 
134 	/**
135 	 * Checks whether to stop processing the REST call on the first error.
136 	 * @return theStop true if so, false if no.
137 	 */
138 	REST.getStopOnFirstError = function ()
139 	{
140 		return myStopOnFirstError;
141 	};
142 
143 	/**
144 	 * Executes the callback with the array of asset id's or the resolver url
145 	 */
146 	REST.execute = function(theExecuteOverParameter)
147 	{
148 		try
149 		{
150 			var aResolver = null;
151 
152 			if (!!myRequestParameters.resolver)
153 			{
154 				//Iterate over Resolver
155 				aResolver = myRequestParameters.resolver;
156 				searchManager.searchByResolverUrl(aResolver, context.getUser().userId, errorCheckingCallback);
157 			} else if (!!theExecuteOverParameter)
158 			{
159 				//Iterate over the passed in parameter name
160 				var aValues = myRequestParameters[theExecuteOverParameter];
161 				if (!!aValues)
162 				{
163 					if (!Array.isArray(aValues))
164 					{
165 						aValues = [aValues];
166 					}
167 					for (var i in aValues)
168 					{
169 						errorCheckingCallback(aValues[i]);
170 					}
171 				}
172 			} else if (!!myRequestParameters.ids)
173 			{
174 				//Iterate over asset ids
175 				if (!Array.isArray(myRequestParameters.ids))
176 				{
177 					myRequestParameters.ids = [myRequestParameters.ids];
178 				}
179 				myRequestParameters.ids = searchManager.filterByACL(myRequestParameters.ids);
180 				for (var i in myRequestParameters.ids)
181 				{
182 					errorCheckingCallback(fileManager.getFileObjectById(myRequestParameters.ids[i]));
183 				}
184 			} else
185 			{
186 				//just execute the callback
187 				errorCheckingCallback();
188 			}
189 		} catch (anE)
190 		{
191 			REST.pushError(REST.errors.e500, "Failed to execute.  Check the workflow logs for more information", anE);
192 		} finally {
193 			REST.setStopOnFirstError(true);
194 		}
195 		return REST.formatResponse(myResult);
196 	};
197 
198 	/**
199 	 * Returns a string to be returned from the workflow.
200 	 * Uses JSONP if the "callback" parameter is defined.
201 	 * if the "pretty" parameter is set to true we will format the response with newlines in the JSON
202 	 */
203 	REST.formatResponse = function(theResponseObject)
204 	{
205 		var aResponseString = "";
206 		if (!!myRequestParameters.pretty)
207 		{
208 			aResponseString = JSON.stringify(theResponseObject, null, 2);
209 		} else
210 		{
211 			aResponseString = JSON.stringify(theResponseObject);
212 		}
213 		var aCallback = context.getParameter("callback");
214 		return !!aCallback ? aCallback + "(" + aResponseString + ");" : aResponseString;
215 	};
216 
217 	REST.filterMatch = function(theObject)
218 	{
219 		var anAllowForFilter = ["id", "name", "path", "height", "width", "bytes", "lastModified", "mimeType", "description", "type", "shared", "public", "count"];
220 		for (var aParameter in myRequestParameters)
221 		{
222 			if (anAllowForFilter.indexOf(aParameter) < 0)
223 			{
224 				continue;
225 			}
226 			var aFilterValue = myRequestParameters[aParameter];
227 			var anAssetValue = theObject[aParameter];
228 			if (anAssetValue === undefined)
229 			{
230 				//don't filter on undefined attributes
231 				return false;
232 			}
233 			if (!isNaN(anAssetValue))
234 			{
235 				//number values
236 				if (isNaN(aFilterValue) && (aFilterValue.indexOf(">") == 0 || aFilterValue.indexOf("<") == 0))
237 				{
238 					//Range filter
239 					var aGtLt = aFilterValue.substring(0, 1);
240 					var aNum = parseInt(aFilterValue.substring(1));
241 					if ((aGtLt == ">" && anAssetValue < aNum) || (aGtLt == "<" && anAssetValue > aNum))
242 					{
243 						return false;
244 					}
245 				} else if (anAssetValue != aFilterValue)
246 				{
247 					return false;
248 				}
249 			} else
250 			{
251 				if (!!aFilterValue && !!anAssetValue)
252 				{
253 					if (aFilterValue.toString().indexOf("*") >= 0)
254 					{
255 						var aRegEx = new RegExp("^" + aFilterValue.split("*").join(".*")+ "$");
256 						if (!aRegEx.test(anAssetValue))
257 						{
258 							return false;
259 						}
260 					} else if (anAssetValue != aFilterValue)
261 					{
262 						return false;
263 					}
264 				}
265 			}
266 
267 		}
268 		return true;
269 	};
270 
271 	/**
272 	 * Gets the standard asset info given an array of asset ids
273 	 * @param theAssetIds
274 	 */
275 	REST.getAssetInfo = function(theAssetIds)
276 	{
277 		var anAssetInfo = [];
278 		for (var i in theAssetIds)
279 		{
280 			var anAsset = fileManager.getFileObjectById(theAssetIds[i]);
281 			if (!!anAsset)
282 			{
283 				anAssetInfo.push(REST.getInfo(anAsset, {}));
284 			} else {
285 				logger.config("REST.getAssetInfo() asset doesn't exist by id: " + theAssetIds[i]);
286 			}
287 		}
288 		return anAssetInfo;
289 	};
290 
291 	/**
292 	 * returns the acl relative path given the MB relative path
293 	 * @param theFullPath
294 	 * @returns {string|void|*|XML}
295 	 */
296 	REST.getACLRelativePath = function(theFullPath)
297 	{
298 		var aUsersRootPath  = context.getACL().getRootPath();
299 		if (aUsersRootPath == null && aUsersRootPath == "")
300 		{
301 			var aUsersAcls = context.getUser().getPrimaryGroup().getACLs();
302 			if (aUsersAcls.length <= 0)
303 			{
304 				aUsersRootPath = null;
305 			} else
306 			{
307 				aUsersRootPath = aUsersAcls[0].getRootPath();
308 			}
309 		}
310 		if (aUsersRootPath == null)
311 		{
312 			throw "Couldn't find ACL for current user";
313 		}
314 		var aPath = theFullPath.replace(aUsersRootPath, "");
315 		return aPath == "" ? "/" : aPath;
316 	};
317 
318 	/**
319 	 * Adds the acl root path to thePath if the user is in a subroot acl
320 	 * @param thePath
321 	 * @returns {*}
322 	 */
323 	REST.getFullPath = function(thePath)
324 	{
325 		thePath = !thePath ? "" : thePath;
326 		var aPath = context.getACL().getRootPath() + thePath;
327 		//normalize any paths like Assets//test/ to Assets/test/
328 		aPath = aPath.split("//").join("/");
329 		return aPath;
330 	};
331 
332 	/**
333 	 * Is file?
334 	 *
335 	 * @param theFile the file to check
336 	 */
337 	REST.isFile = function (theFile)
338 	{
339 		return fileManager.isFile(theFile.path) || theFile instanceof UnmanagedFile;
340 	};
341 
342 	/**
343 	 * Returns the apikey request parameter and value in string form
344 	 * @returns {string}
345 	 */
346 	REST.getAuthParam = function()
347 	{
348 		return "apikey=" + apiKeyManager.getOrCreateApiKey("", context.getUser().username) + "&acl_id=" + context.getACL().id;
349 	};
350 
351 	/**
352 	 * Given a field id like "http://purl.org/dc/elements/1.1/ subject" or "database record_id" or "record_id"
353 	 * @param theFieldId
354 	 * @returns {Property}
355 	 */
356 	REST.getProperty = function(theFieldId)
357 	{
358 		try
359 		{
360 			if (theFieldId.indexOf(" ") < 0)
361 			{
362 				//assume its a DB field
363 				return new Property("database", theFieldId);
364 			} else
365 			{
366 				var aFieldSet = theFieldId.split(' ');
367 				return new Property(aFieldSet[0], aFieldSet[1]);
368 			}
369 		} catch (anE)
370 		{
371 			REST.pushError(REST.errors.e404, "Failed to find the field for the field ID: " + theFieldId, anE);
372 			return null;
373 		}
374 	};
375 
376 	/**
377 	 * Call another REST workflow with the parameters
378 	 * @param theWorkflowName
379 	 * @param theParameters
380 	 */
381 	REST.callRESTWorkflow = function(theWorkflowName, theParameters)
382 	{
383 		var aParameters = new Parameters();
384 		if (!!myRequestParameters["verbose"])
385 		{
386 			aParameters.put("verbose", myRequestParameters["verbose"]);
387 		}
388 		if (!!myRequestParameters["fields"])
389 		{
390 			aParameters.put("fields", myRequestParameters["fields"]);
391 		}
392 		for (var aParam in theParameters)
393 		{
394 			aParameters.put(aParam, JSON.stringify(theParameters[aParam]));
395 		}
396 		var aWorkflow = new Workflow("Renditions/Workflows/_internal/restapi/v2/" + theWorkflowName + ".xmpwf");
397 		var aResponse = aWorkflow.trigger(aParameters);
398 		try
399 		{
400 			return JSON.parse(aResponse);
401 		} catch(anE)
402 		{
403 			return aResponse;
404 		}
405 	};
406 
407 	REST.AssetTriggers = Object.freeze({
408 		Modified: "asset modified",
409 		Added: "asset added",
410 		Removed: "asset removed",
411 		Downloaded: "asset downloaded"
412 	});
413 
414 	REST.triggerAssetBasedWorkflows = function(theType, theFile, theModificationsIfAny)
415 	{
416 		var aStub = {};
417 		if (!context.getParameter("triggerAssetBasedWorkflow", true))
418 		{
419 			return false;
420 		}
421 
422 		aStub.ok = false;
423 		aStub.type = theType;
424 
425 		switch (theType)
426 		{
427 			case REST.AssetTriggers.Modified:
428 				workflowManager.triggerAssetModified(theFile, theModificationsIfAny);
429 				aStub.ok = true;
430 				aStub.changes = theModificationsIfAny;
431 				break;
432 			case REST.AssetTriggers.Added:
433 				workflowManager.triggerAssetAdded(theFile);
434 				aStub.ok = true;
435 				break;
436 			case REST.AssetTriggers.Removed:
437 				workflowManager.triggerAssetRemoved(theFile);
438 				aStub.ok = true;
439 				break;
440 			case REST.AssetTriggers.Downloaded:
441 				workflowManager.triggerAssetDownloaded(theFile);
442 				aStub.ok = true;
443 				break;
444 		}
445 
446 		return aStub;
447 	};
448 
449 	REST.addToChangeList = function(theChangeList, theProperty, theOld, theNew)
450 	{
451 		theChangeList[theProperty.fieldId] = {
452 			"old": typeof(theOld) === "object" ? theOld : theOld.toString(),
453 			"new": typeof(theNew) === "object" ? theNew : theNew.toString(),
454 			"type": theProperty.getFieldType()
455 		};
456 
457 		return theChangeList;
458 	};
459 
460 	REST.formatDiscussionList = function(theDiscussionSet, theLimit, theOrder)
461 	{
462 		var aFormattedList = [];
463 
464 		if (theDiscussionSet != null)
465 		{
466 			// Set the limit if it's too large.
467 			if (theLimit && theLimit > theDiscussionSet.length)
468 			{
469 				theLimit = theDiscussionSet.length;
470 			}
471 
472 			// Set the start: either 0 or the end of the array.
473 			var aStartIndex = theOrder === 'desc' ? theDiscussionSet.length - 1 : 0;
474 
475 			// Pick where to stop: either the limit requested or the discussion set length or 0, depending on the order.
476 			var aLimit = !isNaN(theLimit) ? theLimit : theDiscussionSet.length;
477 
478 			// Set the actual array index.
479 			var aPlacementIndex = 0;
480 
481 			// Loop through them and add a useful item to the array.
482 			while (true)
483 			{
484 				aFormattedList[aPlacementIndex] = {};
485 
486 				// Get the sub entries in the discussion.
487 				var aSubFields = theDiscussionSet.getItemAt(aStartIndex).getFields();
488 
489 				// Loop through all the sub entry's fields and place them in the appropriate array.
490 				for (var j = 0; j < aSubFields.length; j++)
491 				{
492 					aFormattedList[aPlacementIndex][aSubFields[j].name] = theDiscussionSet.getItemAt(aStartIndex).getField(aSubFields[j]).toString()
493 				}
494 
495 				aPlacementIndex++;
496 
497 				// Descending order.
498 				aLimit--;
499 				if (aLimit <= 0)
500 				{
501 					break;
502 				}
503 				if (theOrder === 'desc')
504 				{
505 					aStartIndex--;
506 					if (aStartIndex < 0)
507 					{
508 						break;
509 					}
510 				} else
511 				{
512 					aStartIndex++;
513 					if (aStartIndex > theDiscussionSet.length - 1)
514 					{
515 						break;
516 					}
517 				}
518 			}
519 		}
520 
521 		return aFormattedList;
522 	};
523 	/**
524 	 * Camelize the string for REST API Response element
525 	 * @param str
526 	 *
527 	 */
528 	function camelize(str) {
529 		return str
530 			.replace(/(?:^\w|[A-Z]|\b\w)/g, function(word, index) {
531 				return index === 0 ? word.toLowerCase() : word.toUpperCase();
532 			})
533 			.replace(/\s+/g, "");
534 	}
535 	/**
536 	 * Adds the standard response data requested by the user
537 	 * @param theFileOrFolder
538 	 * @param theJSON
539 	 */
540 	REST.getInfo = function(theFileOrFolder, theJSON)
541 	{
542 		logger.fine("file or folder: " + theFileOrFolder + " " + theJSON);
543 		theJSON = !theJSON ? {} : theJSON;
544 		if (fileManager.isFile(theFileOrFolder.path))
545 		{
546 			theJSON.id = theFileOrFolder.assetId;
547 			if (myVerbose)
548 			{
549 				theJSON.name = theFileOrFolder.name;
550 				theJSON.path = REST.getACLRelativePath(theFileOrFolder.path);
551 				theJSON.directoryId = theFileOrFolder.parent.directoryId;
552 				theJSON.height = theFileOrFolder.height;
553 				theJSON.width = theFileOrFolder.width;
554 				theJSON.bytes = theFileOrFolder.fileSizeIncludingMetadata;
555 				theJSON.lastModified = theFileOrFolder.lastModified;
556 				if (!!theFileOrFolder.fileNameExtension || !!kMimeMap[theFileOrFolder.fileNameExtension.toLowerCase()])
557 				{
558 					theJSON.mimeType = kMimeMap[theFileOrFolder.fileNameExtension.toLowerCase()];
559 				} else
560 				{
561 					logger.error("Failed to find a mimeType for the file extension: " + theFileOrFolder.fileNameExtension);
562 				}
563 				theJSON.previews = {};
564 				theJSON.previews.thumbnail = theFileOrFolder.getImageURL("thumbnails").replace("..", context.getServerURL());
565 				theJSON.previews.viewex = theFileOrFolder.getImageURL("viewex").replace("..", context.getServerURL());
566 				theJSON.previews.high = theFileOrFolder.getImageURL("high").replace("..", context.getServerURL());
567 				theJSON.previews.downloadUrl = context.getServerURL() + "/servlet/dload/" + theFileOrFolder.name + "?id=" + theFileOrFolder.encodedAssetId;
568  				var renditionList = theFileOrFolder.getAwsRenditionKeyDataList;
569 
570 				if (renditionList != null) {
571 					var renditionListArray= Array.from(renditionList);
572 					var renditionURL = theFileOrFolder.getExternalPortalRenditionUrl;
573 					theJSON.publishedRenditions = {};
574 
575 					var presetKey;
576 					for (var i = 0; i < renditionListArray.length; i++) {
577 						currentKeyValue = renditionListArray[i];
578 						rendtionKeyValueArray = currentKeyValue.split(":");
579 						presetKey = camelize(rendtionKeyValueArray[0].replace(/ /g,''));
580 						theJSON.publishedRenditions[presetKey] = renditionURL + rendtionKeyValueArray[1];
581 					}
582 
583 				}
584 				theJSON.replaceDate = theFileOrFolder.xmp.meta.getField(kReplaceDate);
585 				theJSON.replaceDate = !!theJSON.replaceDate ? parseInt(theJSON.replaceDate) : 0;
586 				var aVersionNumber = versionManager.getVersionCount(
587 					theFileOrFolder.assetId,
588 					"",
589 					["Named"]
590 				);
591 				theJSON.versionNumber = !aVersionNumber || isNaN(aVersionNumber) ? 0 : parseInt(aVersionNumber);
592 				var aVersionAssets = versionManager.getVersions(
593 					theFileOrFolder.assetId,
594 					["Named"],
595 					aVersionNumber
596 				);
597 				if (!!aVersionAssets && aVersionAssets.length > 0)
598 				{
599 					var aVersionIds = [];
600 					for (var i = 0; i < aVersionAssets.length; i++)
601 					{
602 						var aVersionAsset = aVersionAssets[i];
603 						aVersionIds.push(aVersionAsset.assetId);
604 					}
605 					theJSON.versionIds = aVersionIds;
606 				}
607 			}
608 
609 			if (myCollectDocumentReport)
610 			{
611 				var anExt = theFileOrFolder.fileNameExtension;
612 				if (anExt == "indd" || anExt == "qxd" || anExt == "ai")
613 				{
614 					//check for linked assets
615 					theJSON.documentLinks = [];
616 					var aLinks = linkManager.getEmbeddedFiles(theFileOrFolder);
617 					for (var i in aLinks)
618 					{
619 						var aLink = aLinks[i];
620 						theJSON.documentLinks[theJSON.documentLinks.length] = REST.getInfo(aLink.getManagedFile(), {
621 							linkPath: aLink.filePath,
622 						});
623 					}
624 				}
625 			}
626 
627 			if (myMtime)
628 			{
629 				//mtime from the db. More specific than lastModified.
630 				theJSON.mtime = new SQL().queryForString("SELECT xmp_modification_db FROM editorial WHERE record_id = " + theJSON.id);
631 			}
632 
633 			//Get fields if they were provided
634 			if (!!myRequestParameters.fields && myRequestParameters.fields.length > 0)
635 			{
636 				theJSON.fields = {};
637 				var aFields = !Array.isArray(myRequestParameters.fields) ? [myRequestParameters.fields] : myRequestParameters.fields;
638 				for (var i = 0; i < aFields.length; i++)
639 				{
640 					var aFieldId = aFields[i];
641 					if (!fieldManager.canView(aFieldId, context.getUser().getViewLevel()))
642 					{
643 						logger.warning("Cannot view: " + aFieldId);
644 						continue;
645 					}
646 					var aProp = REST.getProperty(aFieldId);
647 					var aVal;
648 					if (aProp.namespace === 'database')
649 					{
650 						aVal = theFileOrFolder[aProp.name];
651 						if (aVal == null)
652 						{
653 							aVal = theFileOrFolder.getDatabaseField(aProp.name);
654 						}
655 					} else
656 					{
657 						aVal = theFileOrFolder.xmp.meta.getField(aProp);
658 						if (aVal instanceof Collection)
659 						{
660 							var aJSONVal = [];
661 							var anIterator = aVal.iterator;
662 							while (anIterator.hasMore)
663 							{
664 								var aBlock = anIterator.next;
665 								if (aBlock instanceof Resource)
666 								{
667 									//Build data block as a JSON object.
668 									var aJSONBlock = {};
669 									var aProperties = aBlock.getFields();
670 									for (var k in aProperties)
671 									{
672 										var aProperty = aProperties[k];
673 										var aBlockVal = aBlock.getField(aProperty);
674 										if (aBlockVal instanceof Collection)
675 										{
676 											aBlockVal = JSON.parse(aBlockVal);
677 										}
678 										aJSONBlock[aProperty.fieldId] = aBlockVal;
679 									}
680 									aJSONVal[aJSONVal.length] = aJSONBlock;
681 								} else
682 								{
683 									aJSONVal[aJSONVal.length] = aBlock;
684 								}
685 							}
686 							aVal = aJSONVal;
687 						}
688 					}
689 					theJSON.fields[aFieldId] = aVal;
690 				}
691 			}
692 		} else if (fileManager.isFolder(theFileOrFolder.path))
693 		{
694 			theJSON = REST.buildFolderObject(theFileOrFolder, REST.getACLRelativePath(theFileOrFolder.path), false);
695 		}
696 
697 		return theJSON;
698 	};
699 
700 	/**
701 	 * Gets all of the Parameters from the request and their values
702 	 * @returns {{}}
703 	 */
704 	function getParameters()
705 	{
706 		var aToIgnore = ["request.headers", "workflow.url.path"];
707 		var aRequestParameters = {};
708 		var aParameters = context.getParameterNames();
709 		for (var i in aParameters)
710 		{
711 			var aParamName = aParameters[i];
712 			var aParamVal = context.getParameter(aParamName);
713 			if (aToIgnore.indexOf(aParameters[i]) >= 0)
714 			{
715 				continue;
716 			}
717 			if (aParamName.indexOf("MBUploadedFile") >= 0)
718 			{
719 				//looks like we found our selves an uploaded file
720 				//add it back as its original name
721 				var anOriginal = aParamName.split("MBUploadedFile").join("");
722 				var aFileObject = context.getParameter(anOriginal);
723 				aRequestParameters[anOriginal] = {
724 					"isFile" : true,
725 					"name" : aFileObject.name,
726 					"length" : aFileObject.length
727 				}
728 			} else
729 			{
730 				aRequestParameters[aParamName] = aParamVal;
731 			}
732 		}
733 		return aRequestParameters;
734 	}
735 
736 	/**
737 	 * Formats the exception
738 	 * @param theE
739 	 * @returns {string}
740 	 */
741 	function stack(theE)
742 	{
743 		return theE + (!!theE.stack ? "\n" + theE.stack : "");
744 	}
745 
746 	/**
747 	 * executes myCallback if we haven't encountered an error already.
748 	 * @param theCallbackParameter
749 	 */
750 	function errorCheckingCallback(theCallbackParameter)
751 	{
752 		if (REST.getStopOnFirstError() && REST.hasErrors())
753 		{
754 			return;
755 		} else
756 		{
757 			try
758 			{
759 				if (!!myCallback)
760 				{
761 					myCallback(theCallbackParameter);
762 				}
763 			} catch (anE)
764 			{
765 				var aParam = !!theCallbackParameter ? theCallbackParameter : "";
766 				aParam = !!aParam.name ? aParam.name : (typeof aParam === 'object' ? JSON.stringify(aParam) : aParam.toString());
767 				REST.pushError(REST.errors.e500, "Failed to execute " + myCallback.name + "(" + (!aParam ? "" : "'" + aParam + "'") + ");", anE);
768 			}
769 		}
770 	}
771 
772 	/**
773 	 * Logs the request made to the REST workflow
774 	 */
775 	function logRequest()
776 	{
777 		var aToIgnore = ["request.headers"];
778 		var aToLog = {};
779 		var aParameters = context.getParameterNames();
780 		for (var i in aParameters)
781 		{
782 			var aParamName = aParameters[i];
783 			var aParamVal = context.getParameter(aParamName);
784 			if (aToIgnore.indexOf(aParameters[i]) >= 0)
785 			{
786 				continue;
787 			}
788 			if (aParamName.indexOf("MBUploadedFile") >= 0)
789 			{
790 				//looks like we found our selves an uploaded file
791 				//add it back as its original name
792 				var anOriginal = aParamName.split("MBUploadedFile").join("");
793 				var aFileObject = context.getParameter(anOriginal);
794 				aToLog[anOriginal] = {
795 					"isFile" : true,
796 					"name" : aFileObject.name,
797 					"length" : aFileObject.length
798 				}
799 			} else
800 			{
801 				aToLog[aParamName] = aParamVal;
802 			}
803 		}
804 		logger.config("REST API request parameters:\n " + JSON.stringify(aToLog, null, 2));
805 	}
806 
807 	/**
808 	 * Executes a search with the parameters the pageSize, pageNumber, sortDirection, and sortField
809 	 * @param theSearch
810 	 * @param theCallback the search callback
811 	 */
812 	REST.executeSearchWithPaging = function(theSearch)
813 	{
814 		var aPageSize = myRequestParameters["pageSize"];
815 		var aPageNumber = myRequestParameters["pageIndex"];
816 		var aSortDirection = myRequestParameters["sortDirection"];
817 		var aSortField = myRequestParameters["sortField"];
818 		if (!!aSortDirection && !!aSortField)
819 		{
820 			theSearch.setSortDirection(aSortDirection);
821 			theSearch.setSortField(aSortField);
822 		}
823 		aPageSize = !aPageSize ? 100 : aPageSize;
824 		aPageNumber = !aPageNumber ? 0 : aPageNumber;
825 		return theSearch.executeForArray(aPageNumber, aPageSize)
826 	};
827 
828 	REST.isVerbose = function()
829 	{
830 		return myVerbose;
831 	};
832 
833 	/**
834 	 * Initializes the JSON object for the response
835 	 * @param theFolder
836 	 * @returns {{name: *, path: (string|void|*|XML), id: *, parentId: *, resolver: string, assets: *}}
837 	 */
838 	REST.buildFolderObject = function(theFolder)
839 	{
840 		var anAclPath = REST.getACLRelativePath(theFolder.path);
841 		var aIsRoot = "/" === anAclPath;
842 		var aFolder = {
843 			"path": anAclPath,
844 			"id": theFolder.directoryId,
845 			"parentId": aIsRoot ? undefined : theFolder.parent.directoryId,
846 		};
847 		if (REST.isVerbose())
848 		{
849 			Object.assign(aFolder, {
850 				"name" : aIsRoot ? "Index": theFolder.name,
851 				"resolver" : "directory://" + theFolder.directoryId,
852 			});
853 		}
854 		return aFolder;
855 	};
856 
857 	/**
858 	 * Gets an array of paths of all of the directories in this acl
859 	 * @param theFolder
860 	 * @param theDepth
861 	 * @param theParentJSON
862 	 * @param theIsHierarchy return a JSON data structure with children folders nested in other folders
863 	 * @returns {Array} flat list of all found directories.
864 	 */
865 	REST.getChildDirectories = function(theFolder, theDepth, theIsHierarchy, theParentJSON)
866 	{
867 		theParentJSON = !!theParentJSON ? theParentJSON : REST.buildFolderObject(theFolder);
868 		var aAllChildren = [];
869 		if (theDepth != 0) //-1 should find all children directories
870 		{
871 			var aChildren = theFolder.children;
872 			if (theIsHierarchy)
873 			{
874 				theParentJSON.children = [];
875 			}
876 			for (var i in aChildren)
877 			{
878 				var aChild = aChildren[i];
879 				if (aChild.path === "Renditions/")
880 				{
881 					continue;
882 				}
883 				var aChildJSON = REST.buildFolderObject(aChild);
884 				if (theIsHierarchy)
885 				{
886 					theParentJSON.children.push(aChildJSON);
887 				}
888 				aAllChildren.push(aChildJSON);
889 				var aGrandChildren = REST.getChildDirectories(aChild, theDepth - 1, theIsHierarchy, aChildJSON);
890 				aAllChildren.push.apply(aAllChildren, aGrandChildren);
891 			}
892 		} else if (theFolder.children.length > 0)
893 		{
894 			theParentJSON.hasChildren = true;
895 		}
896 		return aAllChildren;
897 	};
898 
899 	/**
900 	 * Get facets as a JSON array from solr.
901 	 *
902 	 * @param theFieldId the field id
903 	 * @param thePageSize the page size
904 	 * @param theIncludedSearch the included search
905 	 * @param theHierarchyLevel the hierarchy level
906 	 * @param thePageNumber the page number
907 	 * @returns {Array}
908 	 */
909 	REST.getFacets = function(theFieldId, thePageSize, theIncludedSearch, theHierarchyLevel, thePageNumber)
910 	{
911 		theFieldId = theFieldId.replace("database ", "");
912 		var aSearch = !!theIncludedSearch ? theIncludedSearch : new Search();
913 		var aSolrConfig = new SolrConfig();
914 
915 		aSolrConfig.addFacetField(theFieldId);
916 		aSolrConfig.setNumberResults(theFieldId, thePageSize);
917 		aSolrConfig.setHierarchyLevel(theFieldId, !!theHierarchyLevel ? theHierarchyLevel : 0);
918 
919 		//Return a facet map from the search
920 		var aResults = [];
921 		var aFacet = aSearch.getTermsWithLimit(
922 			aSolrConfig,
923 			!!thePageNumber ? thePageNumber : 0,
924 			!!thePageSize ? thePageSize : 1000
925 		);
926 		if (!!aFacet)
927 		{
928 			var aFacetFieldId = aFacet.getFieldId();
929 			if (aFacetFieldId == theFieldId)
930 			{
931 				for (var i = 0; i < aFacet.size(); i++)
932 				{
933 					var aFacetLabel = aFacet.getValue(i).getLabel();
934 					if (aFacetLabel != "MBFacetMissing")
935 					{
936 						aResults[aResults.length] = {
937 							value: aFacetLabel,
938 							count: aFacet.getValue(i).getCount(),
939 							raw: aFacet.getValue(i).getRawLabel()
940 						};
941 					}
942 				}
943 			}
944 		}
945 		return aResults;
946 	};
947 
948 	REST.errors = {
949 		// 400
950 		e400: {name: "Bad Request", code: 400},
951 		e401: {name: "Unauthorized", code: 401},
952 		e403: {name: "Forbidden", code: 403},
953 		e404: {name: "Not Found", code: 404},
954 		e405: {name: "Method Not Allowed", code: 405},
955 		e406: {name: "Not Acceptable", code: 406},
956 		e409: {name: "Conflict", code: 409},
957 
958 		// 500
959 		e500: {name: "Internal Server Error", code: 500},
960 	};
961 
962 	return REST;
963 };
964 
965 
966 /**
967  * ext to mime type mapping
968  */
969 var kMimeMap = {
970 	"x3d":"application/vnd.hzn-3d-crossword",
971 	"3gp":"video/3gpp",
972 	"3g2":"video/3gpp2",
973 	"mseq":"application/vnd.mseq",
974 	"pwn":"application/vnd.3m.post-it-notes",
975 	"plb":"application/vnd.3gpp.pic-bw-large",
976 	"psb":"application/vnd.3gpp.pic-bw-small",
977 	"pvb":"application/vnd.3gpp.pic-bw-var",
978 	"tcap":"application/vnd.3gpp2.tcap",
979 	"7z":"application/x-7z-compressed",
980 	"abw":"application/x-abiword",
981 	"ace":"application/x-ace-compressed",
982 	"acc":"application/vnd.americandynamics.acc",
983 	"acu":"application/vnd.acucobol",
984 	"atc":"application/vnd.acucorp",
985 	"adp":"audio/adpcm",
986 	"aab":"application/x-authorware-bin",
987 	"aam":"application/x-authorware-map",
988 	"aas":"application/x-authorware-seg",
989 	"air":"application/vnd.adobe.air-application-installer-package+zip",
990 	"swf":"application/x-shockwave-flash",
991 	"fxp":"application/vnd.adobe.fxp",
992 	"pdf":"application/pdf",
993 	"ppd":"application/vnd.cups-ppd",
994 	"dir":"application/x-director",
995 	"xdp":"application/vnd.adobe.xdp+xml",
996 	"xfdf":"application/vnd.adobe.xfdf",
997 	"aac":"audio/x-aac",
998 	"ahead":"application/vnd.ahead.space",
999 	"azf":"application/vnd.airzip.filesecure.azf",
1000 	"azs":"application/vnd.airzip.filesecure.azs",
1001 	"azw":"application/vnd.amazon.ebook",
1002 	"ami":"application/vnd.amiga.ami",
1003 	"apk":"application/vnd.android.package-archive",
1004 	"cii":"application/vnd.anser-web-certificate-issue-initiation",
1005 	"fti":"application/vnd.anser-web-funds-transfer-initiation",
1006 	"atx":"application/vnd.antix.game-component",
1007 	"dmg":"application/x-apple-diskimage",
1008 	"mpkg":"application/vnd.apple.installer+xml",
1009 	"aw":"application/applixware",
1010 	"les":"application/vnd.hhe.lesson-player",
1011 	"swi":"application/vnd.aristanetworks.swi",
1012 	"s":"text/x-asm",
1013 	"atomcat":"application/atomcat+xml",
1014 	"atomsvc":"application/atomsvc+xml",
1015 	"atom":"application/atom+xml",
1016 	"xml":"application/atom+xml",
1017 	"ac":"application/pkix-attr-cert",
1018 	"aif":"audio/x-aiff",
1019 	"avi":"video/x-msvideo",
1020 	"aep":"application/vnd.audiograph",
1021 	"dxf":"image/vnd.dxf",
1022 	"dwf":"model/vnd.dwf",
1023 	"par":"text/plain-bas",
1024 	"bcpio":"application/x-bcpio",
1025 	"bin":"application/octet-stream",
1026 	"bmp":"image/bmp",
1027 	"torrent":"application/x-bittorrent",
1028 	"cod":"application/vnd.rim.cod",
1029 	"mpm":"application/vnd.blueice.multipass",
1030 	"bmi":"application/vnd.bmi",
1031 	"sh":"application/x-sh",
1032 	"btif":"image/prs.btif",
1033 	"rep":"application/vnd.businessobjects",
1034 	"bz":"application/x-bzip",
1035 	"bz2":"application/x-bzip2",
1036 	"csh":"application/x-csh",
1037 	"c":"text/x-c",
1038 	"cdxml":"application/vnd.chemdraw+xml",
1039 	"css":"text/css",
1040 	"cdx":"chemical/x-cdx",
1041 	"cml":"chemical/x-cml",
1042 	"csml":"chemical/x-csml",
1043 	"cdbcmsg":"application/vnd.contact.cmsg",
1044 	"cla":"application/vnd.claymore",
1045 	"c4g":"application/vnd.clonk.c4group",
1046 	"sub":"image/vnd.dvb.subtitle",
1047 	"cdmia":"application/cdmi-capability",
1048 	"cdmic":"application/cdmi-container",
1049 	"cdmid":"application/cdmi-domain",
1050 	"cdmio":"application/cdmi-object",
1051 	"cdmiq":"application/cdmi-queue",
1052 	"c11amc":"application/vnd.cluetrust.cartomobile-config",
1053 	"c11amz":"application/vnd.cluetrust.cartomobile-config-pkg",
1054 	"ras":"image/x-cmu-raster",
1055 	"dae":"model/vnd.collada+xml",
1056 	"csv":"text/csv",
1057 	"cpt":"application/mac-compactpro",
1058 	"wmlc":"application/vnd.wap.wmlc",
1059 	"cgm":"image/cgm",
1060 	"ice":"x-conference/x-cooltalk",
1061 	"cmx":"image/x-cmx",
1062 	"xar":"application/vnd.xara",
1063 	"cmc":"application/vnd.cosmocaller",
1064 	"cpio":"application/x-cpio",
1065 	"clkx":"application/vnd.crick.clicker",
1066 	"clkk":"application/vnd.crick.clicker.keyboard",
1067 	"clkp":"application/vnd.crick.clicker.palette",
1068 	"clkt":"application/vnd.crick.clicker.template",
1069 	"clkw":"application/vnd.crick.clicker.wordbank",
1070 	"wbs":"application/vnd.criticaltools.wbs+xml",
1071 	"cryptonote":"application/vnd.rig.cryptonote",
1072 	"cif":"chemical/x-cif",
1073 	"cmdf":"chemical/x-cmdf",
1074 	"cu":"application/cu-seeme",
1075 	"cww":"application/prs.cww",
1076 	"curl":"text/vnd.curl",
1077 	"dcurl":"text/vnd.curl.dcurl",
1078 	"mcurl":"text/vnd.curl.mcurl",
1079 	"scurl":"text/vnd.curl.scurl",
1080 	"car":"application/vnd.curl.car",
1081 	"pcurl":"application/vnd.curl.pcurl",
1082 	"cmp":"application/vnd.yellowriver-custom-menu",
1083 	"dssc":"application/dssc+der",
1084 	"xdssc":"application/dssc+xml",
1085 	"deb":"application/x-debian-package",
1086 	"uva":"audio/vnd.dece.audio",
1087 	"uvi":"image/vnd.dece.graphic",
1088 	"uvh":"video/vnd.dece.hd",
1089 	"uvm":"video/vnd.dece.mobile",
1090 	"uvu":"video/vnd.uvvu.mp4",
1091 	"uvp":"video/vnd.dece.pd",
1092 	"uvs":"video/vnd.dece.sd",
1093 	"uvv":"video/vnd.dece.video",
1094 	"dvi":"application/x-dvi",
1095 	"seed":"application/vnd.fdsn.seed",
1096 	"dtb":"application/x-dtbook+xml",
1097 	"res":"application/x-dtbresource+xml",
1098 	"ait":"application/vnd.dvb.ait",
1099 	"svc":"application/vnd.dvb.service",
1100 	"eol":"audio/vnd.digital-winds",
1101 	"djvu":"image/vnd.djvu",
1102 	"dtd":"application/xml-dtd",
1103 	"mlp":"application/vnd.dolby.mlp",
1104 	"wad":"application/x-doom",
1105 	"dpg":"application/vnd.dpgraph",
1106 	"dra":"audio/vnd.dra",
1107 	"dfac":"application/vnd.dreamfactory",
1108 	"dts":"audio/vnd.dts",
1109 	"dtshd":"audio/vnd.dts.hd",
1110 	"dwg":"image/vnd.dwg",
1111 	"geo":"application/vnd.dynageo",
1112 	"es":"application/ecmascript",
1113 	"mag":"application/vnd.ecowin.chart",
1114 	"mmr":"image/vnd.fujixerox.edmics-mmr",
1115 	"rlc":"image/vnd.fujixerox.edmics-rlc",
1116 	"exi":"application/exi",
1117 	"mgz":"application/vnd.proteus.magazine",
1118 	"epub":"application/epub+zip",
1119 	"eml":"message/rfc822",
1120 	"nml":"application/vnd.enliven",
1121 	"xpr":"application/vnd.is-xpr",
1122 	"xif":"image/vnd.xiff",
1123 	"xfdl":"application/vnd.xfdl",
1124 	"emma":"application/emma+xml",
1125 	"ez2":"application/vnd.ezpix-album",
1126 	"ez3":"application/vnd.ezpix-package",
1127 	"fst":"image/vnd.fst",
1128 	"fvt":"video/vnd.fvt",
1129 	"fbs":"image/vnd.fastbidsheet",
1130 	"fe_launch":"application/vnd.denovo.fcselayout-link",
1131 	"f4v":"video/x-f4v",
1132 	"flv":"video/x-flv",
1133 	"fpx":"image/vnd.fpx",
1134 	"npx":"image/vnd.net-fpx",
1135 	"flx":"text/vnd.fmi.flexstor",
1136 	"fli":"video/x-fli",
1137 	"ftc":"application/vnd.fluxtime.clip",
1138 	"fdf":"application/vnd.fdf",
1139 	"f":"text/x-fortran",
1140 	"mif":"application/vnd.mif",
1141 	"fm":"application/vnd.framemaker",
1142 	"fh":"image/x-freehand",
1143 	"fsc":"application/vnd.fsc.weblaunch",
1144 	"fnc":"application/vnd.frogans.fnc",
1145 	"ltf":"application/vnd.frogans.ltf",
1146 	"ddd":"application/vnd.fujixerox.ddd",
1147 	"xdw":"application/vnd.fujixerox.docuworks",
1148 	"xbd":"application/vnd.fujixerox.docuworks.binder",
1149 	"oas":"application/vnd.fujitsu.oasys",
1150 	"oa2":"application/vnd.fujitsu.oasys2",
1151 	"oa3":"application/vnd.fujitsu.oasys3",
1152 	"fg5":"application/vnd.fujitsu.oasysgp",
1153 	"bh2":"application/vnd.fujitsu.oasysprs",
1154 	"spl":"application/x-futuresplash",
1155 	"fzs":"application/vnd.fuzzysheet",
1156 	"g3":"image/g3fax",
1157 	"gmx":"application/vnd.gmx",
1158 	"gtw":"model/vnd.gtw",
1159 	"txd":"application/vnd.genomatix.tuxedo",
1160 	"ggb":"application/vnd.geogebra.file",
1161 	"ggt":"application/vnd.geogebra.tool",
1162 	"gdl":"model/vnd.gdl",
1163 	"gex":"application/vnd.geometry-explorer",
1164 	"gxt":"application/vnd.geonext",
1165 	"g2w":"application/vnd.geoplan",
1166 	"g3w":"application/vnd.geospace",
1167 	"gsf":"application/x-font-ghostscript",
1168 	"bdf":"application/x-font-bdf",
1169 	"gtar":"application/x-gtar",
1170 	"texinfo":"application/x-texinfo",
1171 	"gnumeric":"application/x-gnumeric",
1172 	"kml":"application/vnd.google-earth.kml+xml",
1173 	"kmz":"application/vnd.google-earth.kmz",
1174 	"gqf":"application/vnd.grafeq",
1175 	"gif":"image/gif",
1176 	"gv":"text/vnd.graphviz",
1177 	"gac":"application/vnd.groove-account",
1178 	"ghf":"application/vnd.groove-help",
1179 	"gim":"application/vnd.groove-identity-message",
1180 	"grv":"application/vnd.groove-injector",
1181 	"gtm":"application/vnd.groove-tool-message",
1182 	"tpl":"application/vnd.groove-tool-template",
1183 	"vcg":"application/vnd.groove-vcard",
1184 	"h261":"video/h261",
1185 	"h263":"video/h263",
1186 	"h264":"video/h264",
1187 	"hpid":"application/vnd.hp-hpid",
1188 	"hps":"application/vnd.hp-hps",
1189 	"hdf":"application/x-hdf",
1190 	"rip":"audio/vnd.rip",
1191 	"hbci":"application/vnd.hbci",
1192 	"jlt":"application/vnd.hp-jlyt",
1193 	"pcl":"application/vnd.hp-pcl",
1194 	"hpgl":"application/vnd.hp-hpgl",
1195 	"hvs":"application/vnd.yamaha.hv-script",
1196 	"hvd":"application/vnd.yamaha.hv-dic",
1197 	"hvp":"application/vnd.yamaha.hv-voice",
1198 	"sfd-hdstx":"application/vnd.hydrostatix.sof-data",
1199 	"stk":"application/hyperstudio",
1200 	"hal":"application/vnd.hal+xml",
1201 	"html":"text/html",
1202 	"irm":"application/vnd.ibm.rights-management",
1203 	"sc":"application/vnd.ibm.secure-container",
1204 	"ics":"text/calendar",
1205 	"icc":"application/vnd.iccprofile",
1206 	"ico":"image/x-icon",
1207 	"icns":"image/x-icon",
1208 	"cur":"image/x-icon",
1209 	"igl":"application/vnd.igloader",
1210 	"ief":"image/ief",
1211 	"ivp":"application/vnd.immervision-ivp",
1212 	"ivu":"application/vnd.immervision-ivu",
1213 	"rif":"application/reginfo+xml",
1214 	"3dml":"text/vnd.in3d.3dml",
1215 	"spot":"text/vnd.in3d.spot",
1216 	"igs":"model/iges",
1217 	"i2g":"application/vnd.intergeo",
1218 	"cdy":"application/vnd.cinderella",
1219 	"xpw":"application/vnd.intercon.formnet",
1220 	"fcs":"application/vnd.isac.fcs",
1221 	"ipfix":"application/ipfix",
1222 	"cer":"application/pkix-cert",
1223 	"pki":"application/pkixcmp",
1224 	"crl":"application/pkix-crl",
1225 	"pkipath":"application/pkix-pkipath",
1226 	"igm":"application/vnd.insors.igm",
1227 	"rcprofile":"application/vnd.ipunplugged.rcprofile",
1228 	"irp":"application/vnd.irepository.package+xml",
1229 	"jad":"text/vnd.sun.j2me.app-descriptor",
1230 	"jar":"application/java-archive",
1231 	"class":"application/java-vm",
1232 	"jnlp":"application/x-java-jnlp-file",
1233 	"ser":"application/java-serialized-object",
1234 	"java":"text/x-java-sourcejava",
1235 	"js":"application/javascript",
1236 	"json":"application/json",
1237 	"joda":"application/vnd.joost.joda-archive",
1238 	"jpm":"video/jpm",
1239 	"jpeg":"image/jpeg",
1240 	"jpe":"image/jpeg",
1241 	"jpg":"image/jpeg",
1242 	"pjpeg":"image/pjpeg",
1243 	"jpgv":"video/jpeg",
1244 	"ktz":"application/vnd.kahootz",
1245 	"mmd":"application/vnd.chipnuts.karaoke-mmd",
1246 	"karbon":"application/vnd.kde.karbon",
1247 	"chrt":"application/vnd.kde.kchart",
1248 	"kfo":"application/vnd.kde.kformula",
1249 	"flw":"application/vnd.kde.kivio",
1250 	"kon":"application/vnd.kde.kontour",
1251 	"kpr":"application/vnd.kde.kpresenter",
1252 	"ksp":"application/vnd.kde.kspread",
1253 	"kwd":"application/vnd.kde.kword",
1254 	"htke":"application/vnd.kenameaapp",
1255 	"kia":"application/vnd.kidspiration",
1256 	"kne":"application/vnd.kinar",
1257 	"sse":"application/vnd.kodak-descriptor",
1258 	"lasxml":"application/vnd.las.las+xml",
1259 	"latex":"application/x-latex",
1260 	"lbd":"application/vnd.llamagraphics.life-balance.desktop",
1261 	"lbe":"application/vnd.llamagraphics.life-balance.exchange+xml",
1262 	"jam":"application/vnd.jam",
1263 	"123":"application/vnd.lotus-1-2-3",
1264 	"apr":"application/vnd.lotus-approach",
1265 	"pre":"application/vnd.lotus-freelance",
1266 	"nsf":"application/vnd.lotus-notes",
1267 	"org":"application/vnd.lotus-organizer",
1268 	"scm":"application/vnd.lotus-screencam",
1269 	"lwp":"application/vnd.lotus-wordpro",
1270 	"lvp":"audio/vnd.lucent.voice",
1271 	"m3u":"audio/x-mpegurl",
1272 	"m4v":"video/x-m4v",
1273 	"hqx":"application/mac-binhex40",
1274 	"portpkg":"application/vnd.macports.portpkg",
1275 	"mgp":"application/vnd.osgeo.mapguide.package",
1276 	"mrc":"application/marc",
1277 	"mrcx":"application/marcxml+xml",
1278 	"mxf":"application/mxf",
1279 	"nbp":"application/vnd.wolfram.player",
1280 	"ma":"application/mathematica",
1281 	"mathml":"application/mathml+xml",
1282 	"mbox":"application/mbox",
1283 	"mc1":"application/vnd.medcalcdata",
1284 	"mscml":"application/mediaservercontrol+xml",
1285 	"cdkey":"application/vnd.mediastation.cdkey",
1286 	"mwf":"application/vnd.mfer",
1287 	"mfm":"application/vnd.mfmp",
1288 	"msh":"model/mesh",
1289 	"mads":"application/mads+xml",
1290 	"mets":"application/mets+xml",
1291 	"mods":"application/mods+xml",
1292 	"meta4":"application/metalink4+xml",
1293 	"mcd":"application/vnd.mcd",
1294 	"flo":"application/vnd.micrografx.flo",
1295 	"igx":"application/vnd.micrografx.igx",
1296 	"es3":"application/vnd.eszigno3+xml",
1297 	"mdb":"application/x-msaccess",
1298 	"asf":"video/x-ms-asf",
1299 	"exe":"application/x-msdownload",
1300 	"cil":"application/vnd.ms-artgalry",
1301 	"cab":"application/vnd.ms-cab-compressed",
1302 	"ims":"application/vnd.ms-ims",
1303 	"application":"application/x-ms-application",
1304 	"clp":"application/x-msclip",
1305 	"mdi":"image/vnd.ms-modi",
1306 	"eot":"application/vnd.ms-fontobject",
1307 	"xls":"application/ms-excel",
1308 	"xlam":"application/vnd.ms-excel.addin.macroenabled.12",
1309 	"xlsb":"application/vnd.ms-excel.sheet.binary.macroenabled.12",
1310 	"xltm":"application/vnd.ms-excel.template.macroenabled.12",
1311 	"xlsm":"application/vnd.ms-excel.sheet.macroenabled.12",
1312 	"chm":"application/vnd.ms-htmlhelp",
1313 	"crd":"application/x-mscardfile",
1314 	"lrm":"application/vnd.ms-lrm",
1315 	"mvb":"application/x-msmediaview",
1316 	"mny":"application/x-msmoney",
1317 	"pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",
1318 	"sldx":"application/vnd.openxmlformats-officedocument.presentationml.slide",
1319 	"ppsx":"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
1320 	"potx":"application/vnd.openxmlformats-officedocument.presentationml.template",
1321 	"xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1322 	"xltx":"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
1323 	"docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1324 	"dotx":"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
1325 	"obd":"application/x-msbinder",
1326 	"thmx":"application/vnd.ms-officetheme",
1327 	"onetoc":"application/onenote",
1328 	"pya":"audio/vnd.ms-playready.media.pya",
1329 	"pyv":"video/vnd.ms-playready.media.pyv",
1330 	"ppt":"application/ms-powerpoint",
1331 	"pps":"application/ms-powerpoint",
1332 	"ppam":"application/vnd.ms-powerpoint.addin.macroenabled.12",
1333 	"sldm":"application/vnd.ms-powerpoint.slide.macroenabled.12",
1334 	"pptm":"application/vnd.ms-powerpoint.presentation.macroenabled.12",
1335 	"ppsm":"application/vnd.ms-powerpoint.slideshow.macroenabled.12",
1336 	"potm":"application/vnd.ms-powerpoint.template.macroenabled.12",
1337 	"mpp":"application/vnd.ms-project",
1338 	"pub":"application/x-mspublisher",
1339 	"scd":"application/x-msschedule",
1340 	"xap":"application/x-silverlight-app",
1341 	"stl":"application/vnd.ms-pki.stl",
1342 	"cat":"application/vnd.ms-pki.seccat",
1343 	"vsd":"application/vnd.visio",
1344 	"vsdx":"application/vnd.visio2013",
1345 	"wm":"video/x-ms-wm",
1346 	"wma":"audio/x-ms-wma",
1347 	"wax":"audio/x-ms-wax",
1348 	"wmx":"video/x-ms-wmx",
1349 	"wmd":"application/x-ms-wmd",
1350 	"wpl":"application/vnd.ms-wpl",
1351 	"wmz":"application/x-ms-wmz",
1352 	"wmv":"video/x-ms-wmv",
1353 	"wvx":"video/x-ms-wvx",
1354 	"wmf":"application/x-msmetafile",
1355 	"trm":"application/x-msterminal",
1356 	"doc":"application/msword",
1357 	"docm":"application/vnd.ms-word.document.macroenabled.12",
1358 	"dotm":"application/vnd.ms-word.template.macroenabled.12",
1359 	"wri":"application/x-mswrite",
1360 	"wps":"application/vnd.ms-works",
1361 	"xbap":"application/x-ms-xbap",
1362 	"xps":"application/vnd.ms-xpsdocument",
1363 	"mid":"audio/midi",
1364 	"mpy":"application/vnd.ibm.minipay",
1365 	"afp":"application/vnd.ibm.modcap",
1366 	"rms":"application/vnd.jcp.javame.midlet-rms",
1367 	"tmo":"application/vnd.tmobile-livetv",
1368 	"prc":"application/x-mobipocket-ebook",
1369 	"mbk":"application/vnd.mobius.mbk",
1370 	"dis":"application/vnd.mobius.dis",
1371 	"plc":"application/vnd.mobius.plc",
1372 	"mqy":"application/vnd.mobius.mqy",
1373 	"msl":"application/vnd.mobius.msl",
1374 	"txf":"application/vnd.mobius.txf",
1375 	"daf":"application/vnd.mobius.daf",
1376 	"fly":"text/vnd.fly",
1377 	"mpc":"application/vnd.mophun.certificate",
1378 	"mpn":"application/vnd.mophun.application",
1379 	"mj2":"video/mj2",
1380 	"mpga":"audio/mpeg",
1381 	"mxu":"video/vnd.mpegurl",
1382 	"mpeg":"video/mpeg",
1383 	"mpg":"video/mpeg",
1384 	"m21":"application/mp21",
1385 	"mp4a":"audio/mp4",
1386 	"mp4":"video/mp4",
1387 	"m4a":"video/mp4",
1388 	"m4b":"video/mp4",
1389 	"m4r":"video/mp4",
1390 	"m4v":"video/mp4",
1391 	"m3u8":"application/vnd.apple.mpegurl",
1392 	"mus":"application/vnd.musician",
1393 	"msty":"application/vnd.muvee.style",
1394 	"mxml":"application/xv+xml",
1395 	"ngdat":"application/vnd.nokia.n-gage.data",
1396 	"n-gage":"application/vnd.nokia.n-gage.symbian.install",
1397 	"ncx":"application/x-dtbncx+xml",
1398 	"nc":"application/x-netcdf",
1399 	"nlu":"application/vnd.neurolanguage.nlu",
1400 	"dna":"application/vnd.dna",
1401 	"nnd":"application/vnd.noblenet-directory",
1402 	"nns":"application/vnd.noblenet-sealer",
1403 	"nnw":"application/vnd.noblenet-web",
1404 	"rpst":"application/vnd.nokia.radio-preset",
1405 	"rpss":"application/vnd.nokia.radio-presets",
1406 	"n3":"text/n3",
1407 	"edm":"application/vnd.novadigm.edm",
1408 	"edx":"application/vnd.novadigm.edx",
1409 	"ext":"application/vnd.novadigm.ext",
1410 	"gph":"application/vnd.flographit",
1411 	"ecelp4800":"audio/vnd.nuera.ecelp4800",
1412 	"ecelp7470":"audio/vnd.nuera.ecelp7470",
1413 	"ecelp9600":"audio/vnd.nuera.ecelp9600",
1414 	"oda":"application/oda",
1415 	"ogx":"application/ogg",
1416 	"oga":"audio/ogg",
1417 	"ogv":"video/ogg",
1418 	"ogg":"video/ogg",
1419 	"dd2":"application/vnd.oma.dd2+xml",
1420 	"oth":"application/vnd.oasis.opendocument.text-web",
1421 	"opf":"application/oebps-package+xml",
1422 	"qbo":"application/vnd.intu.qbo",
1423 	"oxt":"application/vnd.openofficeorg.extension",
1424 	"osf":"application/vnd.yamaha.openscoreformat",
1425 	"weba":"audio/webm",
1426 	"webm":"video/webm",
1427 	"odc":"application/vnd.oasis.opendocument.chart",
1428 	"otc":"application/vnd.oasis.opendocument.chart-template",
1429 	"odb":"application/vnd.oasis.opendocument.database",
1430 	"odf":"application/vnd.oasis.opendocument.formula",
1431 	"odft":"application/vnd.oasis.opendocument.formula-template",
1432 	"odg":"application/vnd.oasis.opendocument.graphics",
1433 	"otg":"application/vnd.oasis.opendocument.graphics-template",
1434 	"odi":"application/vnd.oasis.opendocument.image",
1435 	"oti":"application/vnd.oasis.opendocument.image-template",
1436 	"odp":"application/vnd.oasis.opendocument.presentation",
1437 	"otp":"application/vnd.oasis.opendocument.presentation-template",
1438 	"ods":"application/vnd.oasis.opendocument.spreadsheet",
1439 	"ots":"application/vnd.oasis.opendocument.spreadsheet-template",
1440 	"odt":"application/vnd.oasis.opendocument.text",
1441 	"odm":"application/vnd.oasis.opendocument.text-master",
1442 	"ott":"application/vnd.oasis.opendocument.text-template",
1443 	"ktx":"image/ktx",
1444 	"sxc":"application/vnd.sun.xml.calc",
1445 	"stc":"application/vnd.sun.xml.calc.template",
1446 	"sxd":"application/vnd.sun.xml.draw",
1447 	"std":"application/vnd.sun.xml.draw.template",
1448 	"sxi":"application/vnd.sun.xml.impress",
1449 	"sti":"application/vnd.sun.xml.impress.template",
1450 	"sxm":"application/vnd.sun.xml.math",
1451 	"sxw":"application/vnd.sun.xml.writer",
1452 	"sxg":"application/vnd.sun.xml.writer.global",
1453 	"stw":"application/vnd.sun.xml.writer.template",
1454 	"otf":"application/x-font-otf",
1455 	"osfpvg":"application/vnd.yamaha.openscoreformat.osfpvg+xml",
1456 	"dp":"application/vnd.osgi.dp",
1457 	"pdb":"application/vnd.palm",
1458 	"p":"text/x-pascal",
1459 	"paw":"application/vnd.pawaafile",
1460 	"pclxl":"application/vnd.hp-pclxl",
1461 	"efif":"application/vnd.picsel",
1462 	"pcx":"image/x-pcx",
1463 	"psd":"image/vnd.adobe.photoshop",
1464 	"prf":"application/pics-rules",
1465 	"pic":"image/x-pict",
1466 	"chat":"application/x-chat",
1467 	"p10":"application/pkcs10",
1468 	"p12":"application/x-pkcs12",
1469 	"p7m":"application/pkcs7-mime",
1470 	"p7s":"application/pkcs7-signature",
1471 	"p7r":"application/x-pkcs7-certreqresp",
1472 	"p7b":"application/x-pkcs7-certificates",
1473 	"p8":"application/pkcs8",
1474 	"plf":"application/vnd.pocketlearn",
1475 	"pnm":"image/x-portable-anymap",
1476 	"pbm":"image/x-portable-bitmap",
1477 	"pcf":"application/x-font-pcf",
1478 	"pfr":"application/font-tdpfr",
1479 	"pgn":"application/x-chess-pgn",
1480 	"pgm":"image/x-portable-graymap",
1481 	"png":"image/png",
1482 	"ppm":"image/x-portable-pixmap",
1483 	"pskcxml":"application/pskc+xml",
1484 	"pml":"application/vnd.ctc-posml",
1485 	"ai":"application/postscript",
1486 	"pfa":"application/x-font-type1",
1487 	"pbd":"application/vnd.powerbuilder6",
1488 	"pgp":"application/pgp-encrypted",
1489 	"box":"application/vnd.previewsystems.box",
1490 	"ptid":"application/vnd.pvi.ptid1",
1491 	"pls":"application/pls+xml",
1492 	"str":"application/vnd.pg.format",
1493 	"ei6":"application/vnd.pg.osasli",
1494 	"dsc":"text/prs.lines.tag",
1495 	"psf":"application/x-font-linux-psf",
1496 	"qps":"application/vnd.publishare-delta-tree",
1497 	"wg":"application/vnd.pmi.widget",
1498 	"qxd":"application/vnd.quark.quarkxpress",
1499 	"esf":"application/vnd.epson.esf",
1500 	"msf":"application/vnd.epson.msf",
1501 	"ssf":"application/vnd.epson.ssf",
1502 	"qam":"application/vnd.epson.quickanime",
1503 	"qfx":"application/vnd.intu.qfx",
1504 	"qt":"video/quicktime",
1505 	"rar":"application/x-rar-compressed",
1506 	"ram":"audio/x-pn-realaudio",
1507 	"rmp":"audio/x-pn-realaudio-plugin",
1508 	"rsd":"application/rsd+xml",
1509 	"rm":"application/vnd.rn-realmedia",
1510 	"ra":"application/vnd.rn-realmedia",
1511 	"rv":"application/vnd.rn-realmedia",
1512 	"bed":"application/vnd.realvnc.bed",
1513 	"mxl":"application/vnd.recordare.musicxml",
1514 	"musicxml":"application/vnd.recordare.musicxml+xml",
1515 	"rnc":"application/relax-ng-compact-syntax",
1516 	"rdz":"application/vnd.data-vision.rdz",
1517 	"rdf":"application/rdf+xml",
1518 	"rp9":"application/vnd.cloanto.rp9",
1519 	"jisp":"application/vnd.jisp",
1520 	"rtf":"application/rtf",
1521 	"rtx":"text/richtext",
1522 	"link66":"application/vnd.route66.link66+xml",
1523 	"rss":"application/rss+xml",
1524 	"shf":"application/shf+xml",
1525 	"st":"application/vnd.sailingtracker.track",
1526 	"svg":"image/svg+xml",
1527 	"svgz":"image/svg+xml",
1528 	"sus":"application/vnd.sus-calendar",
1529 	"sru":"application/sru+xml",
1530 	"setpay":"application/set-payment-initiation",
1531 	"setreg":"application/set-registration-initiation",
1532 	"sema":"application/vnd.sema",
1533 	"semd":"application/vnd.semd",
1534 	"semf":"application/vnd.semf",
1535 	"see":"application/vnd.seemail",
1536 	"snf":"application/x-font-snf",
1537 	"spq":"application/scvp-vp-request",
1538 	"spp":"application/scvp-vp-response",
1539 	"scq":"application/scvp-cv-request",
1540 	"scs":"application/scvp-cv-response",
1541 	"sdp":"application/sdp",
1542 	"etx":"text/x-setext",
1543 	"movie":"video/x-sgi-movie",
1544 	"ifm":"application/vnd.shana.informed.formdata",
1545 	"itp":"application/vnd.shana.informed.formtemplate",
1546 	"iif":"application/vnd.shana.informed.interchange",
1547 	"ipk":"application/vnd.shana.informed.package",
1548 	"tfi":"application/thraud+xml",
1549 	"shar":"application/x-shar",
1550 	"rgb":"image/x-rgb",
1551 	"slt":"application/vnd.epson.salt",
1552 	"aso":"application/vnd.accpac.simply.aso",
1553 	"imp":"application/vnd.accpac.simply.imp",
1554 	"twd":"application/vnd.simtech-mindmapper",
1555 	"csp":"application/vnd.commonspace",
1556 	"saf":"application/vnd.yamaha.smaf-audio",
1557 	"mmf":"application/vnd.smaf",
1558 	"spf":"application/vnd.yamaha.smaf-phrase",
1559 	"teacher":"application/vnd.smart.teacher",
1560 	"svd":"application/vnd.svd",
1561 	"rq":"application/sparql-query",
1562 	"srx":"application/sparql-results+xml",
1563 	"gram":"application/srgs",
1564 	"grxml":"application/srgs+xml",
1565 	"ssml":"application/ssml+xml",
1566 	"skp":"application/vnd.koan",
1567 	"sgml":"text/sgml",
1568 	"sdc":"application/vnd.stardivision.calc",
1569 	"sda":"application/vnd.stardivision.draw",
1570 	"sdd":"application/vnd.stardivision.impress",
1571 	"smf":"application/vnd.stardivision.math",
1572 	"sdw":"application/vnd.stardivision.writer",
1573 	"sgl":"application/vnd.stardivision.writer-global",
1574 	"sm":"application/vnd.stepmania.stepchart",
1575 	"sit":"application/x-stuffit",
1576 	"sitx":"application/x-stuffitx",
1577 	"sdkm":"application/vnd.solent.sdkm+xml",
1578 	"xo":"application/vnd.olpc-sugar",
1579 	"au":"audio/basic",
1580 	"wqd":"application/vnd.wqd",
1581 	"sis":"application/vnd.symbian.install",
1582 	"smi":"application/smil+xml",
1583 	"xsm":"application/vnd.syncml+xml",
1584 	"bdm":"application/vnd.syncml.dm+wbxml",
1585 	"xdm":"application/vnd.syncml.dm+xml",
1586 	"sv4cpio":"application/x-sv4cpio",
1587 	"sv4crc":"application/x-sv4crc",
1588 	"sbml":"application/sbml+xml",
1589 	"tsv":"text/tab-separated-values",
1590 	"tif":"image/tiff",
1591 	"tiff":"image/tiff",
1592 	"tao":"application/vnd.tao.intent-module-archive",
1593 	"tar":"application/x-tar",
1594 	"tcl":"application/x-tcl",
1595 	"tex":"application/x-tex",
1596 	"tfm":"application/x-tex-tfm",
1597 	"tei":"application/tei+xml",
1598 	"txt":"text/plain",
1599 	"dxp":"application/vnd.spotfire.dxp",
1600 	"sfs":"application/vnd.spotfire.sfs",
1601 	"tsd":"application/timestamped-data",
1602 	"tpt":"application/vnd.trid.tpt",
1603 	"mxs":"application/vnd.triscape.mxs",
1604 	"t":"text/troff",
1605 	"tra":"application/vnd.trueapp",
1606 	"ttf":"application/x-font-ttf",
1607 	"ttl":"text/turtle",
1608 	"umj":"application/vnd.umajin",
1609 	"uoml":"application/vnd.uoml+xml",
1610 	"unityweb":"application/vnd.unity",
1611 	"ufd":"application/vnd.ufdl",
1612 	"uri":"text/uri-list",
1613 	"utz":"application/vnd.uiq.theme",
1614 	"ustar":"application/x-ustar",
1615 	"uu":"text/x-uuencode",
1616 	"vcs":"text/x-vcalendar",
1617 	"vcf":"text/x-vcard",
1618 	"vcd":"application/x-cdlink",
1619 	"vsf":"application/vnd.vsf",
1620 	"wrl":"model/vrml",
1621 	"vcx":"application/vnd.vcx",
1622 	"mts":"model/vnd.mts",
1623 	"vtu":"model/vnd.vtu",
1624 	"vis":"application/vnd.visionary",
1625 	"viv":"video/vnd.vivo",
1626 	"ccxml":"application/ccxml+xml",
1627 	"vxml":"application/voicexml+xml",
1628 	"src":"application/x-wais-source",
1629 	"wbxml":"application/vnd.wap.wbxml",
1630 	"wbmp":"image/vnd.wap.wbmp",
1631 	"wav":"audio/x-wav",
1632 	"davmount":"application/davmount+xml",
1633 	"woff":"application/x-font-woff",
1634 	"wspolicy":"application/wspolicy+xml",
1635 	"webp":"image/webp",
1636 	"wtb":"application/vnd.webturbo",
1637 	"wgt":"application/widget",
1638 	"hlp":"application/winhlp",
1639 	"wml":"text/vnd.wap.wml",
1640 	"wmls":"text/vnd.wap.wmlscript",
1641 	"wmlsc":"application/vnd.wap.wmlscriptc",
1642 	"wpd":"application/vnd.wordperfect",
1643 	"stf":"application/vnd.wt.stf",
1644 	"wsdl":"application/wsdl+xml",
1645 	"xbm":"image/x-xbitmap",
1646 	"xpm":"image/x-xpixmap",
1647 	"xwd":"image/x-xwindowdump",
1648 	"der":"application/x-x509-ca-cert",
1649 	"fig":"application/x-xfig",
1650 	"xhtml":"application/xhtml+xml",
1651 	"xdf":"application/xcap-diff+xml",
1652 	"xenc":"application/xenc+xml",
1653 	"xer":"application/patch-ops-error+xml",
1654 	"rl":"application/resource-lists+xml",
1655 	"rs":"application/rls-services+xml",
1656 	"rld":"application/resource-lists-diff+xml",
1657 	"xslt":"application/xslt+xml",
1658 	"xop":"application/xop+xml",
1659 	"xpi":"application/x-xpinstall",
1660 	"xspf":"application/xspf+xml",
1661 	"xul":"application/vnd.mozilla.xul+xml",
1662 	"xyz":"chemical/x-xyz",
1663 	"yaml":"text/yaml",
1664 	"yang":"application/yang",
1665 	"yin":"application/yin+xml",
1666 	"zir":"application/vnd.zul",
1667 	"zip":"application/zip",
1668 	"zmm":"application/vnd.handheld-entertainment+xml",
1669 	"zaz":"application/vnd.zzazz.deck+xml",
1670 	"xmp":"application/octet-stream",
1671 	"mov":"video/quicktime",
1672 	"ini":"text/plain",
1673 	"mp3":"audio/x-mpeg"
1674 };
1675