<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

/* eslint-disable react/forbid-prop-types */
import React from 'react';
import PropTypes from 'prop-types';
import { View, TouchableWithoutFeedback, Text, TextInput } from 'react-native';
import { useExpiryDateMask } from '../hooks/useExpiryDateMask';
import Cell from './DataTable/Cell';
import { dataTableColors, newDataTableStyles } from '../globalStyles/index';
import { getAdjustedStyle } from './DataTable/utilities';
import { parseExpiryDate, formatExpiryDate } from '../utilities';

/**
 * Renders an expiry date cell, managing its own state and not submitting
 * a date to be committed to the underlying model until a valid date has
 * been submitted.
 *
 * Similar to EditableCell, this component renders a Cell when disabled,
 * a Text wrapped in a TouchableComponent when un-focused and a TextInput
 * when focused - A workaround for react-native crashes when large numbers
 * of TextInput components are rendered.
 *
 * @param {string|number} value The value to render in cell
 * @param {string|number} rowKey Unique key associated to row cell is in
 * @param {string|number} columnKey Unique key associated to column cell is in
 * @param {bool} disabled If `true` will render a plain Cell element with no interaction
 * @param {bool} isFocused If `false` will TouchableOpacity that dispatches a focusAction
 *                         when pressed. When `true` will render a TextInput with focus
 * @param {func} editAction Action creator for handling editing of this cell.
 *                          `(newValue, rowKey, columnKey) => {...}`
 * @param {func} focusAction Action creator for handling focusing of this cell.
 *                          `(rowKey, columnKey) => {...}`
 * @param {func} focusNextAction Action creator for handling focusing of this cell.
 *                          `(rowKey, columnKey) => {...}`
 * @param {func}  dispatch Reducer dispatch callback for handling actions
 * @param {Number}  width Optional flex property to inject into styles.
 * @param {Bool}  isLastCell Indicator for if this cell is the last
 *                                   in a row. Removing the borderRight if true.
 * @param {String}  placeholder String to display when the cell is empty.
 * @
 *
 */
export const NewExpiryDateInput = React.memo(
  ({
    value,
    rowKey,
    columnKey,
    isDisabled,
    isFocused,
    editAction,
    focusAction,
    focusNextAction,
    dispatch,
    isLastCell,
    width,
    debug,
    placeholder,
  }) => {
    if (debug) console.log(`- ExpiryTextInputCell: ${value}`);

    // Customhook managing the editing of an expiry date to stay valid.
    const [expiryDate, finalseExpiryDate, setExpiryDate] = useExpiryDateMask(
      formatExpiryDate(value)
    );

    // Helpers controlling the submitting of the expiry date. Losing focus/submitting
    // Handed similarly, but losing focus will not auto focus the next cell. Changes
    // to the underlying model are not committed until a valid date is entered.
    const finishEditingExpiryDate = () => {
      finalseExpiryDate();
      dispatch(editAction(parseExpiryDate(expiryDate), rowKey, columnKey));
    };

    const onSubmit = () => {
      finishEditingExpiryDate();
      dispatch(focusNextAction(focusNextAction(rowKey, columnKey)));
    };

    const usingPlaceholder = placeholder && !expiryDate;
    const {
      expiryBatchTextView,
      expiryBatchViewStyle,
      expiryBatchText,
      expiryBatchPlaceholderText,
    } = newDataTableStyles;

    const textStyle = usingPlaceholder ? expiryBatchPlaceholderText : expiryBatchText;

    // Render a plain Cell if disabled.
    if (isDisabled) {
      return (
        <Cell
          key={columnKey}
          viewStyle={expiryBatchViewStyle}
          textStyle={textStyle}
          value={usingPlaceholder ? 'N/A' : expiryDate}
          width={width}
          isLastCell={isLastCell}
        />
      );
    }

    const internalViewStyle = getAdjustedStyle(expiryBatchViewStyle, width, isLastCell);

    // Too many TextInputs causes React Native to crash, so only
    // truly mount the TextInput when the Cell is focused.
    // Use TouchableWithoutFeedback because we want the appearance and
    // feedback to resemble a TextInput regardless of focus.
    if (!isFocused) {
      const text = usingPlaceholder ? placeholder : expiryDate;

      return (
        <TouchableWithoutFeedback onPress={dispatch(focusAction(rowKey, columnKey))}>
          <View style={internalViewStyle}>
            <View style={expiryBatchTextView}>
              <Text ellipsizeMode="tail" numberOfLines={1} style={textStyle}>
                {text}
              </Text>
            </View>
          </View>
        </TouchableWithoutFeedback>
      );
    }

    // Render a Cell with a textInput.
    return (
      <View style={internalViewStyle}>
        <TextInput
          placeholder={placeholder}
          style={textStyle}
          value={expiryDate}
          onChangeText={setExpiryDate}
          autoFocus={isFocused}
          onSubmitEditing={onSubmit}
          onEndEditing={finishEditingExpiryDate}
          underlineColorAndroid={dataTableColors.editableCellUnderline}
          keyboardType="numeric"
          selectTextOnFocus
        />
      </View>
    );
  }
);

NewExpiryDateInput.propTypes = {
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  columnKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  isDisabled: PropTypes.bool,
  isFocused: PropTypes.bool,
  editAction: PropTypes.func.isRequired,
  focusAction: PropTypes.func.isRequired,
  focusNextAction: PropTypes.func.isRequired,
  dispatch: PropTypes.func.isRequired,
  width: PropTypes.number,
  isLastCell: PropTypes.bool,
  debug: PropTypes.bool,
  placeholder: PropTypes.string,
};

NewExpiryDateInput.defaultProps = {
  value: '',
  isDisabled: false,
  isFocused: false,
  isLastCell: false,
  width: 0,
  debug: false,
  placeholder: 'mm/yyyy',
};

export default NewExpiryDateInput;
<commit_msg>Add dispatch fix<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

/* eslint-disable react/forbid-prop-types */
import React from 'react';
import PropTypes from 'prop-types';
import { View, TouchableWithoutFeedback, Text, TextInput } from 'react-native';
import { useExpiryDateMask } from '../hooks/useExpiryDateMask';
import Cell from './DataTable/Cell';
import { dataTableColors, newDataTableStyles } from '../globalStyles/index';
import { getAdjustedStyle } from './DataTable/utilities';
import { parseExpiryDate, formatExpiryDate } from '../utilities';

/**
 * Renders an expiry date cell, managing its own state and not submitting
 * a date to be committed to the underlying model until a valid date has
 * been submitted.
 *
 * Similar to EditableCell, this component renders a Cell when disabled,
 * a Text wrapped in a TouchableComponent when un-focused and a TextInput
 * when focused - A workaround for react-native crashes when large numbers
 * of TextInput components are rendered.
 *
 * @param {string|number} value The value to render in cell
 * @param {string|number} rowKey Unique key associated to row cell is in
 * @param {string|number} columnKey Unique key associated to column cell is in
 * @param {bool} disabled If `true` will render a plain Cell element with no interaction
 * @param {bool} isFocused If `false` will TouchableOpacity that dispatches a focusAction
 *                         when pressed. When `true` will render a TextInput with focus
 * @param {func} editAction Action creator for handling editing of this cell.
 *                          `(newValue, rowKey, columnKey) => {...}`
 * @param {func} focusAction Action creator for handling focusing of this cell.
 *                          `(rowKey, columnKey) => {...}`
 * @param {func} focusNextAction Action creator for handling focusing of this cell.
 *                          `(rowKey, columnKey) => {...}`
 * @param {func}  dispatch Reducer dispatch callback for handling actions
 * @param {Number}  width Optional flex property to inject into styles.
 * @param {Bool}  isLastCell Indicator for if this cell is the last
 *                                   in a row. Removing the borderRight if true.
 * @param {String}  placeholder String to display when the cell is empty.
 * @
 *
 */
export const NewExpiryDateInput = React.memo(
  ({
    value,
    rowKey,
    columnKey,
    isDisabled,
    isFocused,
    editAction,
    focusAction,
    focusNextAction,
    dispatch,
    isLastCell,
    width,
    debug,
    placeholder,
  }) => {
    if (debug) console.log(`- ExpiryTextInputCell: ${value}`);

    // Customhook managing the editing of an expiry date to stay valid.
    const [expiryDate, finalseExpiryDate, setExpiryDate] = useExpiryDateMask(
      formatExpiryDate(value)
    );

    // Helpers controlling the submitting of the expiry date. Losing focus/submitting
    // Handed similarly, but losing focus will not auto focus the next cell. Changes
    // to the underlying model are not committed until a valid date is entered.
    const finishEditingExpiryDate = () => {
      finalseExpiryDate();
      dispatch(editAction(parseExpiryDate(expiryDate), rowKey, columnKey));
    };

    const onSubmit = () => {
      finishEditingExpiryDate();
      dispatch(focusNextAction(focusNextAction(rowKey, columnKey)));
    };

    const usingPlaceholder = placeholder && !expiryDate;
    const {
      expiryBatchTextView,
      expiryBatchViewStyle,
      expiryBatchText,
      expiryBatchPlaceholderText,
    } = newDataTableStyles;

    const textStyle = usingPlaceholder ? expiryBatchPlaceholderText : expiryBatchText;

    // Render a plain Cell if disabled.
    if (isDisabled) {
      return (
        <Cell
          key={columnKey}
          viewStyle={expiryBatchViewStyle}
          textStyle={textStyle}
          value={usingPlaceholder ? 'N/A' : expiryDate}
          width={width}
          isLastCell={isLastCell}
        />
      );
    }

    const internalViewStyle = getAdjustedStyle(expiryBatchViewStyle, width, isLastCell);

    // Too many TextInputs causes React Native to crash, so only
    // truly mount the TextInput when the Cell is focused.
    // Use TouchableWithoutFeedback because we want the appearance and
    // feedback to resemble a TextInput regardless of focus.
    if (!isFocused) {
      const text = usingPlaceholder ? placeholder : expiryDate;

      return (
        <TouchableWithoutFeedback onPress={() => dispatch(focusAction(rowKey, columnKey))}>
          <View style={internalViewStyle}>
            <View style={expiryBatchTextView}>
              <Text ellipsizeMode="tail" numberOfLines={1} style={textStyle}>
                {text}
              </Text>
            </View>
          </View>
        </TouchableWithoutFeedback>
      );
    }

    // Render a Cell with a textInput.
    return (
      <View style={internalViewStyle}>
        <TextInput
          placeholder={placeholder}
          style={textStyle}
          value={expiryDate}
          onChangeText={setExpiryDate}
          autoFocus={isFocused}
          onSubmitEditing={onSubmit}
          onEndEditing={finishEditingExpiryDate}
          underlineColorAndroid={dataTableColors.editableCellUnderline}
          keyboardType="numeric"
          selectTextOnFocus
        />
      </View>
    );
  }
);

NewExpiryDateInput.propTypes = {
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  columnKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  isDisabled: PropTypes.bool,
  isFocused: PropTypes.bool,
  editAction: PropTypes.func.isRequired,
  focusAction: PropTypes.func.isRequired,
  focusNextAction: PropTypes.func.isRequired,
  dispatch: PropTypes.func.isRequired,
  width: PropTypes.number,
  isLastCell: PropTypes.bool,
  debug: PropTypes.bool,
  placeholder: PropTypes.string,
};

NewExpiryDateInput.defaultProps = {
  value: '',
  isDisabled: false,
  isFocused: false,
  isLastCell: false,
  width: 0,
  debug: false,
  placeholder: 'mm/yyyy',
};

export default NewExpiryDateInput;
<|endoftext|>


<commit_before>
/*
progress.auth.js    Version: 4.3.0-1

Copyright (c) 2016 Progress Software Corporation and/or its subsidiaries or affiliates.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

 */

(function () {

    "use strict";

    /*global progress : true, btoa*/
    /*global $ : false*/

    /* define these if not defined yet - they may already be defined if
       progress.js was included first */
    if (typeof progress === "undefined") {
        progress = {};
    }
    if (typeof progress.data === "undefined") {
        progress.data = {};
    }

    progress.data.AuthenticationProvider = function (options) {
        var authenticationURI,
            tokenLocation,
            defaultHeaderName = "X-OE-CLIENT-CONTEXT-ID",
            that = this;

        // PROPERTIES
        Object.defineProperty(this, 'authenticationURI',
            {
                get: function () {
                    return authenticationURI;
                },
                enumerable: true
            });

        Object.defineProperty(this, 'tokenLocation',
            {
                get: function () {
                    return tokenLocation;
                },
                enumerable: true
            });

        Object.defineProperty(this, 'token',
            {
                set: function (val) {
                    sessionStorage.setItem(authenticationURI, val);
                },
                get: function () {
                    return sessionStorage.getItem(authenticationURI);
                },
                enumerable: false
            });

        if (typeof options === "undefined") {
            throw new Error(progress.data._getMsgText("jsdoMSG038", "1"));
        }

        if (options.authenticationURI) {
            authenticationURI = options.authenticationURI;
        } else {
            throw new Error(progress.data._getMsgText("jsdoMSG048", "AuthenticationProvider", "Constructor",
                                                      "options", "authenticationURI"));
        }

        if (options.tokenLocation) {
            tokenLocation = options.tokenLocation;
        } else {
            // Give it a default location
            tokenLocation = {
                headerName : defaultHeaderName
            };
        }

        // PRIVATE FUNCTIONS

        function openTokenRequest(xhr, authProvider, credentials) {
            xhr.open('POST', authProvider.authenticationURI, true);
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xhr.setRequestHeader("Cache-Control", "max-age=0");
            xhr.withCredentials = true;
            xhr.setRequestHeader("Accept", "application/json");
        }

        function processAuthResult(xhr) {
            var token,
                errorObject,
                result;

            if (that.deferred) {
                if (xhr.status === 200) {
                    // get token and store it; if that goes well, resolve the promise, otherwise reject it
                    try {
                        token = that.getTokenFromXHR({xhr: xhr});
                        that.token = token;
                        result = progress.data.Session.SUCCESS;
                    } catch (e) {
                        result = progress.data.Session.AUTHENTICATION_FAILURE;
                        errorObject = e;
                    }
                } else if (xhr.status === 401 || xhr.status === 403) {
                    result = progress.data.Session.AUTHENTICATION_FAILURE;
                } else {
                    result = progress.data.Session.GENERAL_FAILURE;
                }

                if (result === progress.data.Session.SUCCESS) {
                    that.deferred.resolve(
                        that,
                        result,
                        {
                            "xhr": xhr
                        }
                    );
                } else {
                    that.deferred.reject(
                        that,
                        result,
                        {
                            errorObject : errorObject, // might be undefined, that's OK
                            xhr: xhr
                        }
                    );
                }
            } else {
                throw new Error("deferred missing from xhr when processing authenticate");
            }
        }

        // METHODS
        this.authenticate = function (options) {
            var deferred = $.Deferred(),
                errorObject,
                xhr;

            xhr = new XMLHttpRequest();

            openTokenRequest(xhr, this, options);

// DELETE THIS FOR REAL IMPLEMENTATION (ASSUMING THAT THE REAL IMPL DOESN'T REQUIRE 2 CALLS)
            xhr.onreadystatechange = function () {
                var errorObject;

                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        xhr.open('GET', "http://172.30.1.11:8810/TokenServer/web/getcp", true);
                        xhr.setRequestHeader("Cache-Control", "no-cache");
                        xhr.setRequestHeader("Pragma", "no-cache");
                        xhr.withCredentials = true;
                        xhr.setRequestHeader("Accept", "application/json");
// END OF DELETION FOR REAL IMPLEMENTATION
                        xhr.onreadystatechange = function () {
                            var errorObject;

                            if (xhr.readyState === 4) {
                                errorObject = null;
                // NOTE: if we keep this as a closure rather than implementing a separate generic
                // readystatechange handler, we can get rid of the xhr.onResponseFn property and just call
                // processAuthResult directly (remove its assignment just before the send at the
                // end of authenticate() )
                                // process the response from the Web application
                                if ((typeof xhr.onResponseFn) === 'function') {
                                    try {
                                        xhr.onResponseFn(xhr);
                                    } catch (e) {
                                        errorObject = e;
                                    }
                                }
                            }
                        };

// DELETE THIS SEND() FOR REAL IMPLEMENTATION
                        xhr.send();
                    }
                }

            };

            xhr.onResponseFn = processAuthResult;
            xhr.send("j_username=" + options.userName + "&j_password=" + options.password + "&submit=Submit");
            return deferred;

        };

        // finds the token in a successful response from a token provider and returns it
        this.getTokenFromXHR = function (options) {
            try {
                return options.xhr.getResponseHeader(this.tokenLocation.headerName);
            } catch (e) {
                throw new Error("Unexpected error authenticating:" + e.message); // add to JSDOMessages
            }
        };
    };

}());

<commit_msg>simplified thanks to previous addition of closure; added error handling<commit_after>
/*
progress.auth.js    Version: 4.3.0-2

Copyright (c) 2016 Progress Software Corporation and/or its subsidiaries or affiliates.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

 */

(function () {

    "use strict";

    /*global progress : true, btoa*/
    /*global $ : false*/

    /* define these if not defined yet - they may already be defined if
       progress.js was included first */
    if (typeof progress === "undefined") {
        progress = {};
    }
    if (typeof progress.data === "undefined") {
        progress.data = {};
    }

    progress.data.AuthenticationProvider = function (options) {
        var authenticationURI,
            tokenLocation,
            defaultHeaderName = "X-OE-CLIENT-CONTEXT-ID",
            that = this;

        // PROPERTIES
        Object.defineProperty(this, 'authenticationURI',
            {
                get: function () {
                    return authenticationURI;
                },
                enumerable: true
            });

        Object.defineProperty(this, 'tokenLocation',
            {
                get: function () {
                    return tokenLocation;
                },
                enumerable: true
            });

        Object.defineProperty(this, 'token',
            {
                set: function (val) {
                    sessionStorage.setItem(authenticationURI, val);
                },
                get: function () {
                    return sessionStorage.getItem(authenticationURI);
                },
                enumerable: false
            });

        if (typeof options === "undefined") {
            // Too few arguments. There must be at least {1}.
            throw new Error(progress.data._getMsgText("jsdoMSG038", "1"));
        }

        if (options.authenticationURI) {
            authenticationURI = options.authenticationURI;
        } else {
            // {2} method has argument '{3}' that is missing property '{4}'
            throw new Error(progress.data._getMsgText("jsdoMSG048", "AuthenticationProvider", "Constructor",
                                                      "options", "authenticationURI"));
        }

        if (options.tokenLocation) {
            tokenLocation = options.tokenLocation;
        } else {
            // Give it a default location
            tokenLocation = {
                headerName : defaultHeaderName
            };
        }

        // PRIVATE FUNCTIONS

        function openTokenRequest(xhr, authProvider, credentials) {
            xhr.open('POST', authProvider.authenticationURI, true);
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xhr.setRequestHeader("Cache-Control", "max-age=0");
            xhr.withCredentials = true;
            xhr.setRequestHeader("Accept", "application/json");
        }

        function processAuthResult(xhr, deferred) {
            var token,
                errorObject,
                result;

            if (deferred) {
                if (xhr.status === 200) {
                    // get token and store it; if that goes well, resolve the promise, otherwise reject it
                    try {
                        that.token = xhr.getResponseHeader(that.tokenLocation.headerName);
                        if (that.token) {
                            result = progress.data.Session.SUCCESS;
                        } else {
                            result = progress.data.Session.AUTHENTICATION_FAILURE;
                            // " Unexpected error authenticating: No token returned from server"
                            errorObject = new Error(progress.data._getMsgText(
                                "jsdoMSG049",
                                "AuthenticationProvider",
                                progress.data._getMsgText("jsdoMSG050")
                            ));
                        }
                    } catch (e) {
                        result = progress.data.Session.AUTHENTICATION_FAILURE;
                           //  Unexpected error authenticating: {2}
                        errorObject = new Error(progress.data._getMsgText(
                            "jsdoMSG049",
                            "AuthenticationProvider",
                            e.message
                        )
                            ); // incomprehensible indentation choice, but what jslint wants, jslint gets!
                    }
                } else if (xhr.status === 401 || xhr.status === 403) {
                    result = progress.data.Session.AUTHENTICATION_FAILURE;
                } else {
                    result = progress.data.Session.GENERAL_FAILURE;
                }

                if (result === progress.data.Session.SUCCESS) {
                    deferred.resolve(
                        that,
                        result,
                        {
                            "xhr": xhr
                        }
                    );
                } else {
                    deferred.reject(
                        that,
                        result,
                        {
                            errorObject : errorObject, // might be undefined, that's OK
                            xhr: xhr
                        }
                    );
                }
            } else {
                throw new Error("deferred missing when processing authenticate result");
            }
        }

        // METHODS
        this.authenticate = function (options) {
            var deferred = $.Deferred(),
                xhr;

            if (this.token) {
                // "authenticate() failed because the AuthenticationProvider is already managing a
                // successful authentication."
                throw new Error(progress.data._getMsgText("jsdoMSG051", "AuthenticationProvider"));
            }

            xhr = new XMLHttpRequest();

            openTokenRequest(xhr, this, options);

// DELETE THIS FOR REAL IMPLEMENTATION (ASSUMING THAT THE REAL IMPL DOESN'T REQUIRE 2 CALLS)
            xhr.onreadystatechange = function () {

                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        xhr.open('GET', "http://localhost:8810/TS4/web/getcp", true);
                        xhr.setRequestHeader("Cache-Control", "no-cache");
                        xhr.setRequestHeader("Pragma", "no-cache");
                        xhr.withCredentials = true;
                        xhr.setRequestHeader("Accept", "application/json");
// END OF DELETION FOR REAL IMPLEMENTATION
                        xhr.onreadystatechange = function () {
                            if (xhr.readyState === 4) {
                                // process the response from the Web application
                                processAuthResult(xhr, deferred);
                            }
                        };

// DELETE THIS SEND() FOR REAL IMPLEMENTATION
                        xhr.send();
                    }
                }

            };

            xhr.send("j_username=" + options.userName + "&j_password=" + options.password + "&submit=Submit");
            return deferred;

        };

    };

}());

<|endoftext|>


<commit_before>/* Модуль сжатия js-скриптов, css-стилей, html-файлов и
 * конвертации картинок в css-стилях
 * в base64 и помещения их в файл стилей
 */
(function() {
    'use strict';

    var DIR         = __dirname +'/',
        LIBDIR      = DIR + 'lib/',
        os          = require('os'),
        main        = require(LIBDIR + 'main'),
        img         = main.require(LIBDIR + 'img'),
        mkdirp      = main.require('mkdirp'),
        platform    = process.platform,
        WIN32       = platform === 'win32',
        crypto      = main.crypto,
        fs          = main.fs,
        path        = main.path,
        Util        = main.util,

        TMPDIR, MinFolder;

    if (os.tmpdir) {
        TMPDIR      = os.tmpdir();
        MinFolder      = TMPDIR + '/minify/';

        if (!WIN32)
            MinFolder += process.getuid() + '/';
    } else {
        MinFolder   = DIR + '/min/';
    }

    /* Trying to create folder min
     * where woud be minifyed versions
     * of files 511(10)=777(8)
     * rwxrwxrwx
     */
    function makeDir(callback) {
        fs.exists(MinFolder, function(exist) {
            var func = function(status, error) {
                Util.exec(callback, error);
            };

            Util.ifExec(exist || !mkdirp, func, function(callback) {
                mkdirp(MinFolder, 511, callback);
            });
        });
    }

    /**
     * function minificate js,css and html files
     *
     * @param files     -   js, css or html file path
     * @param options   -   object contain main options
     */
    function optimize(file, options) {
        makeDir(function(error) {
            var name,
                isObj   = Util.isObject(file);

            if (error)
                Util.log(error);

            if (isObj)
                name    = Object.keys(file)[0];
            else
                name    = file;

            Util.log('minify: reading file ' + path.basename(name) + '...');

             fs.readFile(name, 'utf8', Util.bind(fileRead, {
                name            : name,
                optimizeParams  : file,
                options         : options,
                callback        : onDataRead
            }));
        });
    }

   /**
    * Processing of files
    * @param fileData {name, data}
    */
    function onDataRead(fileData, error, data) {
        var ext, minFileName,
            readFilesCount  = 0,
            options         = fileData.options,
            filename        = fileData.name;

        Util.log('minify: file ' + path.basename(filename) + ' read');

        if (error) {
            options.callback(error);
        } else {
            ext         = Util.getExtension(filename);
            minFileName = getName(filename, ext);

            data        = main.optimize({
                ext : ext,
                data: data
            });

            Util.ifExec(ext !== '.css', function(optimizedData) {
                var ret = Util.isString(optimizedData);

                if (ret)
                    data    = optimizedData;

                ++readFilesCount;

                writeFile(minFileName, data, function(dataMin) {
                    if (options)
                        if (options.returnName)
                             Util.exec(options.callback, null, {
                                 name: minFileName
                             });
                         else
                            Util.exec(options.callback, null, dataMin);
                    });
                }, function(callback) {
                    img.optimize(filename, data, callback);
                });
        }
    }

    /**
     * function get name of file in min folder
     *
     * @param name
     * @param ext
     */
    function getName(name, ext) {
        var ret, minFileName;

        if (Util.isString(name)) {
            if (!ext)
                ext         = Util.getExtension(name);

            minFileName = crypto.createHash('sha1')
                .update(name)
                .digest('hex') + ext;

            ret = MinFolder + minFileName;
        }

        return ret;
    }

    function fileRead(params, error, data) {
        Util.log(error);

        if (params)
            Util.exec(params.callback, params, error, data);
    }

    /*
     * Функция записывает файла
     * и выводит ошибку или сообщает,
     * что файл успешно записан
     */
    function writeFile(name, data, callback) {
        fs.writeFile(name, data, function(error) {
            if (error)
                Util.log(error);
            else {
                name = path.basename(name);
                Util.log('minify: file ' + name + ' written...');
            }

            Util.exec(callback, data);
        });
    }

    exports.getName     = getName;
    exports.optimize    = optimize;
    exports.MinFolder   = MinFolder;

})();
<commit_msg>chore(minify) add " "<commit_after>/* Модуль сжатия js-скриптов, css-стилей, html-файлов и
 * конвертации картинок в css-стилях
 * в base64 и помещения их в файл стилей
 */
(function() {
    'use strict';

    var DIR         = __dirname +'/',
        LIBDIR      = DIR + 'lib/',
        os          = require('os'),
        main        = require(LIBDIR + 'main'),
        img         = main.require(LIBDIR + 'img'),
        mkdirp      = main.require('mkdirp'),
        platform    = process.platform,
        WIN32       = platform === 'win32',
        crypto      = main.crypto,
        fs          = main.fs,
        path        = main.path,
        Util        = main.util,

        TMPDIR, MinFolder;

    if (os.tmpdir) {
        TMPDIR      = os.tmpdir();
        MinFolder      = TMPDIR + '/minify/';

        if (!WIN32)
            MinFolder += process.getuid() + '/';
    } else {
        MinFolder   = DIR + '/min/';
    }

    /* Trying to create folder min
     * where woud be minifyed versions
     * of files 511(10)=777(8)
     * rwxrwxrwx
     */
    function makeDir(callback) {
        fs.exists(MinFolder, function(exist) {
            var func = function(status, error) {
                Util.exec(callback, error);
            };

            Util.ifExec(exist || !mkdirp, func, function(callback) {
                mkdirp(MinFolder, 511, callback);
            });
        });
    }

    /**
     * function minificate js,css and html files
     *
     * @param files     -   js, css or html file path
     * @param options   -   object contain main options
     */
    function optimize(file, options) {
        makeDir(function(error) {
            var name,
                isObj   = Util.isObject(file);

            if (error)
                Util.log(error);

            if (isObj)
                name    = Object.keys(file)[0];
            else
                name    = file;

            Util.log('minify: reading file ' + path.basename(name) + '...');

             fs.readFile(name, 'utf8', Util.bind(fileRead, {
                name            : name,
                optimizeParams  : file,
                options         : options,
                callback        : onDataRead
            }));
        });
    }

   /**
    * Processing of files
    * @param fileData {name, data}
    */
    function onDataRead(fileData, error, data) {
        var ext, minFileName,
            readFilesCount  = 0,
            options         = fileData.options,
            filename        = fileData.name;

        Util.log('minify: file ' + path.basename(filename) + ' read');

        if (error) {
            options.callback(error);
        } else {
            ext         = Util.getExtension(filename);
            minFileName = getName(filename, ext);

            data        = main.optimize({
                ext : ext,
                data: data
            });

            Util.ifExec(ext !== '.css', function(optimizedData) {
                var ret = Util.isString(optimizedData);

                if (ret)
                    data    = optimizedData;

                ++readFilesCount;

                writeFile(minFileName, data, function(dataMin) {
                    if (options)
                        if (options.returnName)
                             Util.exec(options.callback, null, {
                                 name: minFileName
                             });
                         else
                            Util.exec(options.callback, null, dataMin);
                    });
                }, function(callback) {
                    img.optimize(filename, data, callback);
                });
        }
    }

    /**
     * function get name of file in min folder
     *
     * @param name
     * @param ext
     */
    function getName(name, ext) {
        var ret, minFileName;

        if (Util.isString(name)) {
            if (!ext)
                ext         = Util.getExtension(name);

            minFileName = crypto.createHash('sha1')
                .update(name)
                .digest('hex') + ext;

            ret = MinFolder + minFileName;
        }

        return ret;
    }

    function fileRead(params, error, data) {
        Util.log(error);

        if (params)
            Util.exec(params.callback, params, error, data);
    }

    /*
     * Функция записывает файла
     * и выводит ошибку или сообщает,
     * что файл успешно записан
     */
    function writeFile(name, data, callback) {
        fs.writeFile(name, data, function(error) {
            if (error)
                Util.log(error);
            else {
                name = path.basename(name);
                Util.log('minify: file ' + name + ' written...');
            }

            Util.exec(callback, data);
        });
    }

    exports.getName     = getName;
    exports.optimize    = optimize;
    exports.MinFolder   = MinFolder;

})();
<|endoftext|>


<commit_before>// @flow

import type { Project } from './types';

const { Lokka } = require('lokka');
const { Transport } = require('lokka-transport-http');
const R = require('ramda');
const { createJWTWithoutSshKey } = require('./jwt');
const { logger } = require('./local-logging');

const { JWTSECRET, JWTAUDIENCE } = process.env;
const API_HOST = R.propOr('http://api:3000', 'API_HOST', process.env);

if (JWTSECRET == null) {
  logger.warn(
    'No JWTSECRET env variable set... this will cause api requests to fail',
  );
}

if (JWTAUDIENCE == null) {
  logger.warn(
    'No JWTAUDIENCE env variable set... this *might* cause api requests to fail',
  );
}

const apiAdminToken = createJWTWithoutSshKey({
  payload: {
    role: 'admin',
    iss: 'lagoon-commons',
    aud: JWTAUDIENCE || 'api.amazee.io',
  },
  jwtSecret: JWTSECRET || '',
});

const options = {
  headers: {
    Authorization: `Bearer ${apiAdminToken}`,
  },
};

const transport = new Transport(`${API_HOST}/graphql`, options);

const graphqlapi = new Lokka({ transport });

class ProjectNotFound extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'ProjectNotFound';
  }
}

class EnvironmentNotFound extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'EnvironmentNotFound';
  }
}

class NoActiveSystemsDefined extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'NoActiveSystemsDefined';
  }
}

async function getProjectsByGitUrl(gitUrl: string): Promise<Project[]> {
  const result = await graphqlapi.query(`
    {
      allProjects(gitUrl: "${gitUrl}") {
        name
        production_environment
        openshift {
          console_url
          token
          project_user
          router_pattern
        }
      }
    }
  `);

  if (!result || !result.allProjects || !result.allProjects.length) {
    throw new ProjectNotFound(`Cannot find project for git repo ${gitUrl}`);
  }

  return result.allProjects;
}

async function getRocketChatInfoForProject(project: string): Project {
  const notificationsFragment = graphqlapi.createFragment(`
    fragment on NotificationRocketChat {
      webhook
      channel
    }
  `);

  const result = await graphqlapi.query(`
    {
      project:projectByName(name: "${project}") {
        rocketchats: notifications(type: ROCKETCHAT) {
          ...${notificationsFragment}
        }
      }
    }
  `);

  if (!result || !result.project || !result.project.rocketchats) {
    throw new ProjectNotFound(
      `Cannot find rocketchat information for project ${project}`,
    );
  }

  return result.project.rocketchats;
}

async function getSlackinfoForProject(project: string): Promise<Project> {
  const notificationsFragment = graphqlapi.createFragment(`
    fragment on NotificationSlack {
      webhook
      channel
    }
  `);

  const result = await graphqlapi.query(`
    {
      project:projectByName(name: "${project}") {
        slacks: notifications(type: SLACK) {
          ...${notificationsFragment}
        }
      }
    }
  `);

  if (!result || !result.project || !result.project.slacks) {
    throw new ProjectNotFound(
      `Cannot find slack information for project ${project}`,
    );
  }

  return result.project.slacks;
}

async function getActiveSystemForProject(
  project: string,
  task: string,
): Promise<Object> {
  const result = await graphqlapi.query(`
    {
      project:projectByName(name: "${project}"){
        active_systems_${task}
        branches
        pullrequests
      }
    }
  `);

  if (!result || !result.project) {
    throw new ProjectNotFound(
      `Cannot find active-systems information for project ${project}`,
    );
  }

  if (!result.project[`active_systems_${task}`]) {
    throw new NoActiveSystemsDefined(
      `Cannot find active system for task ${task} in project ${project}`,
    );
  }

  return result.project;
}

async function getEnvironmentByName(
  name: string,
  projectId: number
): Promise<Project[]> {
  const result = await graphqlapi.query(`
    {
      environmentByName(name: "${name}",project:${projectId}) {
        id,
        name,
        lagoon_route,
        lagoon_routes,
        deploy_type,
        environment_type,
        openshift_projectname,
        updated,
        created,
        deleted,
      }
    }
  `);

  if (!result || !result.environmentByName) {
    throw new EnvironmentNotFound(`Cannot find environment for projectId ${projectId}, name ${name}\n${result.environmentByName}`);
  }

  return result;
}

const addOrUpdateEnvironment = (
  name: string,
  projectId: number,
  deploy_type: string,
  environment_type: string,
  openshift_projectname: string,
): Promise<Object> =>
  graphqlapi.query(`
  mutation {
    addOrUpdateEnvironment(input: {
        name: "${name}",
        project: ${projectId},
        deploy_type: ${deploy_type},
        environment_type: ${environment_type},
        openshift_projectname: "${openshift_projectname}"
    }) {
      id
      name
      project {
        name
      }
      deploy_type
      environment_type
      openshift_projectname
    }
  }
`);

const updateEnvironment = (
  name: string,
  projectId: number,
  patch: string,
): Promise<Object> =>
  graphqlapi.query(`
    mutation {
      updateEnvironment(input: {
        project: ${projectId},
        name: "${name}",
        patch: "${patch}"
      }) {
        id
        name
      }
    }
  `);

async function deleteEnvironment(
  name: string,
  project: string,
): Promise<Object> {
  const result = await graphqlapi.query(`
    {
      project:projectByName(name: "${project}"){
        id
      }
    }
  `);

  if (!result || !result.project) {
    throw new ProjectNotFound(`Cannot load id for project ${project}`);
  }

  return graphqlapi.query(`
    mutation {
      deleteEnvironment(input: {name: "${name}", project: ${result.project.id}})
    }
  `);
}

const getOpenShiftInfoForProject = (project: string): Promise<Object> =>
  graphqlapi.query(`
    {
      project:projectByName(name: "${project}"){
        id
        openshift  {
          console_url
          token
          project_user
          router_pattern
        }
        customer {
          private_key
        }
        git_url
        subfolder
        openshift_project_pattern
        production_environment
      }
    }
`);

const getProductionEnvironmentForProject = (project: string): Promise<Object> =>
  graphqlapi.query(`
    {
      project:projectByName(name: "${project}"){
        production_environment
      }
    }
`);

module.exports = {
  getProjectsByGitUrl,
  getRocketChatInfoForProject,
  getSlackinfoForProject,
  getActiveSystemForProject,
  getOpenShiftInfoForProject,
  getProductionEnvironmentForProject,
  addOrUpdateEnvironment,
  deleteEnvironment,
};
<commit_msg>#492 - update needs the environmentId, no quotes on the patch<commit_after>// @flow

import type { Project } from './types';

const { Lokka } = require('lokka');
const { Transport } = require('lokka-transport-http');
const R = require('ramda');
const { createJWTWithoutSshKey } = require('./jwt');
const { logger } = require('./local-logging');

const { JWTSECRET, JWTAUDIENCE } = process.env;
const API_HOST = R.propOr('http://api:3000', 'API_HOST', process.env);

if (JWTSECRET == null) {
  logger.warn(
    'No JWTSECRET env variable set... this will cause api requests to fail',
  );
}

if (JWTAUDIENCE == null) {
  logger.warn(
    'No JWTAUDIENCE env variable set... this *might* cause api requests to fail',
  );
}

const apiAdminToken = createJWTWithoutSshKey({
  payload: {
    role: 'admin',
    iss: 'lagoon-commons',
    aud: JWTAUDIENCE || 'api.amazee.io',
  },
  jwtSecret: JWTSECRET || '',
});

const options = {
  headers: {
    Authorization: `Bearer ${apiAdminToken}`,
  },
};

const transport = new Transport(`${API_HOST}/graphql`, options);

const graphqlapi = new Lokka({ transport });

class ProjectNotFound extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'ProjectNotFound';
  }
}

class EnvironmentNotFound extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'EnvironmentNotFound';
  }
}

class NoActiveSystemsDefined extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'NoActiveSystemsDefined';
  }
}

async function getProjectsByGitUrl(gitUrl: string): Promise<Project[]> {
  const result = await graphqlapi.query(`
    {
      allProjects(gitUrl: "${gitUrl}") {
        name
        production_environment
        openshift {
          console_url
          token
          project_user
          router_pattern
        }
      }
    }
  `);

  if (!result || !result.allProjects || !result.allProjects.length) {
    throw new ProjectNotFound(`Cannot find project for git repo ${gitUrl}`);
  }

  return result.allProjects;
}

async function getRocketChatInfoForProject(project: string): Project {
  const notificationsFragment = graphqlapi.createFragment(`
    fragment on NotificationRocketChat {
      webhook
      channel
    }
  `);

  const result = await graphqlapi.query(`
    {
      project:projectByName(name: "${project}") {
        rocketchats: notifications(type: ROCKETCHAT) {
          ...${notificationsFragment}
        }
      }
    }
  `);

  if (!result || !result.project || !result.project.rocketchats) {
    throw new ProjectNotFound(
      `Cannot find rocketchat information for project ${project}`,
    );
  }

  return result.project.rocketchats;
}

async function getSlackinfoForProject(project: string): Promise<Project> {
  const notificationsFragment = graphqlapi.createFragment(`
    fragment on NotificationSlack {
      webhook
      channel
    }
  `);

  const result = await graphqlapi.query(`
    {
      project:projectByName(name: "${project}") {
        slacks: notifications(type: SLACK) {
          ...${notificationsFragment}
        }
      }
    }
  `);

  if (!result || !result.project || !result.project.slacks) {
    throw new ProjectNotFound(
      `Cannot find slack information for project ${project}`,
    );
  }

  return result.project.slacks;
}

async function getActiveSystemForProject(
  project: string,
  task: string,
): Promise<Object> {
  const result = await graphqlapi.query(`
    {
      project:projectByName(name: "${project}"){
        active_systems_${task}
        branches
        pullrequests
      }
    }
  `);

  if (!result || !result.project) {
    throw new ProjectNotFound(
      `Cannot find active-systems information for project ${project}`,
    );
  }

  if (!result.project[`active_systems_${task}`]) {
    throw new NoActiveSystemsDefined(
      `Cannot find active system for task ${task} in project ${project}`,
    );
  }

  return result.project;
}

async function getEnvironmentByName(
  name: string,
  projectId: number
): Promise<Project[]> {
  const result = await graphqlapi.query(`
    {
      environmentByName(name: "${name}",project:${projectId}) {
        id,
        name,
        lagoon_route,
        lagoon_routes,
        deploy_type,
        environment_type,
        openshift_projectname,
        updated,
        created,
        deleted,
      }
    }
  `);

  if (!result || !result.environmentByName) {
    throw new EnvironmentNotFound(`Cannot find environment for projectId ${projectId}, name ${name}\n${result.environmentByName}`);
  }

  return result;
}

const addOrUpdateEnvironment = (
  name: string,
  projectId: number,
  deploy_type: string,
  environment_type: string,
  openshift_projectname: string,
): Promise<Object> =>
  graphqlapi.query(`
  mutation {
    addOrUpdateEnvironment(input: {
        name: "${name}",
        project: ${projectId},
        deploy_type: ${deploy_type},
        environment_type: ${environment_type},
        openshift_projectname: "${openshift_projectname}"
    }) {
      id
      name
      project {
        name
      }
      deploy_type
      environment_type
      openshift_projectname
    }
  }
`);

const updateEnvironment = (
  name: string,
  environmentId: number,
  patch: string,
): Promise<Object> =>
  graphqlapi.query(`
    mutation {
      updateEnvironment(input: {
        name: "${name}",
        id: ${environmentId},
        patch: ${patch}
      }) {
        id
        name
      }
    }
  `);

async function deleteEnvironment(
  name: string,
  project: string,
): Promise<Object> {
  const result = await graphqlapi.query(`
    {
      project:projectByName(name: "${project}"){
        id
      }
    }
  `);

  if (!result || !result.project) {
    throw new ProjectNotFound(`Cannot load id for project ${project}`);
  }

  return graphqlapi.query(`
    mutation {
      deleteEnvironment(input: {name: "${name}", project: ${result.project.id}})
    }
  `);
}

const getOpenShiftInfoForProject = (project: string): Promise<Object> =>
  graphqlapi.query(`
    {
      project:projectByName(name: "${project}"){
        id
        openshift  {
          console_url
          token
          project_user
          router_pattern
        }
        customer {
          private_key
        }
        git_url
        subfolder
        openshift_project_pattern
        production_environment
      }
    }
`);

const getProductionEnvironmentForProject = (project: string): Promise<Object> =>
  graphqlapi.query(`
    {
      project:projectByName(name: "${project}"){
        production_environment
      }
    }
`);

module.exports = {
  getProjectsByGitUrl,
  getRocketChatInfoForProject,
  getSlackinfoForProject,
  getActiveSystemForProject,
  getOpenShiftInfoForProject,
  getProductionEnvironmentForProject,
  addOrUpdateEnvironment,
  deleteEnvironment,
};
<|endoftext|>


<commit_before>/*!
 * Copyright 2014 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var OAE = require('oae-util/lib/oae');
var swagger = require('oae-util/lib/swagger');
var swaggerParam = require('oae-util/lib/swaggerParamTypes');
var DocAPI = require('./api');

/**
 * @REST getDocModulesByType
 * Get list of modules depending on the type
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /doc/{type}
 * @PathParam   {string}     type         The type of modules to list        [backend, frontend]
 * @Return      {string[]}                A JSON array of module names
 */
OAE.tenantRouter.on('get', '/api/doc/:type', function(req, res) {
    DocAPI.getModules(req.params.type, function(err, modules) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200, modules);
    });
});

/**
 * @REST getDocModule
 * Get documentation for a module
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /doc/{type}/{module}
 * @PathParam   {string}     type         The type of modules to list        [backend, frontend]
 * @PathParam   {string}     module       The name of the module
 * @Return      {Doc[]}                   The dox documentation for the module
 */
OAE.tenantRouter.on('get', '/api/doc/:type/:module', function(req, res) {
    DocAPI.getModuleDocumentation(req.params.module, req.params.type, function(err, docs) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200, docs);
    });
});

/**
 * Get the swagger resources json
 */
OAE.tenantRouter.on('get', '/api/swagger', function(req, res) {
    return res.send(200, swagger.getResources(req.ctx));
});

/**
 * Get the swagger apis json
 */
OAE.tenantRouter.on('get', '/api/swagger/:id', function(req, res) {
    return res.send(200, swagger.getApi(req.ctx, req.params.id));
});

// Add the REST models for Docs
/**
 * @RESTModel Doc
 *
 * @Required  [tags, description, code, ignore]
 * @Property  {DocTag[]}      tags            A list of jsdoc tags
 * @Property  {DocDesc}       description     A description of what the code does
 * @Property  {string}        code            The source code being documented
 * @Property  {boolean}       ignore          Whether this block should be ignored by the UI
 * @Property  {DocCtx}        ctx             The documentation context
 * @Property  {boolean}       isPrivate       Whether this section is private
 */

/**
 * @RESTModel DocTag
 *
 * @Required  [type, types, name, description]
 * @Property  {string}        type
 * @Property  {string[]}      types
 * @Property  {string}        items
 * @Property  {string}        name
 * @Property  {string}        description
 */

/**
 * @RESTModel DocDesc
 *
 * @Required  [full, summary, body]
 * @Property  {string}        full
 * @Property  {string}        summary
 * @Property  {string}        body
 */

/**
 * @RESTModel DocCtx
 *
 * @Required  [type, name, value, string]
 * @Property  {string}        type
 * @Property  {string}        name
 * @Property  {string}        value
 * @Property  {string}        string
 */
<commit_msg>add descriptions to models and newlines before descriptions<commit_after>/*!
 * Copyright 2014 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var OAE = require('oae-util/lib/oae');
var swagger = require('oae-util/lib/swagger');
var swaggerParam = require('oae-util/lib/swaggerParamTypes');
var DocAPI = require('./api');

/**
 * @REST getDocModulesByType
 *
 * Get list of modules depending on the type
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /doc/{type}
 * @PathParam   {string}     type         The type of modules to list        [backend, frontend]
 * @Return      {string[]}                A JSON array of module names
 */
OAE.tenantRouter.on('get', '/api/doc/:type', function(req, res) {
    DocAPI.getModules(req.params.type, function(err, modules) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200, modules);
    });
});

/**
 * @REST getDocModule
 *
 * Get documentation for a module
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /doc/{type}/{module}
 * @PathParam   {string}     type         The type of modules to list        [backend, frontend]
 * @PathParam   {string}     module       The name of the module
 * @Return      {Doc[]}                   The dox documentation for the module
 */
OAE.tenantRouter.on('get', '/api/doc/:type/:module', function(req, res) {
    DocAPI.getModuleDocumentation(req.params.module, req.params.type, function(err, docs) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200, docs);
    });
});

/**
 * Get the swagger resources json
 */
OAE.tenantRouter.on('get', '/api/swagger', function(req, res) {
    return res.send(200, swagger.getResources(req.ctx));
});

/**
 * Get the swagger apis json
 */
OAE.tenantRouter.on('get', '/api/swagger/:id', function(req, res) {
    return res.send(200, swagger.getApi(req.ctx, req.params.id));
});

// Add the REST models for Docs
/**
 * @RESTModel Doc
 *
 * The container object that holds all the documentation for a library
 *
 * @Required  [tags, description, code, ignore]
 * @Property  {DocTag[]}      tags            A list of jsdoc tags
 * @Property  {DocDesc}       description     A description of what the code does
 * @Property  {string}        code            The source code being documented
 * @Property  {boolean}       ignore          Whether this block should be ignored by the UI
 * @Property  {DocCtx}        ctx             The documentation context
 * @Property  {boolean}       isPrivate       Whether this section is private
 */

/**
 * @RESTModel DocTag
 *
 * A JSDoc tag like `@param` with all of it's relevant info
 *
 * @Required  [type, types, name, description]
 * @Property  {string}        type
 * @Property  {string[]}      types
 * @Property  {string}        items
 * @Property  {string}        name
 * @Property  {string}        description
 */

/**
 * @RESTModel DocDesc
 *
 * The description block from the JSDoc
 *
 * @Required  [full, summary, body]
 * @Property  {string}        full
 * @Property  {string}        summary
 * @Property  {string}        body
 */

/**
 * @RESTModel DocCtx
 *
 * The context the documentation appeared in
 *
 * @Required  [type, name, value, string]
 * @Property  {string}        type
 * @Property  {string}        name
 * @Property  {string}        value
 * @Property  {string}        string
 */
<|endoftext|>


<commit_before>function form_request(form, method, skip_empty) {
    if (typeof skip_empty == 'undefined' || skip_empty == null)
        skip_empty = false;
    var files_to_upload = [];

    var js_form = form2js(form, '.', skip_empty, function(node) {
        /* Find any file input fields and add them to the files array */
        if (!node.nodeName.match(/INPUT/i) || !node.type.match(/file/i))
            return false;
        if (node.files.length > 0)
            files_to_upload.push({name: node.name, files: node.files});
        return false;
    });

    file_handler = new FileHandler(files_to_upload, js_form, function() {
        /* Only submit the form once all files have replaced by file_ids */
        var jsonified_form = JSON.stringify(js_form);
        console.log('About to submit');
        console.log(js_form);
        $.ajax({url: form.action, data: jsonified_form, type: method,
                complete: handle_response});
    });
    return false;  // Ensure the form submission doesn't actually happen
}

function handle_response(xhr) {
    if (xhr.status > 500) {
        console.log('Server error');
        console.log(xhr.responseText);
        return;
    }
    data = JSON.parse(xhr.responseText);
    switch(xhr.status) {
    case 200:  // Ok
        alert(data['message'])
        break;
    case 201:  // Created
        window.location = data['redir_location'];
        break;
    case 400:  // BadRequest
        msg = data['error']
        if (typeof data['messages'] === 'string')
            msg += '\n' + data['messages']
        else
            for (i in data['messages'])
                msg += '\n' + data['messages'][i]
        alert(msg);
        break;
    case 409:  // Conflict
        alert(data['message']);
        break;
        case 410:  // Gone
        window.location = data['redir_location'];
        break;
    default:
        alert("Unhandled status code: " + xhr.status);
    }
}

function FileHandler(to_replace, js_form, completed_callback) {
    this.to_replace = to_replace;
    this.js_form = js_form;
    this.completed_callback = completed_callback;
    this.current = null;
    this.upload_or_submit();
}

FileHandler.prototype.upload_or_submit = function() {
    this.current = this.to_replace.pop();
    if (this.current) {
        console.log('Attempting to replace ' + this.current.name);
        process_file(this);
    }
    else {
        this.completed_callback();
    }
}

FileHandler.prototype.replace_file = function(xhr_response) {
    var file_id = $.parseJSON(xhr_response)['file_id'];
    console.log(file_id);
    this.js_form[this.current.name] = String(file_id);
    this.upload_or_submit();
}

function process_file(handler) {
    var file = handler.current.files[0];
    var reader = new FileReader();
    reader.onload = function(event){  // When the file is loaded
        var data = event.target.result;
        setTimeout(function() {  // Perform asynchronously
            var base64 = window.btoa(data);
            var sha1 = hex_sha1(data);
            var url = '/file/' + sha1;
            console.log('Checking if ' + sha1 + ' exists');
            $.ajax({url: url, complete: function(xhr) {  // Test if file exists
                if (xhr.status == 404) {
                    console.log('Uploading file for ' + sha1);
                    var form_json = JSON.stringify({b64data: base64});
                    $.ajax({url: url, type: 'PUT', complete: function(xhr) {
                        if (xhr.status == 200)
                            handler.replace_file(xhr.responseText);
                        else {
                            console.log('Error uploading file: ' + xhr.status);
                        }}, data: form_json});
                }
                else
                    handler.replace_file(xhr.responseText);
            }});
        }, 0);
    };
    reader.readAsBinaryString(file);
}
<commit_msg>Fix javascript uploader URLs.<commit_after>function form_request(form, method, skip_empty) {
    if (typeof skip_empty == 'undefined' || skip_empty == null)
        skip_empty = false;
    var files_to_upload = [];

    var js_form = form2js(form, '.', skip_empty, function(node) {
        /* Find any file input fields and add them to the files array */
        if (!node.nodeName.match(/INPUT/i) || !node.type.match(/file/i))
            return false;
        if (node.files.length > 0)
            files_to_upload.push({name: node.name, files: node.files});
        return false;
    });

    file_handler = new FileHandler(files_to_upload, js_form, function() {
        /* Only submit the form once all files have replaced by file_ids */
        var jsonified_form = JSON.stringify(js_form);
        console.log('About to submit');
        console.log(js_form);
        $.ajax({url: form.action, data: jsonified_form, type: method,
                complete: handle_response});
    });
    return false;  // Ensure the form submission doesn't actually happen
}

function handle_response(xhr) {
    if (xhr.status > 500) {
        console.log('Server error');
        console.log(xhr.responseText);
        return;
    }
    data = JSON.parse(xhr.responseText);
    switch(xhr.status) {
    case 200:  // Ok
        alert(data['message'])
        break;
    case 201:  // Created
        window.location = data['redir_location'];
        break;
    case 400:  // BadRequest
        msg = data['error']
        if (typeof data['messages'] === 'string')
            msg += '\n' + data['messages']
        else
            for (i in data['messages'])
                msg += '\n' + data['messages'][i]
        alert(msg);
        break;
    case 409:  // Conflict
        alert(data['message']);
        break;
        case 410:  // Gone
        window.location = data['redir_location'];
        break;
    default:
        alert("Unhandled status code: " + xhr.status);
    }
}

function FileHandler(to_replace, js_form, completed_callback) {
    this.to_replace = to_replace;
    this.js_form = js_form;
    this.completed_callback = completed_callback;
    this.current = null;
    this.upload_or_submit();
}

FileHandler.prototype.upload_or_submit = function() {
    this.current = this.to_replace.pop();
    if (this.current) {
        console.log('Attempting to replace ' + this.current.name);
        process_file(this);
    }
    else {
        this.completed_callback();
    }
}

FileHandler.prototype.replace_file = function(xhr_response) {
    var file_id = $.parseJSON(xhr_response)['file_id'];
    console.log(file_id);
    this.js_form[this.current.name] = String(file_id);
    this.upload_or_submit();
}

function process_file(handler) {
    var file = handler.current.files[0];
    var reader = new FileReader();
    reader.onload = function(event){  // When the file is loaded
        var data = event.target.result;
        setTimeout(function() {  // Perform asynchronously
            var base64 = window.btoa(data);
            var sha1 = hex_sha1(data);
            var url = '/file/' + sha1 + '/info';
            console.log('Checking if ' + sha1 + ' exists');
            $.ajax({url: url, complete: function(xhr) {  // Test if file exists
                if (xhr.status == 404) {
                    console.log('Uploading file for ' + sha1);
                    var form_json = JSON.stringify({b64data: base64});
                    var url = '/file/' + sha1 + '/info';
                    $.ajax({url: url, type: 'PUT', complete: function(xhr) {
                        if (xhr.status == 200)
                            handler.replace_file(xhr.responseText);
                        else {
                            console.log('Error uploading file: ' + xhr.status);
                        }}, data: form_json});
                }
                else
                    handler.replace_file(xhr.responseText);
            }});
        }, 0);
    };
    reader.readAsBinaryString(file);
}
<|endoftext|>


<commit_before>import {getScriptElements} from "../src/getJSScriptTags"
import _ from "underscore"
import getHeadAndBodyContent from "./getHeadAndBodyContent"

function measureTodoMVCRenderingTime(){
    // see perf.txt for more info
    console.time("TodoMVC Rendering")
    var start = new Date();

    checkIfDone();
    function checkIfDone(){
        if (document.querySelectorAll("ul.todo-list li").length > 0){
            console.timeEnd("TodoMVC Rendering")
            var time = new Date().valueOf() - start.valueOf();
            alert("TodoMVC took " + time + "s to render")
        } else {
            setTimeout(checkIfDone, 10)
        }
    }
}

window.onFromJSReady = function(){
    console.log("Loading page from FromJS")

    // measureTodoMVCRenderingTime()

    window.fromJSInitialPageHtml = pageHtml;
    var bodyContent, headContent;

    var headAndBody = getHeadAndBodyContent(pageHtml)
    var bodyScripts = getScriptElements(headAndBody.bodyContent);

    if (headAndBody.headContent) {
        document.head.innerHTML = headAndBody.headContent
        var headScripts = getScriptElements(headAndBody.headContent);
        window.fromJSEnableTracing() // be careful calling global functions like regexp.exec, array.join etc after this
        appendScriptsOneAfterAnother(headScripts, document.head, function(){
            loadBody()
        })
    } else {
        window.fromJSEnableTracing()
        loadBody()
    }

    function loadBody(){
        document.body.innerHTML = headAndBody.bodyContent
        makeSureInitialHTMLHasBeenProcessed()
        appendScriptsOneAfterAnother(bodyScripts, document.body, function(){
            simulateOnLoad()
        })
    }
}

// Normally this file is loaded before fromJS is ready, but sometimes not
if (window.fromJSIsReady) {
    window.onFromJSReady()
}

function simulateOnLoad(){
    if (document.body.onload) {
        document.body.onload({});
    }

    window.dispatchEvent(new Event("DOMContentLoaded"))
    document.dispatchEvent(new Event("DOMContentLoaded"))

    // I can't override document.readyState, so it will always be "complete" and never "loading"
    document.dispatchEvent(new Event("readystatechange"))

    window.dispatchEvent(new Event("load"))
    document.dispatchEvent(new Event("load"))
}

function sendMessageToBackgroundPage(data, callback){
    var callbackName = "fromJSBackgroundMessageCallback" + _.uniqueId()
    window[callbackName] = function(){
        delete window[callbackName];
        callback.apply(this, arguments);
    }
    data.callbackName = callbackName;

    data.isFromJSExtensionMessage = true
    var event = new CustomEvent("RebroadcastExtensionMessage", {detail: data});
    window.dispatchEvent(event);
}

function appendScriptsOneAfterAnother(scripts, container, done){
    next()
    function next(){
        if (scripts.length === 0) {
            done();
            return
        }
        var script = scripts.shift()
        if (nativeInnerHTMLDescriptor.get.call(script) === ""){
            // Do this rather than appending script element, because
            // requests on https may be cross origin
            sendMessageToBackgroundPage({
                type: "loadScript",
                url: script.src
            }, function(){
                next();
            })

            // script.onload = function(){
            //     next();
            // }
            // script.onerror = function(err){
            //     console.warn("Error loading script", script, err)
            //     next();
            // }
            // container.appendChild(script)
        } else {
            container.appendChild(script)
            next();
        }
    }
}
<commit_msg>Tidy up injected.js a bit.<commit_after>import {getScriptElements} from "../src/getJSScriptTags"
import _ from "underscore"
import getHeadAndBodyContent from "./getHeadAndBodyContent"

function measureTodoMVCRenderingTime(){
    // see perf.txt for more info
    console.time("TodoMVC Rendering")
    var start = new Date();

    checkIfDone();
    function checkIfDone(){
        if (document.querySelectorAll("ul.todo-list li").length > 0){
            console.timeEnd("TodoMVC Rendering")
            var time = new Date().valueOf() - start.valueOf();
            alert("TodoMVC took " + time + "s to render")
        } else {
            setTimeout(checkIfDone, 10)
        }
    }
}

window.onFromJSReady = function(){
    console.log("Loading page from FromJS")

    // measureTodoMVCRenderingTime()

    window.fromJSInitialPageHtml = pageHtml;
    var bodyContent, headContent;

    var headAndBody = getHeadAndBodyContent(pageHtml)
    var bodyScripts = getScriptElements(headAndBody.bodyContent);

    if (headAndBody.headContent) {
        var headScripts = getScriptElements(headAndBody.headContent);
    }

    window.fromJSEnableTracing() // be careful calling global functions like regexp.exec, array.join etc after this
    if (headAndBody.headContent) {
        document.head.innerHTML = headAndBody.headContent
        appendScriptsOneAfterAnother(headScripts, document.head, function(){
            loadBody()
        })
    } else {
        loadBody()
    }

    function loadBody(){
        document.body.innerHTML = headAndBody.bodyContent
        makeSureInitialHTMLHasBeenProcessed()
        appendScriptsOneAfterAnother(bodyScripts, document.body, function(){
            simulateOnLoad()
        })
    }
}

// Normally this file is loaded before fromJS is ready, but sometimes not
if (window.fromJSIsReady) {
    window.onFromJSReady()
}

function simulateOnLoad(){
    if (document.body.onload) {
        document.body.onload({});
    }

    window.dispatchEvent(new Event("DOMContentLoaded"))
    document.dispatchEvent(new Event("DOMContentLoaded"))

    // I can't override document.readyState, so it will always be "complete" and never "loading"
    document.dispatchEvent(new Event("readystatechange"))

    window.dispatchEvent(new Event("load"))
    document.dispatchEvent(new Event("load"))
}

function sendMessageToBackgroundPage(data, callback){
    var callbackName = "fromJSBackgroundMessageCallback" + _.uniqueId()
    window[callbackName] = function(){
        delete window[callbackName];
        callback.apply(this, arguments);
    }
    data.callbackName = callbackName;

    data.isFromJSExtensionMessage = true
    var event = new CustomEvent("RebroadcastExtensionMessage", {detail: data});
    window.dispatchEvent(event);
}

function appendScriptsOneAfterAnother(scripts, container, done){
    next()
    function next(){
        if (scripts.length === 0) {
            done();
            return
        }
        var script = scripts.shift()
        console.log("loading script", script)
        if (script.src.indexOf("platform") !== -1) {
            debugger
        }
        if (nativeInnerHTMLDescriptor.get.call(script) === ""){
            // Do this rather than appending script element, because
            // requests on https may be cross origin
            sendMessageToBackgroundPage({
                type: "loadScript",
                url: script.src
            }, function(){
                next();
            })

            // script.onload = function(){
            //     next();
            // }
            // script.onerror = function(err){
            //     console.warn("Error loading script", script, err)
            //     next();
            // }
            // container.appendChild(script)
        } else {
            container.appendChild(script)
            next();
        }
    }
}
<|endoftext|>


<commit_before>'use strict';

var DEFAULT_SETTINGS = {
        length: 20,
        repeat: 0,
        iteration: 8,
        lower: null,
        upper: null,
        number: null,
        dash: null,
        space: null,
        symbol: null,
        isVaultCompatible: true,

        autosend: false,
        servicename: 'prefix',
        defServicename: '',

        pwFieldList: [
            'pass', 'pass1', 'pass2', 'Pass', 'passwd', 'Passwd', 'password', 'Password', 'PASSWORD',
            'pw', 'PW', 'passwort', 'Passwort', 'ap_password', 'login_password', 'user_password',
            'user_pass', 'pwd', 'rpass', 'mypassword', 'myPassword', 'myregpassword'
        ],
        userFieldList: [
            'mail', 'Mail', 'email', 'Email', 'EMail', 'e-mail', 'E-Mail', 'eMail', 'login', 'Login',
            'user', 'User', 'username', 'Username', 'ap_email', 'userid', 'Userid', 'userId', 'UserId',
            'login_email', 'user_login', 'signin-email', 'j_username', 'session[username_or_email]'
        ],
        ccTldList: [
            'com', 'co', 'ar', 'net', 'org', 'jp', 'se', 'ae', 'me', 'plc', 'ac', 'ltd', 'gov', 'kids', 'us'
        ],

        serviceExceptions: {
            'alternate.de': {
                length: 15
            },
            'o2online.de': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'o2.co.uk': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'o2online.ie': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'o2.cz': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'o2.sk': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'npmjs.org': {
                symbol: 0
            },
            'hosteurope.de': {
                length: 16,
                symbols: '!%&/()=*+#.,:;'
            },
            'wordpress.com': {
                symbols: '!%&()=*+#.,:;'
            },
            'zooplus.de': {
                length: 20,
                symbols: '!#$%&\'()*+,./=?[\\]^{}~'
            },
            'nodejitsu.com': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'check24.de': {
                length: 15
            },
            'kabeldeutschland.de': {
                space: 0
            },
            'unitymedia.de': {
                space: 0,
                symbols: '/+=]',
                dash: 0
            },
            'paket.de': {
                length: 13,
                space: 0,
                symbols: '!&/()=?*+'
            }
        },

        imgUrl: 'images/close.png'
    },
    TYPES = 'lower upper number dash space symbol'.split(' '),
    UUID = '1e9632fa-e9b3-4a49-ab3b-e17256b83ff9';

var $ = function (selector) {
    var element = document.getElementById(selector);

    if (!element) {
        element = document.getElementsByName(selector)[0];
    }

    return element;
};

var on = function (element, event, listener) {
    if (!element) {
        return;
    }

    if ('string' === typeof event) {
        event = [event];
    }

    for (var i = 0, n = event.length; i < n; i++) {
        if (element.addEventListener) {
            element.addEventListener(event[i], listener, true);
        } else if (element.attachEvent) {
            element.attachEvent('on' + event[i], listener);
        } else {
            throw new Error('element not type of EventTarget');
        }
    }
};

/**
 * handles specific domain extensions
 */
var DomainService = {
    _domainName: '',
    _rules: null,
    _setPasswordRules: null,
    _setDomainname: null,
    getPasswordRules: null,
    getDomainname: null

};

DomainService._setDomainname = function (domain) {
    var domainname = domain || document.domain,
        domainparts = domainname.split('.');

    if (2 < domainparts.length) {
        domainname = domainparts[domainparts.length - 2] + '.' + domainparts[domainparts.length - 1];

        if (Helper.isCcTld(domainparts[domainparts.length - 2])) {
            domainname = domainparts[domainparts.length - 3] + '.' + domainname;
        }
    }

    this._domainName = domainname;
};

DomainService._setPasswordRules = function (settings) {
    if (settings && settings[this._domainName]) {
        this._rules = settings[this._domainName];
    }
};

DomainService.getDomainname = function () {
    return this._domainName;
};

DomainService.getPasswordRules = function () {
    return this._rules;
};

DomainService.init = function (ruleSettings, domain) {
    this._setDomainname(domain);
    this._setPasswordRules(ruleSettings);

    return this;
};

/**
 * commonly used logic
 */
var Helper = {};

/**
 *
 * @param {Array} list
 *
 * @returns {*}
 */
Helper.getElementFromList = function (list) {
    var i, n, element;

    for (i = 0, n = list.length; i < n; i++) {
        element = $(list[i]);

        if (element) {
            return element;
        }
    }

    return null;
};

/**
 * checks if the given name is in the cctld list
 *
 * @param {String} name
 *
 * @returns {boolean}
 */
Helper.isCcTld = function (name) {
    var i, n;

    for (i = 0, n = DEFAULT_SETTINGS.ccTldList.length; i < n; i++) {
        if (name === DEFAULT_SETTINGS.ccTldList[i]) {
            return true;
        }
    }

    return false;
};

/**
 * fix problem if a password field id does exist more than once on a page
 *
 * @param {NodeList} nodeList
 */
Helper.fixDuplicateIds = function (nodeList) {
    var i, j, n = nodeList.length;

    for (i = 0; i < n; i++) {
        for (j = i + 1; j < n; j++) {
            if (nodeList[i].id === nodeList[j].id) {
                nodeList[j].id += '-' + Math.random().toString(16).substring(7);
            }
        }
    }
};

/**
 * check if given pwField is part of an overlay
 *
 * @param {Object} pwField
 *
 * @returns {Boolean}
 */
Helper.isOverlay = function (pwField) {
    // @todo this is easy password handler (overlay) only
    return pwField && pwField.id && pwField.id.match(/^easy-password-passphrase/);
};

/**
 * check if given pwField already has an overlay
 *
 * @param {Object} pwField
 *
 * @returns {Boolean}
 */
Helper.hasOverlay = function (pwField) {
    // @todo this is easy password handler (overlay) only
    return pwField && pwField.id && $(BASE_NAME + 'generator-overlay-' + pwField.id);
};

/**
 * cancel event bubbling and capturing
 *
 * @param {Object} event
 */
Helper.cancelEventPropagation = function (event) {
    if (event.stopImmediatePropagation) {
        // as long it is the first registered event: even captured events are stopped
        event.stopImmediatePropagation();
    }

    if (event.cancelBubble != null) {
        event.cancelBubble = true;
    }
};

/**
 * merges second object into first
 *
 * @param {Object} first
 * @param {Object} second
 *
 * @returns {Object}
 */
Helper.mergeObject = function (first, second) {
    var attrName;

    if (first && second) {
        for (attrName in second) {
            if (second.hasOwnProperty(attrName)) {
                first[attrName] = second[attrName];
            }
        }
    }

    return first;
};

/**
 * gets the current password field's login form
 *
 * @param {Object} pwField
 *
 * @returns {Number|Boolean}
 */
Helper.getLoginForm = function (pwField) {
    for (var i = 0, n = document.forms.length; i < n; i++) {
        for (var o = 0, m = document.forms[i].length; o < m; o++) {
            if (pwField.id === document.forms[i][o].id) {
                return i;
            }
            if (pwField.name === document.forms[i][o].name) {
                return i;
            }
        }
    }

    return false;
};

/**
 * generates a random servicename
 *
 * @returns {string}
 */
Helper.getRandomServicename = function () {
    return Math.random().toString(36).substring(7) + '@';
};

/**
 * get input type radio values
 *
 * @param {string} name
 * @returns {*}
 */
Helper.getRadio = function (name) {
    var inputs = document.getElementsByTagName('input'), input, i, n;

    for (i = 0, n = inputs.length; i < n; i++) {
        input = inputs[i];
        if (input.type === 'radio' && input.name === name && input.checked) {
            return input.value;
        }
    }

    return null;
};

/**
 * Set radio by name
 *
 * @param {String} name
 * @param {int} value
 */
Helper.setRadio = function (name, value) {
    var inputs = document.getElementsByTagName('input'), input, i, n;

    for (i = 0, n = inputs.length; i < n; i++) {
        input = inputs[i];
        if (input.type === 'radio' && input.name === name) {
            switch (input.value) {
                case 'required':
                    input.checked = (value && value > 0);
                    break;
                case 'allowed':
                    input.checked = (value === null);
                    break;
                case 'forbidden':
                    input.checked = (value === 0);
                    break;
            }
        }
    }
};

/**
 * Get current vault type settings
 *
 * @param {Object} settings
 * @param {int} requiredLength
 * @returns {Object}
 */
Helper.getTypeSettings = function (settings, requiredLength) {
    var i, n, value;

    for (i = 0, n = TYPES.length; i < n; i++) {
        value = this.getRadio(TYPES[i]);

        if (value === 'forbidden') {
            settings[TYPES[i]] = 0;
        } else if (value === 'required') {
            settings[TYPES[i]] = requiredLength;
        } else {
            settings[TYPES[i]] = null;
        }
    }

    return settings;
};

/**
 * set all vault radio types
 *
 * @param {Object} settings
 */
Helper.setTypeSettings = function (settings) {
    var i, n;

    for (i = 0, n = TYPES.length; i < n; i++) {
        Helper.setRadio(TYPES[i], settings[TYPES[i]]);
    }
};<commit_msg>fixed typo<commit_after>'use strict';

var DEFAULT_SETTINGS = {
        length: 20,
        repeat: 0,
        iteration: 8,
        lower: null,
        upper: null,
        number: null,
        dash: null,
        space: null,
        symbol: null,
        isVaultCompatible: true,

        autosend: false,
        servicename: 'prefix',
        defServicename: '',

        pwFieldList: [
            'pass', 'pass1', 'pass2', 'Pass', 'passwd', 'Passwd', 'password', 'Password', 'PASSWORD',
            'pw', 'PW', 'passwort', 'Passwort', 'ap_password', 'login_password', 'user_password',
            'user_pass', 'pwd', 'rpass', 'mypassword', 'myPassword', 'myregpassword'
        ],
        userFieldList: [
            'mail', 'Mail', 'email', 'Email', 'EMail', 'e-mail', 'E-Mail', 'eMail', 'login', 'Login',
            'user', 'User', 'username', 'Username', 'ap_email', 'userid', 'Userid', 'userId', 'UserId',
            'login_email', 'user_login', 'signin-email', 'j_username', 'session[username_or_email]'
        ],
        ccTldList: [
            'com', 'co', 'ar', 'net', 'org', 'jp', 'se', 'ae', 'me', 'plc', 'ac', 'ltd', 'gov', 'kids', 'us'
        ],

        serviceExceptions: {
            'alternate.de': {
                length: 15
            },
            'o2online.de': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'o2.co.uk': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'o2online.ie': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'o2.cz': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'o2.sk': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'npmjs.org': {
                symbol: 0
            },
            'hosteurope.de': {
                length: 16,
                symbols: '!%&/()=*+#.,:;'
            },
            'wordpress.com': {
                symbols: '!%&()=*+#.,:;'
            },
            'zooplus.de': {
                length: 20,
                symbols: '!#$%&\'()*+,./=?[\\]^{}~'
            },
            'nodejitsu.com': {
                space: 0,
                dash: 0,
                symbol: 0
            },
            'check24.de': {
                length: 15
            },
            'kabeldeutschland.de': {
                space: 0
            },
            'unitymedia.de': {
                space: 0,
                symbols: '/+=]',
                dash: 0
            },
            'paket.de': {
                length: 13,
                space: 0,
                symbols: '!&/()=?*+'
            }
        },

        imgUrl: 'images/close.png'
    },
    TYPES = 'lower upper number dash space symbol'.split(' '),
    UUID = '1e9632fa-e9b3-4a49-ab3b-e17256b83ff9';

var $ = function (selector) {
    var element = document.getElementById(selector);

    if (!element) {
        element = document.getElementsByName(selector)[0];
    }

    return element;
};

var on = function (element, event, listener) {
    if (!element) {
        return;
    }

    if ('string' === typeof event) {
        event = [event];
    }

    for (var i = 0, n = event.length; i < n; i++) {
        if (element.addEventListener) {
            element.addEventListener(event[i], listener, true);
        } else if (element.attachEvent) {
            element.attachEvent('on' + event[i], listener);
        } else {
            throw new Error('element not of type EventTarget');
        }
    }
};

/**
 * handles specific domain extensions
 */
var DomainService = {
    _domainName: '',
    _rules: null,
    _setPasswordRules: null,
    _setDomainname: null,
    getPasswordRules: null,
    getDomainname: null

};

DomainService._setDomainname = function (domain) {
    var domainname = domain || document.domain,
        domainparts = domainname.split('.');

    if (2 < domainparts.length) {
        domainname = domainparts[domainparts.length - 2] + '.' + domainparts[domainparts.length - 1];

        if (Helper.isCcTld(domainparts[domainparts.length - 2])) {
            domainname = domainparts[domainparts.length - 3] + '.' + domainname;
        }
    }

    this._domainName = domainname;
};

DomainService._setPasswordRules = function (settings) {
    if (settings && settings[this._domainName]) {
        this._rules = settings[this._domainName];
    }
};

DomainService.getDomainname = function () {
    return this._domainName;
};

DomainService.getPasswordRules = function () {
    return this._rules;
};

DomainService.init = function (ruleSettings, domain) {
    this._setDomainname(domain);
    this._setPasswordRules(ruleSettings);

    return this;
};

/**
 * commonly used logic
 */
var Helper = {};

/**
 *
 * @param {Array} list
 *
 * @returns {*}
 */
Helper.getElementFromList = function (list) {
    var i, n, element;

    for (i = 0, n = list.length; i < n; i++) {
        element = $(list[i]);

        if (element) {
            return element;
        }
    }

    return null;
};

/**
 * checks if the given name is in the cctld list
 *
 * @param {String} name
 *
 * @returns {boolean}
 */
Helper.isCcTld = function (name) {
    var i, n;

    for (i = 0, n = DEFAULT_SETTINGS.ccTldList.length; i < n; i++) {
        if (name === DEFAULT_SETTINGS.ccTldList[i]) {
            return true;
        }
    }

    return false;
};

/**
 * fix problem if a password field id does exist more than once on a page
 *
 * @param {NodeList} nodeList
 */
Helper.fixDuplicateIds = function (nodeList) {
    var i, j, n = nodeList.length;

    for (i = 0; i < n; i++) {
        for (j = i + 1; j < n; j++) {
            if (nodeList[i].id === nodeList[j].id) {
                nodeList[j].id += '-' + Math.random().toString(16).substring(7);
            }
        }
    }
};

/**
 * check if given pwField is part of an overlay
 *
 * @param {Object} pwField
 *
 * @returns {Boolean}
 */
Helper.isOverlay = function (pwField) {
    // @todo this is easy password handler (overlay) only
    return pwField && pwField.id && pwField.id.match(/^easy-password-passphrase/);
};

/**
 * check if given pwField already has an overlay
 *
 * @param {Object} pwField
 *
 * @returns {Boolean}
 */
Helper.hasOverlay = function (pwField) {
    // @todo this is easy password handler (overlay) only
    return pwField && pwField.id && $(BASE_NAME + 'generator-overlay-' + pwField.id);
};

/**
 * cancel event bubbling and capturing
 *
 * @param {Object} event
 */
Helper.cancelEventPropagation = function (event) {
    if (event.stopImmediatePropagation) {
        // as long it is the first registered event: even captured events are stopped
        event.stopImmediatePropagation();
    }

    if (event.cancelBubble != null) {
        event.cancelBubble = true;
    }
};

/**
 * merges second object into first
 *
 * @param {Object} first
 * @param {Object} second
 *
 * @returns {Object}
 */
Helper.mergeObject = function (first, second) {
    var attrName;

    if (first && second) {
        for (attrName in second) {
            if (second.hasOwnProperty(attrName)) {
                first[attrName] = second[attrName];
            }
        }
    }

    return first;
};

/**
 * gets the current password field's login form
 *
 * @param {Object} pwField
 *
 * @returns {Number|Boolean}
 */
Helper.getLoginForm = function (pwField) {
    for (var i = 0, n = document.forms.length; i < n; i++) {
        for (var o = 0, m = document.forms[i].length; o < m; o++) {
            if (pwField.id === document.forms[i][o].id) {
                return i;
            }
            if (pwField.name === document.forms[i][o].name) {
                return i;
            }
        }
    }

    return false;
};

/**
 * generates a random servicename
 *
 * @returns {string}
 */
Helper.getRandomServicename = function () {
    return Math.random().toString(36).substring(7) + '@';
};

/**
 * get input type radio values
 *
 * @param {string} name
 * @returns {*}
 */
Helper.getRadio = function (name) {
    var inputs = document.getElementsByTagName('input'), input, i, n;

    for (i = 0, n = inputs.length; i < n; i++) {
        input = inputs[i];
        if (input.type === 'radio' && input.name === name && input.checked) {
            return input.value;
        }
    }

    return null;
};

/**
 * Set radio by name
 *
 * @param {String} name
 * @param {int} value
 */
Helper.setRadio = function (name, value) {
    var inputs = document.getElementsByTagName('input'), input, i, n;

    for (i = 0, n = inputs.length; i < n; i++) {
        input = inputs[i];
        if (input.type === 'radio' && input.name === name) {
            switch (input.value) {
                case 'required':
                    input.checked = (value && value > 0);
                    break;
                case 'allowed':
                    input.checked = (value === null);
                    break;
                case 'forbidden':
                    input.checked = (value === 0);
                    break;
            }
        }
    }
};

/**
 * Get current vault type settings
 *
 * @param {Object} settings
 * @param {int} requiredLength
 * @returns {Object}
 */
Helper.getTypeSettings = function (settings, requiredLength) {
    var i, n, value;

    for (i = 0, n = TYPES.length; i < n; i++) {
        value = this.getRadio(TYPES[i]);

        if (value === 'forbidden') {
            settings[TYPES[i]] = 0;
        } else if (value === 'required') {
            settings[TYPES[i]] = requiredLength;
        } else {
            settings[TYPES[i]] = null;
        }
    }

    return settings;
};

/**
 * set all vault radio types
 *
 * @param {Object} settings
 */
Helper.setTypeSettings = function (settings) {
    var i, n;

    for (i = 0, n = TYPES.length; i < n; i++) {
        Helper.setRadio(TYPES[i], settings[TYPES[i]]);
    }
};<|endoftext|>