snappymail/dev/Model/Attachment.js
2019-07-04 22:19:24 +03:00

498 lines
11 KiB
JavaScript

import window from 'window';
import _ from '_';
import ko from 'ko';
import { FileType } from 'Common/Enums';
import { bAllowPdfPreview, data as GlobalsData } from 'Common/Globals';
import { trim, pInt, inArray, isNonEmptyArray, getFileExtension, friendlySize } from 'Common/Utils';
import {
attachmentDownload,
attachmentPreview,
attachmentFramed,
attachmentPreviewAsPlain,
attachmentThumbnailPreview
} from 'Common/Links';
import { AbstractModel } from 'Knoin/AbstractModel';
import Audio from 'Common/Audio';
/**
* @param {string} sExt
* @param {string} sMimeType
* @returns {string}
*/
export const staticFileType = _.memoize((ext, mimeType) => {
ext = trim(ext).toLowerCase();
mimeType = trim(mimeType).toLowerCase();
let result = FileType.Unknown;
const mimeTypeParts = mimeType.split('/');
switch (true) {
case 'image' === mimeTypeParts[0] || -1 < inArray(ext, ['png', 'jpg', 'jpeg', 'gif', 'bmp']):
result = FileType.Image;
break;
case 'audio' === mimeTypeParts[0] || -1 < inArray(ext, ['mp3', 'ogg', 'oga', 'wav']):
result = FileType.Audio;
break;
case 'video' === mimeTypeParts[0] || -1 < inArray(ext, ['mkv', 'avi']):
result = FileType.Video;
break;
case -1 < inArray(ext, ['php', 'js', 'css']):
result = FileType.Code;
break;
case 'eml' === ext || -1 < inArray(mimeType, ['message/delivery-status', 'message/rfc822']):
result = FileType.Eml;
break;
case ('text' === mimeTypeParts[0] && 'html' !== mimeTypeParts[1]) || -1 < inArray(ext, ['txt', 'log']):
result = FileType.Text;
break;
case 'text/html' === mimeType || -1 < inArray(ext, ['html']):
result = FileType.Html;
break;
case -1 <
inArray(mimeTypeParts[1], [
'zip',
'7z',
'tar',
'rar',
'gzip',
'bzip',
'bzip2',
'x-zip',
'x-7z',
'x-rar',
'x-tar',
'x-gzip',
'x-bzip',
'x-bzip2',
'x-zip-compressed',
'x-7z-compressed',
'x-rar-compressed'
]) || -1 < inArray(ext, ['zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2']):
result = FileType.Archive;
break;
case -1 < inArray(mimeTypeParts[1], ['pdf', 'x-pdf']) || -1 < inArray(ext, ['pdf']):
result = FileType.Pdf;
break;
case -1 < inArray(mimeType, ['application/pgp-signature', 'application/pgp-keys']) ||
-1 < inArray(ext, ['asc', 'pem', 'ppk']):
result = FileType.Certificate;
break;
case -1 < inArray(mimeType, ['application/pkcs7-signature']) || -1 < inArray(ext, ['p7s']):
result = FileType.CertificateBin;
break;
case -1 <
inArray(mimeTypeParts[1], [
'rtf',
'msword',
'vnd.msword',
'vnd.openxmlformats-officedocument.wordprocessingml.document',
'vnd.openxmlformats-officedocument.wordprocessingml.template',
'vnd.ms-word.document.macroEnabled.12',
'vnd.ms-word.template.macroEnabled.12'
]):
result = FileType.WordText;
break;
case -1 <
inArray(mimeTypeParts[1], [
'excel',
'ms-excel',
'vnd.ms-excel',
'vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'vnd.openxmlformats-officedocument.spreadsheetml.template',
'vnd.ms-excel.sheet.macroEnabled.12',
'vnd.ms-excel.template.macroEnabled.12',
'vnd.ms-excel.addin.macroEnabled.12',
'vnd.ms-excel.sheet.binary.macroEnabled.12'
]):
result = FileType.Sheet;
break;
case -1 <
inArray(mimeTypeParts[1], [
'powerpoint',
'ms-powerpoint',
'vnd.ms-powerpoint',
'vnd.openxmlformats-officedocument.presentationml.presentation',
'vnd.openxmlformats-officedocument.presentationml.template',
'vnd.openxmlformats-officedocument.presentationml.slideshow',
'vnd.ms-powerpoint.addin.macroEnabled.12',
'vnd.ms-powerpoint.presentation.macroEnabled.12',
'vnd.ms-powerpoint.template.macroEnabled.12',
'vnd.ms-powerpoint.slideshow.macroEnabled.12'
]):
result = FileType.Presentation;
break;
// no default
}
return result;
});
/**
* @param {string} sFileType
* @returns {string}
*/
export const staticIconClass = _.memoize((fileType) => {
let resultText = '',
resultClass = 'icon-file';
switch (fileType) {
case FileType.Text:
case FileType.Eml:
case FileType.WordText:
resultClass = 'icon-file-text';
break;
case FileType.Html:
case FileType.Code:
resultClass = 'icon-file-code';
break;
case FileType.Image:
resultClass = 'icon-file-image';
break;
case FileType.Audio:
resultClass = 'icon-file-music';
break;
case FileType.Video:
resultClass = 'icon-file-movie';
break;
case FileType.Archive:
resultClass = 'icon-file-zip';
break;
case FileType.Certificate:
case FileType.CertificateBin:
resultClass = 'icon-file-certificate';
break;
case FileType.Sheet:
resultClass = 'icon-file-excel';
break;
case FileType.Presentation:
resultClass = 'icon-file-chart-graph';
break;
case FileType.Pdf:
resultText = 'pdf';
resultClass = 'icon-none';
break;
// no default
}
return [resultClass, resultText];
});
/**
* @static
* @param {string} sFileType
* @returns {string}
*/
export const staticCombinedIconClass = (data) => {
let result = '',
types = [];
if (isNonEmptyArray(data)) {
result = 'icon-attachment';
types = _.uniq(_.compact(_.map(data, (item) => (item ? staticFileType(getFileExtension(item[0]), item[1]) : ''))));
if (types && 1 === types.length && types[0]) {
switch (types[0]) {
case FileType.Text:
case FileType.WordText:
result = 'icon-file-text';
break;
case FileType.Html:
case FileType.Code:
result = 'icon-file-code';
break;
case FileType.Image:
result = 'icon-file-image';
break;
case FileType.Audio:
result = 'icon-file-music';
break;
case FileType.Video:
result = 'icon-file-movie';
break;
case FileType.Archive:
result = 'icon-file-zip';
break;
case FileType.Certificate:
case FileType.CertificateBin:
result = 'icon-file-certificate';
break;
case FileType.Sheet:
result = 'icon-file-excel';
break;
case FileType.Presentation:
result = 'icon-file-chart-graph';
break;
// no default
}
}
}
return result;
};
class AttachmentModel extends AbstractModel {
constructor() {
super('AttachmentModel');
this.checked = ko.observable(false);
this.mimeType = '';
this.fileName = '';
this.fileNameExt = '';
this.fileType = FileType.Unknown;
this.estimatedSize = 0;
this.friendlySize = '';
this.isInline = false;
this.isLinked = false;
this.isThumbnail = false;
this.cid = '';
this.cidWithOutTags = '';
this.contentLocation = '';
this.download = '';
this.folder = '';
this.uid = '';
this.mimeIndex = '';
this.framed = false;
}
/**
* @static
* @param {AjaxJsonAttachment} json
* @returns {?AttachmentModel}
*/
static newInstanceFromJson(json) {
const attachment = new AttachmentModel();
return attachment.initByJson(json) ? attachment : null;
}
/**
* @param {AjaxJsonAttachment} json
* @returns {boolean}
*/
initByJson(json) {
let bResult = false;
if (json && 'Object/Attachment' === json['@Object']) {
this.mimeType = trim((json.MimeType || '').toLowerCase());
this.fileName = trim(json.FileName);
this.estimatedSize = pInt(json.EstimatedSize);
this.isInline = !!json.IsInline;
this.isLinked = !!json.IsLinked;
this.isThumbnail = !!json.IsThumbnail;
this.cid = json.CID;
this.contentLocation = json.ContentLocation;
this.download = json.Download;
this.folder = json.Folder;
this.uid = json.Uid;
this.mimeIndex = json.MimeIndex;
this.framed = !!json.Framed;
this.friendlySize = friendlySize(this.estimatedSize);
this.cidWithOutTags = this.cid.replace(/^<+/, '').replace(/>+$/, '');
this.fileNameExt = getFileExtension(this.fileName);
this.fileType = staticFileType(this.fileNameExt, this.mimeType);
bResult = true;
}
return bResult;
}
/**
* @returns {boolean}
*/
isImage() {
return FileType.Image === this.fileType;
}
/**
* @returns {boolean}
*/
isMp3() {
return FileType.Audio === this.fileType && 'mp3' === this.fileNameExt;
}
/**
* @returns {boolean}
*/
isOgg() {
return FileType.Audio === this.fileType && ('oga' === this.fileNameExt || 'ogg' === this.fileNameExt);
}
/**
* @returns {boolean}
*/
isWav() {
return FileType.Audio === this.fileType && 'wav' === this.fileNameExt;
}
/**
* @returns {boolean}
*/
hasThumbnail() {
return this.isThumbnail;
}
/**
* @returns {boolean}
*/
isText() {
return (
FileType.Text === this.fileType ||
FileType.Eml === this.fileType ||
FileType.Certificate === this.fileType ||
FileType.Html === this.fileType ||
FileType.Code === this.fileType
);
}
/**
* @returns {boolean}
*/
isPdf() {
return FileType.Pdf === this.fileType;
}
/**
* @returns {boolean}
*/
isFramed() {
return (
this.framed &&
(GlobalsData.__APP__ && GlobalsData.__APP__.googlePreviewSupported()) &&
!(this.isPdf() && bAllowPdfPreview) &&
!this.isText() &&
!this.isImage()
);
}
/**
* @returns {boolean}
*/
hasPreview() {
return this.isImage() || (this.isPdf() && bAllowPdfPreview) || this.isText() || this.isFramed();
}
/**
* @returns {boolean}
*/
hasPreplay() {
return (
(Audio.supportedMp3 && this.isMp3()) ||
(Audio.supportedOgg && this.isOgg()) ||
(Audio.supportedWav && this.isWav())
);
}
/**
* @returns {string}
*/
linkDownload() {
return attachmentDownload(this.download);
}
/**
* @returns {string}
*/
linkPreview() {
return attachmentPreview(this.download);
}
/**
* @returns {string}
*/
linkThumbnail() {
return this.hasThumbnail() ? attachmentThumbnailPreview(this.download) : '';
}
/**
* @returns {string}
*/
linkThumbnailPreviewStyle() {
const link = this.linkThumbnail();
return '' === link ? '' : 'background:url(' + link + ')';
}
/**
* @returns {string}
*/
linkFramed() {
return attachmentFramed(this.download);
}
/**
* @returns {string}
*/
linkPreviewAsPlain() {
return attachmentPreviewAsPlain(this.download);
}
/**
* @returns {string}
*/
linkPreviewMain() {
let result = '';
switch (true) {
case this.isImage():
case this.isPdf() && bAllowPdfPreview:
result = this.linkPreview();
break;
case this.isText():
result = this.linkPreviewAsPlain();
break;
case this.isFramed():
result = this.linkFramed();
break;
// no default
}
return result;
}
/**
* @returns {string}
*/
generateTransferDownloadUrl() {
let link = this.linkDownload();
if ('http' !== link.substr(0, 4)) {
link = window.location.protocol + '//' + window.location.host + window.location.pathname + link;
}
return this.mimeType + ':' + this.fileName + ':' + link;
}
/**
* @param {AttachmentModel} attachment
* @param {*} event
* @returns {boolean}
*/
eventDragStart(attachment, event) {
const localEvent = event.originalEvent || event;
if (attachment && localEvent && localEvent.dataTransfer && localEvent.dataTransfer.setData) {
localEvent.dataTransfer.setData('DownloadURL', this.generateTransferDownloadUrl());
}
return true;
}
/**
* @returns {string}
*/
iconClass() {
return staticIconClass(this.fileType)[0];
}
/**
* @returns {string}
*/
iconText() {
return staticIconClass(this.fileType)[1];
}
}
export { AttachmentModel, AttachmentModel as default };