From 781c50b1dafffa7558e718fc4ff9b415139a87bf Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 3 Apr 2020 17:15:18 -0700 Subject: small commenting on uploadutils --- src/server/DashUploadUtils.ts | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'src/server/DashUploadUtils.ts') diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 2af816df8..ab3564ebb 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -160,6 +160,11 @@ export namespace DashUploadUtils { export const InspectImage = async (source: string): Promise => { let rawMatches: RegExpExecArray | null; let filename: string | undefined; + /** + * Just more edge case handling: this if clause handles the case where an image onto the canvas that + * is represented by a base64 encoded data uri, rather than a proper file. We manually write it out + * to the server and then carry on as if it had been put there by the Formidable form / file parser. + */ if ((rawMatches = /^data:image\/([a-z]+);base64,(.*)/.exec(source)) !== null) { const [ext, data] = rawMatches.slice(1, 3); const resolved = filename = `upload_${Utils.GenerateGuid()}.${ext}`; @@ -172,21 +177,35 @@ export namespace DashUploadUtils { source = `http://localhost:1050${clientPathToFile(Directory.images, resolved)}`; } let resolvedUrl: string; + /** + * At this point, we want to take whatever url we have and make sure it's requestable. + * Anything that's hosted by some other website already is, but if the url is a local file url + * (locates the file on this server machine), we have to resolve the client side url by cutting out the + * basename subtree (i.e. /images/.) and put it on the end of the server's url. + * + * This can always be localhost, regardless of whether this is on the server or not, since we (the server, not the client) + * will be the ones making the request, and from the perspective of dash-release or dash-web, localhost:1050 refers to the same thing + * as the full dash-release.eastus.cloudapp.azure.com:1050. + */ const matches = isLocal().exec(source); if (matches === null) { resolvedUrl = source; } else { resolvedUrl = `http://localhost:1050/${matches[1].split("\\").join("/")}`; } + // See header comments: not all image files have exif data (I believe only JPG is the only format that can have it) const exifData = await parseExifData(resolvedUrl); const results = { exifData, requestable: resolvedUrl }; + // Use the request library to parse out file level image information in the headers const { headers } = (await new Promise((resolve, reject) => { request.head(resolvedUrl, (error, res) => error ? reject(error) : resolve(res)); }).catch(error => console.error(error))); + // Compute the native width and height ofthe image with an npm module const { width: nativeWidth, height: nativeHeight }: RequestedImageSize = await requestImageSize(resolvedUrl); + // Bundle up the information into an object return { source, contentSize: parseInt(headers[size]), @@ -198,6 +217,16 @@ export namespace DashUploadUtils { }; }; + /** + * Basically just a wrapper around rename, which 'deletes' + * the file at the old path and 'moves' it to the new one. For simplicity, the + * caller just has to pass in the name of the target directory, and this function + * will resolve the actual target path from that. + * @param file The file to move + * @param destination One of the specific media asset directories into which to move it + * @param suffix If the file doesn't have a suffix and you want to provide it one + * to appear in the new location + */ export async function MoveParsedFile(file: File, destination: Directory, suffix: string | undefined = undefined): Promise { const { path: sourcePath } = file; let name = path.basename(sourcePath); @@ -211,10 +240,8 @@ export namespace DashUploadUtils { accessPaths: { agnostic: getAccessPaths(destination, name) } - } - } - ); + }); }); }); } -- cgit v1.2.3-70-g09d2 From d95affdc0ac87ed748fdffc0eabc7916dc9469e5 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sat, 11 Apr 2020 17:29:18 -0700 Subject: small server checks, removed buxton import document dragger --- src/server/DashUploadUtils.ts | 14 ++++++++++++-- src/server/authentication/models/current_user_utils.ts | 4 +--- src/server/database.ts | 2 +- src/server/index.ts | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) (limited to 'src/server/DashUploadUtils.ts') diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index ab3564ebb..8052d8e56 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -1,4 +1,4 @@ -import { unlinkSync, createWriteStream, readFileSync, rename, writeFile } from 'fs'; +import { unlinkSync, createWriteStream, readFileSync, rename, writeFile, existsSync } from 'fs'; import { Utils } from '../Utils'; import * as path from 'path'; import * as sharp from 'sharp'; @@ -6,7 +6,7 @@ import request = require('request-promise'); import { ExifImage } from 'exif'; import { Opt } from '../new_fields/Doc'; import { AcceptibleMedia, Upload } from './SharedMediaTypes'; -import { filesDirectory } from '.'; +import { filesDirectory, publicDirectory } from '.'; import { File } from 'formidable'; import { basename } from "path"; import { createIfNotExists } from './ActionUtilities'; @@ -136,6 +136,16 @@ export namespace DashUploadUtils { }; export async function buildFileDirectories() { + if (!existsSync(publicDirectory)) { + console.error("\nPlease ensure that the following directory exists...\n"); + console.log(publicDirectory); + process.exit(0); + } + if (!existsSync(filesDirectory)) { + console.error("\nPlease ensure that the following directory exists...\n"); + console.log(filesDirectory); + process.exit(0); + } const pending = Object.keys(Directory).map(sub => createIfNotExists(`${filesDirectory}/${sub}`)); return Promise.all(pending); } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 5e0e9ad67..5408440e7 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -74,7 +74,6 @@ export class CurrentUserUtils { { title: "preview", icon: "expand", ignoreClick: true, drag: 'Docs.Create.DocumentDocument(ComputedField.MakeFunction("selectedDocs(this,this.excludeCollections,[_last_])?.[0]"), { _width: 250, _height: 250, title: "container" })' }, { title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", {_width: 300, _height: 300, title: "New Webpage" })' }, { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' }, - { title: "buxton", icon: "cloud-upload-alt", ignoreClick: true, drag: "Docs.Create.Buxton()" }, { title: "screenshot", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' }, { title: "webcam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' }, { title: "record", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` }, @@ -89,8 +88,7 @@ export class CurrentUserUtils { { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc }, { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc }, { title: "query", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' }, - - + // { title: "buxton", icon: "cloud-upload-alt", ignoreClick: true, drag: "Docs.Create.Buxton()" }, ]; return docProtoData.filter(d => !alreadyCreatedButtons?.includes(d.title)).map(data => Docs.Create.FontIconDocument({ _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, diff --git a/src/server/database.ts b/src/server/database.ts index fc91ff3a2..a46531641 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -54,7 +54,7 @@ export namespace Database { private onConnect: (() => void)[] = []; constructor() { - this.MongoClient.connect(url, (_err, client) => { + this.MongoClient.connect(url, { connectTimeoutMS: 30000, socketTimeoutMS: 30000 }, (_err, client) => { if (!client) { console.error("\nPlease start MongoDB by running 'mongod' in a terminal before continuing...\n"); process.exit(0); diff --git a/src/server/index.ts b/src/server/index.ts index 97f70630b..8b040c926 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -39,10 +39,10 @@ export const filesDirectory = path.resolve(publicDirectory, "files"); */ async function preliminaryFunctions() { // Utils.TraceConsoleLog(); + await DashUploadUtils.buildFileDirectories(); await Logger.initialize(); await GoogleCredentialsLoader.loadCredentials(); GoogleApiServerUtils.processProjectCredentials(); - await DashUploadUtils.buildFileDirectories(); if (process.env.DB !== "MEM") { await log_execution({ startMessage: "attempting to initialize mongodb connection", -- cgit v1.2.3-70-g09d2 From 55c403c9fd074f030ab78127803a5dc6183a2638 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sun, 12 Apr 2020 00:14:29 -0700 Subject: exif buffer decoder --- src/server/DashUploadUtils.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/server/DashUploadUtils.ts') diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 8052d8e56..e77662ca4 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -283,9 +283,22 @@ export namespace DashUploadUtils { return information; }; + const bufferConverterRec = (layer: any) => { + for (const key of Object.keys(layer)) { + const val: any = layer[key]; + if (val instanceof Buffer) { + layer[key] = val.toString(); + } else if (Array.isArray(val) && typeof val[0] === "number") { + layer[key] = new Buffer(val).toString(); + } else if (typeof val === "object") { + bufferConverterRec(val); + } + } + }; + const parseExifData = async (source: string): Promise => { const image = await request.get(source, { encoding: null }); - return new Promise(resolve => { + const { data, error } = await new Promise(resolve => { new ExifImage({ image }, (error, data) => { let reason: Opt = undefined; if (error) { @@ -294,6 +307,8 @@ export namespace DashUploadUtils { resolve({ data, error: reason }); }); }); + bufferConverterRec(data); + return { data, error }; }; const { pngs, jpgs, webps, tiffs } = AcceptibleMedia; -- cgit v1.2.3-70-g09d2 From 62b66636c9244e55ff14b982c82a7e80075be20b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 12 Apr 2020 12:08:38 -0400 Subject: don't convert buffer if no data in dashuploadutils --- src/server/DashUploadUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/server/DashUploadUtils.ts') diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index e77662ca4..f91e018b5 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -307,7 +307,7 @@ export namespace DashUploadUtils { resolve({ data, error: reason }); }); }); - bufferConverterRec(data); + data && bufferConverterRec(data); return { data, error }; }; -- cgit v1.2.3-70-g09d2 From 23d6d5eaa71a83691e0c711bce9e84d2967d2f4c Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 12 Apr 2020 16:57:36 -0400 Subject: fixed warning --- src/server/DashUploadUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/server/DashUploadUtils.ts') diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index f91e018b5..9b518749c 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -289,7 +289,7 @@ export namespace DashUploadUtils { if (val instanceof Buffer) { layer[key] = val.toString(); } else if (Array.isArray(val) && typeof val[0] === "number") { - layer[key] = new Buffer(val).toString(); + layer[key] = Buffer.from(val).toString(); } else if (typeof val === "object") { bufferConverterRec(val); } -- cgit v1.2.3-70-g09d2