<commit_before>"use strict";

const Handler = require('../../router/handler');
const Busboy = require('busboy');
const Form = require('../form');
const cipher = require('../../../util/cipher');
const mkdirp = require('../../../util/mkdirp');
const rename = require('../../../util/rename');
const uuid = require('node-uuid');
const path = require('path');
const fs = require('fs');
const os = require('os');
const {coroutine: co, promisify} = require('bluebird');
const unlink = promisify(fs.unlink);

class FormApiHandler extends Handler {
  init(context) {
    let busboy,
        post = {},
        form = {},
        {request} = context;

    // Create formApiErrorList to hold a list of elements in an error state.
    context.formApiErrorList = {};
    context.formError = {};
    context.post = {};
    if (request.method !== 'POST') {
      return Promise.resolve();
    }

    let FormApi = context.engine.plugin.get('FormApi');

    return co(function*(self) {
      // Parsing the headers with busboy requires streams, so use a promise to
      // hide the complexity.
      yield promisify(function(next) {
        // Parse form data.
        // Example: https://github.com/mscdex/busboy
        // TODO: Expose Busboy options to admin, such as upload limits.
        busboy = new Busboy({headers: request.headers });

        // Set file processing.
        busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
          if (filename) {
            post[fieldname] = {
              type: 'file',
              name: filename,
              encoding: encoding,
              mime: mimetype,
              path: path.join(os.tmpdir(), uuid.v4()),
              size: 0,
            };
            file.on('data', data => post[fieldname].size += data.length);
            // TODO: Handle broken, incomplete, and file-too-big errors.
            file.on('limit', () => {});
            file.pipe(fs.createWriteStream(post[fieldname].path));
          }
        });

        // Set regular field processing.
        busboy.on('field', (fieldname, val, fieldnameTruncated, valTruncated) => {
          if (fieldname.substring(fieldname.length - 2) == '[]') {
            // If there is an empty bracket (e.g., '[]') at the end of the
            // fieldname, then this is input from a checkbox or radio button.
            //
            // In this case, treat the value as an element in an object.
            // The value will always a string, so use it for both the key and<commit_msg>Fix hang when empty file field is submitted<commit_after>"use strict";

const Handler = require('../../router/handler');
const Busboy = require('busboy');
const Form = require('../form');
const cipher = require('../../../util/cipher');
const mkdirp = require('../../../util/mkdirp');
const rename = require('../../../util/rename');
const uuid = require('node-uuid');
const path = require('path');
const fs = require('fs');
const os = require('os');
const {coroutine: co, promisify} = require('bluebird');
const unlink = promisify(fs.unlink);

class FormApiHandler extends Handler {
  init(context) {
    let busboy,
        post = {},
        form = {},
        {request} = context;

    // Create formApiErrorList to hold a list of elements in an error state.
    context.formApiErrorList = {};
    context.formError = {};
    context.post = {};
    if (request.method !== 'POST') {
      return Promise.resolve();
    }

    let FormApi = context.engine.plugin.get('FormApi');

    return co(function*(self) {
      // Parsing the headers with busboy requires streams, so use a promise to
      // hide the complexity.
      yield promisify(function(next) {
        // Parse form data.
        // Example: https://github.com/mscdex/busboy
        // TODO: Expose Busboy options to admin, such as upload limits.
        busboy = new Busboy({headers: request.headers });

        // Set file processing.
        busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
          if (filename) {
            post[fieldname] = {
              type: 'file',
              name: filename,
              encoding: encoding,
              mime: mimetype,
              path: path.join(os.tmpdir(), uuid.v4()),
              size: 0,
            };
            file.on('data', data => post[fieldname].size += data.length);
            // TODO: Handle broken, incomplete, and file-too-big errors.
            file.on('limit', () => {});
            file.on('end', () => {});
            file.pipe(fs.createWriteStream(post[fieldname].path));
          }
          else {
            // There was no upload.  Resume the stream to continue processing.
            file.resume();
          }
        });

        // Set regular field processing.
        busboy.on('field', (fieldname, val, fieldnameTruncated, valTruncated) => {
          if (fieldname.substring(fieldname.length - 2) == '[]') {
            // If there is an empty bracket (e.g., '[]') at the end of the
            // fieldname, then this is input from a checkbox or radio button.
            //
            // In this case, treat the value as an element in an object.
            // The value will always a string, so use it for both the key and
{'fraction_non_alphanumeric': 0.1473905562989868, 'fraction_numerical': 0.0011470082202255784, 'mean_word_length': 2.0958579881656805, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 12, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5315445', 'n_tokens_mistral': 1456, 'n_tokens_neox': 1426, 'n_words': 441}