parse-multipart-data-umd

A UMD build of parse-multipart-data

Questo script non dovrebbe essere installato direttamente. È una libreria per altri script da includere con la chiave // @require https://update.greasyfork.org/scripts/517244/1483543/parse-multipart-data-umd.js

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.parseMultipartData = {}));
})(this, (function (exports) { 'use strict';

    function process(part) {
        // will transform this object:
        // { header: 'Content-Disposition: form-data; name="uploads[]"; filename="A.txt"',
        // info: 'Content-Type: text/plain',
        // part: 'AAAABBBB' }
        // into this one:
        // { filename: 'A.txt', type: 'text/plain', data: <Buffer 41 41 41 41 42 42 42 42> }
        const obj = function (str) {
            const k = str.split('=');
            const a = k[0].trim();
            const b = JSON.parse(k[1].trim());
            const o = {};
            Object.defineProperty(o, a, {
                value: b,
                writable: true,
                enumerable: true,
                configurable: true
            });
            return o;
        };
        const header = part.contentDispositionHeader.split(';');
        const filenameData = header[2];
        let input = {};
        if (filenameData) {
            input = obj(filenameData);
            const contentType = part.contentTypeHeader.split(':')[1].trim();
            Object.defineProperty(input, 'type', {
                value: contentType,
                writable: true,
                enumerable: true,
                configurable: true
            });
        }
        // always process the name field
        Object.defineProperty(input, 'name', {
            value: header[1].split('=')[1].replace(/"/g, ''),
            writable: true,
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(input, 'data', {
            value: new Uint8Array(part.part),
            writable: true,
            enumerable: true,
            configurable: true
        });
        return input;
    }

    const ParsingState = (ParsingState => {
        ParsingState[(ParsingState.INIT = 0)] = 'INIT';
        ParsingState[(ParsingState.READING_HEADERS = 1)] = 'READING_HEADERS';
        ParsingState[(ParsingState.READING_DATA = 2)] = 'READING_DATA';
        ParsingState[(ParsingState.READING_PART_SEPARATOR = 3)] = 'READING_PART_SEPARATOR';
        return ParsingState;
    })({});

    function parse(multipartBodyBuffer, boundary) {
        let lastline = '';
        let contentDispositionHeader = '';
        let contentTypeHeader = '';
        let state = ParsingState.INIT;
        let buffer = [];
        const allParts = [];
        let currentPartHeaders = [];
        for (let i = 0; i < multipartBodyBuffer.length; i++) {
            const oneByte = multipartBodyBuffer[i];
            const prevByte = i > 0 ? multipartBodyBuffer[i - 1] : null;
            // 0x0a => \n
            // 0x0d => \r
            const newLineDetected = oneByte === 0x0a && prevByte === 0x0d;
            const newLineChar = oneByte === 0x0a || oneByte === 0x0d;
            if (!newLineChar) lastline += String.fromCharCode(oneByte);
            if (ParsingState.INIT === state && newLineDetected) {
                // searching for boundary
                if ('--' + boundary === lastline) {
                    state = ParsingState.READING_HEADERS; // found boundary. start reading headers
                }
                lastline = '';
            } else if (ParsingState.READING_HEADERS === state && newLineDetected) {
                // parsing headers. Headers are separated by an empty line from the content. Stop reading headers when the line is empty
                if (lastline.length) {
                    currentPartHeaders.push(lastline);
                } else {
                    // found empty line. search for the headers we want and set the values
                    for (const h of currentPartHeaders) {
                        if (h.toLowerCase().startsWith('content-disposition:')) {
                            contentDispositionHeader = h;
                        } else if (h.toLowerCase().startsWith('content-type:')) {
                            contentTypeHeader = h;
                        }
                    }
                    state = ParsingState.READING_DATA;
                    buffer = [];
                }
                lastline = '';
            } else if (ParsingState.READING_DATA === state) {
                // parsing data
                if (lastline.length > boundary.length + 4) {
                    lastline = ''; // mem save
                }
                if ('--' + boundary === lastline) {
                    const j = buffer.length - lastline.length;
                    const part = buffer.slice(0, j - 1);
                    allParts.push(process({
                        contentDispositionHeader,
                        contentTypeHeader,
                        part
                    }));
                    buffer = [];
                    currentPartHeaders = [];
                    lastline = '';
                    state = ParsingState.READING_PART_SEPARATOR;
                    contentDispositionHeader = '';
                    contentTypeHeader = '';
                } else {
                    buffer.push(oneByte);
                }
                if (newLineDetected) {
                    lastline = '';
                }
            } else if (ParsingState.READING_PART_SEPARATOR === state) {
                if (newLineDetected) {
                    state = ParsingState.READING_HEADERS;
                }
            }
        }
        return allParts;
    }
    //  read the boundary from the content-type header sent by the http client
    //  this value may be similar to:
    //  'multipart/form-data; boundary=----WebKitFormBoundaryvm5A9tzU1ONaGP5B',
    function getBoundary(header) {
        const items = header.split(';');
        if (items) {
            for (let i = 0; i < items.length; i++) {
                const item = new String(items[i]).trim();
                if (item.indexOf('boundary') >= 0) {
                    const k = item.split('=');
                    return new String(k[1]).trim().replace(/^["']|["']$/g, '');
                }
            }
        }
        return '';
    }
    exports.getBoundary = getBoundary;
    exports.parse = parse;
}));