Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
No results found
Select Git revision
  • master
1 result
Show changes
531 files
+ 94911
0
Compare changes
  • Side-by-side
  • Inline

Files

+4 −0
Original line number Diff line number Diff line
##

projet/node_modules*

############### MacOS
# General
.DS_Store
+268 −0
Original line number Diff line number Diff line
# Hyperdrive

## Une introduction

Dans le cadre du cours de Développement Web Avancé, nous avons du réaliser un projet web. Durant ce projet, nous avons du créer une API REST afin d'offrir un accès aux données. Ce projet a été réalisé en Javascript en utilisant Node JS.

## L'application

Le projet que nous avons choisi de réaliser est un drive. Pour des besoins personnels, nous avons jugé ce projet pertinent et l'avons donc réalisé. Le but est donc de permettre à un utilisateur de s'enregistrer et de stocker des fichiers sur la plateforme. Il a aussi la possibilité de les organiser en créant des dossiers. Il a aussi la possibilité de les partager avec d'autre utilisateurs du service. Nous avons créer une interface simple découpée en quatre partie :

- Une zone de menu pour se connecter, se déconnecter et créer des dossiers / importer des fichiers.
- La zone de contenu du drive ou sont affichés tous les dossiers et fichiers de l'utilisateur.
- Une zone d'information sur le fichier (nom, son propriétaire, la date d'upload, l'adresse d'upload)
- Une zone de contenu affichants tous les fichiers que les autres utilisateurs partagent avec lui.

L'utilisateur a la possibilité de s'inscrire ainsi que de se connecter au service. Lors de sa connexion, il reçoit un token lui permettant d'accéder à l'API. Lors de sa déconnexion, le token est détruit. Pour créer un dossier, il lui suffit de se mettre à un endroit spécifique et de cliquer sur le bouton "New File" après avoir renseigné le nom du dossier à créer.

Pour permettre la géolocalisation des fichiers, nous avons utilisé 2 API publiques qui sont :

- https://ip-api.com/ Cette API nous permet de récupérer les informations de localisation d'une adresse IP. Nous pouvons grâce à celle-ci, récupérer les latitude et longitude que nous stockons dans la base de données.
- http://bot.whatismyipaddress.com Cette API permet de récupérer l'adresse ip de l'ordinateur courant. Nous l'utilisons exclusivement pour la raisons suivantes. Nous travaillons en local, et n'avons pas déployé de serveur public. Nous ne pouvons donc pas récupérer l'adresse du client qui fait une requête sur l'API car il s'agit d'une adresse privée. Il est cependant facile de modifier cette partie du code pour utiliser l'adresse du client au cas ou nous voudrions rendre notre API public.

## Installation

Avant de faire fonctionner le site, assurez vous d'avoir la plateforme Node JS d'installée. Installer ensuite les packages nécessaire au fonctionnement du site en vous rendant à la racine du projet et en executant la commande suivante : *npm install*

Pour démarrer le site il faut réaliser ces 2 étapes :

- Se rendre dans le dossier *db* se trouvant dans la hiérarchie du projet et taper la commande *docker-compose up -d*. Assurez-vous que le port 3306 est libre pour permettre au service MySQL de démarrer correctement.
- Se rendre dans le projet ou se trouve le fichier *hyperdrive-rest*.js et taper la commande *node hyperdrive-rest.js*. après vous être assurer que le port 8080 n'est pas utilisé par un autre service. Le site est accessible à l'adress de votre ordinateur sur le port 8080.

## Répartition

Fleury Noé :

- Upload / Download des fichiers
  - Localisation de ceux-ci à l'upload
- JWT
- Partage des fichiers

Paschoud Nicolas :

- Base de donnée
  - Requêtes SQL (sql-request.js)
- Affichage de l'arborescence dans le drive
- Affichage des informations du fichier
- Création d'un dossier

## Architecture

L'interraction entre les API se présente sous cette forme.

![hyperdrive](/Users/klaus/Documents/Web/Back/2019_tp2/documentation/hyperdrive.png)

- Le bloc Client fais des appels à l'API hyperdrive qui lui réponds avec les données que le client souhaite. Le client les traites et les affiches à sa guise.
- L'API Hyperdrive réponds à des requêtes des clients. Il ne fait appel qu'en cas de besoin aux API *whatismyipaddress* et *ip-api*.
- L'API *ip-api* est appelée par hyperdrive seulement lorsque le client upload un fichier. Cet appel permet de retourner l'addresse de la personne en fonction de son IP. Les latitudes et longitudes sont stockée par l'hyperdrive dans le bloc SQL
- Le bloc whatismyipaddress n'est util que dans le cadre du développement. Cette API nous sert à récupérer notre IP pour ensuite faire un appel à *ip-api*.

Voici comment se présente notre architecture

<img src="./architecture.png" height="1000px">

Nous avons plusieurs dossier principaux :

- /

  A la racine se trouve les fichiers principaux de l'API :

  - hyperdrive-rest.js

    Il s'agit du fichier contenant le traitement pour chacune des routes.

  - sql-request.js

    Ce fichier permet de faire des requêtes SQL vers la base de données.

- front/

  Ce dossier contient tout le frontend de l'application.

  - images

    Ce dossier contient 2 petites images faites main pour l'affichage des dossiers et des fichiers.

  - styles

    Il s'agit du dossier contenant tous le style du site.

  - show-content.js

    Ce fichier est le plus important du frontend. C'est lui qui s'occupe de faire des requêtes vers notre API et de faire l'affichage de nos données correctement

  - 

## Technologies

Pour la réalisation de ce projet, nous avons utilisé la plateform Node JS pour la réalisation de notre API REST. Nous avons aussi réaliser une base de données relationnelle MySQL qui se trouve dans un container. Tout notre projet a été réaliser en Javascript en utilisant les modules Node JS suivant : 

- Express nous a permis de créer nos routes.
- MySQL nous a permis de faire des requêtes SQL vers la base de donnée
- Crypto-js nous a permis de faire la partie JWT
- http nous a permis de faire des appels vers les API public

Pour le frontend, nous avons 2 technologies principalement:

- jQuery nous a permis de faire des requêtes vers l'API REST
- JavaScript nous a permis de gérer l'affichage à la réception des données

## Routes

### /

La route principale retourne la page principale du site (index.html).

### /login

Cette route permet de créer un token pour l'utilisateur si il est inscrit au site.

Paramètre : 

- pseudo : Pseudo de l'utilisateur.
- password : Mot de passe de l'utilisateur.

Retour : 

Le retour de cette route est un objet JSON formé de cette manière : 

```json
{
	"route": "/login",
	"resCode": 0,
	"signedToken": jwt.signedToken,
	"comment": `Password for user '${ user }' true.`
}
```



### /logout

Logout permet de supprimer un token lorsqu'un utilisateur se deconnecte.

Param : 

- Token : Token de l'utilisateur a déconnecter.

### /register

Cette route permet d'inscrire un utilisateur au service de l'hyperdrive.

Paramètres : 

- pseudo : Pseudo du nouvel utilisateur.
- password : Mot de passe du nouvel utilisateur.

### /share/:file_id/:to_user

Cette route permet de partager un fichier avec un utilisateur.

Paramètres :

- token : Il s'agit du token de l'utilisateur qui souhaite partage un fichier.
- file_id : Il s'agit de l'id du fichier à partager.
- to_user : Il s'agit de la personne à qui on souhaite partager le fichier.

### /upload

Cette fonction permet d'uploader un fichier dans un path.

Paramètre :

- token : Token d'authentification de l'utilisateur.
- file_name : Il s'agit du nom du fichier.

### /download/:file_id

Cette fonction permet de télécharger un fichier.

Paramètre : 

- file_id : Id du fichier que l'on souhaite télécharger.
- token : Token d'authentification de l'utilisateur.

### /change-path*

Cette fonction permet d'afficher le contenu d'un dossier.

Paramètres : 

- token : Token d'authentification de l'utilisateur.
- path : Il s'agit du dossier dont le contenu doit être affiché.

Retour :

Cette route retour un tableau d'objet JSON. Chaque object est soit un dossier, soit un fichier.

Voici l'exemple d'un objet fichier. Cet objet se trouve dans un tableau.

```json
{
  "paths": "/a",
  "login": "a",
  "parent": null,
  "file_id": "ab",
  "file_name": "deux"
}
```

Voici l'exemple d'un objet dossier. Cet objet se trouve dans un tableau.

```json
{
  "paths": "/a/coucou",
  "login": "a",
  "parent": "/a",
  "file_id": null,
  "file_name": null
}
```

Un dossier possède un parent, car il se trouve dans un dossier. Dans le cas du dossier, le champ *path* indique la ou se trouve le fichier ainsi que son nom. Le dernier élément est le nom, tandis que tout ce qui se trouve avant est la ou est stocké le fichier.

A l'inverse, un fichier se trouve dans un dossier, il a donc un *path*. Il est certe enfant d'un dossier, mais la seule information de ou il se trouve nous suffit.

### /create-path*

Cette fonction permet de créer un dossier à un endroit spécifique.

Paramètres : 

- token : Token d'authentification de l'utilisateur.
- path : Il s'agit du nouveau dossier à créer.

### /get-info

La route get-info nous permet de récupérer les informations d'un fichier.

Paramètres : 

- file_id : Id du fichier dont on souhaite avoir les informations.
- token : Il s'agit du token d'authentification.

### /show-shared-file

Cette route permet de récupérer tous les fichiers partagé avec un utilisateur.

Paramètres :

- token : Le token nous permet de récupérer l'id de l'utilisateur.

Retour : 

La réponse est un tableau d'objet JSON. Chaque objet contient ces informations :

```json
{
  "login": "b", // La personne qui a cherché le fichier
  "file_id": "abcd", // Id du fichier
  "file_name": "un" // Nom du fichier
}
```

## Conclusion

Lors du développement de ce drive, nous avons pu utiliser des technologies nouvelles ainsi qu'un manière intéressante de dévelloper. La programmation asynchrone fut difficile à prendre en main, mais nous y somme arrivé. Le développement de ce drive fut fort interessant et captivant, nous avons pris beaucoup de plaisir. Le temps nous a malheureusement manqué pour nous permettre de faire quelque chose qui nous satisfait à 100%.

Nous vous proposons quand même une version intéressante et bien aboutit. Certaines fonctionnalités prévue au début on été revue et même parfois supprimées car leur présence ne faisait aucun sens.
 No newline at end of file

projet/db/data.sql

0 → 100644
+38 −0
Original line number Diff line number Diff line
USE hyperdrive;

INSERT INTO Users
VALUES 
    ("a", "test"),
    ("b", "test"),
    ("c", "test"),
    ("d", "test"),
    ("e", "test");

INSERT INTO Paths
VALUES
    ("/a", "a", NULL),
    ("/a/coucou", "a", "/a"),
    ("/a/coucou/test", "a", "/a/coucou"),
    ("/b", "b", NULL),
    ("/c", "c", NULL),
    ("/c/test", "c", "/c"),
    ("/d", "d", NULL),
    ("/e", "e", NULL);

INSERT INTO Files
VALUES
    ("abcd", "un", "/a", 46.2054, 6.1459),
    ("adssb", "deux", "/a", 46.2054, 6.1459),
    ("accb", "deux", "/a/coucou", 46.2054, 6.1459),
    ("abnnnnn", "deux", "/a/coucou", 46.2054, 6.1459),
    ("@dfsg", "trois", "/c/test", 46.2054, 6.1459),
    ("gbvaf", "quatre", "/b", 46.2054, 6.1459),
    ("dsfgh", "cinq", "/d", 46.2054, 6.1459),
    ("sdfa", "six", "/e", 46.2054, 6.1459);

INSERT INTO Shares
VALUES
    ("a", "b", "abcd"),
    ("a", "c", "abcd"),
    ("a", "d", "abcd"),
    ("c", "e", "@dfsg");
+17 −0
Original line number Diff line number Diff line
version: '3'
services:
    db:
        image: mysql:5
        restart: always
        container_name: hyperdrive
        environment:
            MYSQL_ROOT_PASSWORD: superhyper
            MYSQL_DATABASE: hyperdrive
            MYSQL_USER: hyperdrive
            MYSQL_PASSWORD: hyper
        ports:
            - '3306:3306'
        expose:
            - 3306
        volumes:
            - ./hyperdrive.sql:/docker-entrypoint-initdb.d/hyperdrive.sql
 No newline at end of file
+86 −0
Original line number Diff line number Diff line
CREATE DATABASE IF NOT EXISTS `hyperdrive` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `hyperdrive`;

-- mysql -h localhost -P 3306 --protocol=tcp -u root -p
-- Creating tables

CREATE TABLE IF NOT EXISTS Users (
    login varchar(60) NOT NULL,
    passwd varchar(256) NOT NULL,
    PRIMARY KEY (login)
);

CREATE TABLE IF NOT EXISTS Paths (
    paths varchar(400) NOT NULL,
    login varchar(60) NOT NULL,
    parent varchar(400),
    PRIMARY KEY (paths),
    FOREIGN KEY (login) REFERENCES Users(login),
    FOREIGN KEY (parent) REFERENCES Paths(paths)
);

CREATE TABLE IF NOT EXISTS Files (
    file_id varchar(100) NOT NULL,
    file_name varchar(50) NOT NULL,
    login varchar(60) NOT NULL,
    paths varchar(400) NOT NULL,
    lat FLOAT,
    lng FLOAT,
    PRIMARY KEY (file_id),
    FOREIGN KEY (paths) REFERENCES Paths(paths),
    FOREIGN KEY (login) REFERENCES Users(login)
);

CREATE TABLE IF NOT EXISTS Shares (
    pseudo_1 varchar(60) NOT NULL,
    pseudo_2 varchar(60) NOT NULL,
    file_id varchar(100) NOT NULL,
    PRIMARY KEY (pseudo_1, pseudo_2, file_id),
    FOREIGN KEY (pseudo_1) REFERENCES Users(login),
    FOREIGN KEY (pseudo_2) REFERENCES Users(login),
    FOREIGN KEY (file_id) REFERENCES Files(file_id)
);


-- Inserting datas
INSERT INTO Users
VALUES 
    ("a", "test"),
    ("b", "test"),
    ("c", "test"),
    ("d", "test"),
    ("e", "test"),
    ("noe", "prov");

INSERT INTO Paths
VALUES
    ("/a", "a", NULL),
    ("/a/coucou", "a", "/a"),
    ("/b", "b", NULL),
    ("/c", "c", NULL),
    ("/c/test", "c", "/c"),
    ("/d", "d", NULL),
    ("/e", "e", NULL),
    ("/n", "noe", NULL);

INSERT INTO Files
VALUES
    ("abcd", "un", 'a', "/a", 46.2054, 6.1459),
    ("ab", "deux", 'a', "/a", 46.2054, 6.1459),
    ("@dfsg", "trois", 'c', "/c/test", 46.2054, 6.1459),
    ("gbvaf", "quatre", 'b', "/b", 46.2054, 6.1459),
    ("dsfgh", "cinq", 'd', "/d", 46.2054, 6.1459),
    ("sdfa", "six.txt", 'e', "/e", 46.2054, 6.1459),
    ("liblb", "myfile.txt", 'noe', "/n", 46.2054, 6.1459);

INSERT INTO Shares
VALUES
    ("a", "b", "abcd"),
    ("a", "c", "abcd"),
    ("a", "d", "abcd"),
    ("c", "e", "@dfsg");


SELECT pseudo_2, Files.file_id, Files.file_name
FROM Shares LEFT JOIN Files ON Shares.file_id=Files.file_id
WHERE pseudo_2='b';
 No newline at end of file

projet/db/request.sql

0 → 100644
+8 −0
Original line number Diff line number Diff line
-- Get content of a folder
-- paths | login | parent | file_id | file_name 
SELECT Paths.paths, login, parent, Files.file_id, Files.file_name FROM Paths 
LEFT JOIN Files ON Files.paths = Paths.paths 
WHERE Files.file_id IS NOT NULL 
AND login='a'
AND Paths.paths='/a/coucou'
OR Paths.parent='/a/coucou';
 No newline at end of file

projet/files/liblb

0 → 100644
+1 −0
Original line number Diff line number Diff line
coucou nicolas

projet/files/sdfa

0 → 100644
+1 −0
Original line number Diff line number Diff line
nothing to see here..
+51 −0
Original line number Diff line number Diff line
function new_file(file_name, file_id, document_id) {
    content = `
        <div class="file" id="${file_id}">
            <p>
                <button onclick="getInfo('${file_id}')">
                    <img src="/images/file_img.png" height="50px">
                </button>
                <p>${file_name}</p>
            </p>
        </div>
    `
    document.getElementById(document_id).innerHTML += content;
}

function new_folder (folder_name, path) {
    content = `
        <div class="folder">
            <p>
                <button onclick="change_path('${path}')">
                    <img src="/images/folder_img.png" height="50px">
                </button>
                <p>${folder_name}</p>
            </p>
        </div>
        `;
    document.getElementById("content-drive").innerHTML += content;
}

function show_info(infos){
    let el = document.getElementById("info-content");
/*
addedon: 1576691707
file_id: "abcd"
file_name: "un"
lat: 46.2054
lng: 6.1459
login: "a"
paths: "/a"
*/
    el.innerHTML = `
        <p>File name : ${infos.file_name}</p>
        <p>Path : ${infos.paths}</p>
        <p>Owner : ${infos.login}</p>
        <p>Localisation :<br>
                lat : ${infos.lat}<br>
                lng : ${infos.lng}
        </p>
        <p>Adresse : Mettre adresse avec gmap ou autre</p>
        <button onclick="download('${infos.file_id}')">Download</button>
    `;
}
 No newline at end of file
+57 −0
Original line number Diff line number Diff line
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="/styles/style.css">
    <script src="jquery-3.4.1.min.js"></script>
    <script src="element-style.js"></script>
    <script src="show-content.js"></script>
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1>Hyperdrive</h1>
    <div id="hyperdrive">
        <div id="menu">
            <h3>Menu</h3>
            <div id="login-div">
                <input type="text" id="username"><br>
                <input type="password" id="passwd"><br>
                <button onclick="login()" id="login-button">Login</button>
            </div>
            <div id="menu-more" style="display: none;">
                <input type="text" id="foldername" placeholder="folder name">
                <button onclick="newFolder()">New Folder</button><br>
                <input type="text" id="filename" placeholder="file name">
                <button onclick="newFile()">New File</button><br>
                <button onclick="showSharedContent()">Shared with me</button>
            </div>
        </div> 
        <div id="drive">
            <h3>Drive</h3>
            <div id="dir_name"></div>
            <div id="content-drive">

            </div>
            <form action="/upload/n" method="POST" encType="multipart/form-data">
                Choose a file :<br>
                <input type="file" name="my_file"><br>
                <input type="submit" value="Send">
              </form>
        </div>
        <div id="info">
            <h3>Infos</h3>
            <div id="info-content">

            </div>
        </div>
        <div id="shared">
            <h3>Shared with me</h3>
            <div id="shared-content">

            </div>
        </div>
    </div>
</body>
</html>
 No newline at end of file
+108 −0
Original line number Diff line number Diff line
"use strict";

let my_login = null;
let token = null;

function change_path(path) {
    document.getElementById("content-drive").innerHTML = "";
    $.ajax({url: 'change-path'+path+"/"+token, success: function(result){
        let p = path.split("/");
        if (p.length === 2){
            p = null;
        } else {
            p.pop()
            p = p.join("/");
        }
        appendLinkToParent(path, p);
        for (let i in result){
            if (result[i].file_id){
                new_file(result[i].file_name, result[i].file_id, "content-drive");
            } else {
                if (path !== result[i].paths){
                    let name = result[i].paths.split("/");
                    new_folder(name[name.length-1], result[i].paths);
                }
            }
        }
    }});
}

function appendLinkToParent(path, parent) {
    let el = document.getElementById("dir_name");
    let btn = ""
    if (parent) {
        btn = `<button onclick="change_path('${parent}')"><-</button>`;
    }
    el.innerHTML = `
        <p>Directory :</p> 
        <p id="path-dir-drive">${path}</p>
        ${btn}
    `;

}

function login() {
    let username = document.getElementById("username").value
    let passwd = document.getElementById("passwd").value

    $.ajax({url: 'login?user='+username+'&pass='+passwd, success: function(result){
        my_login = username;
        token = result.signedToken;
        change_path('/' + username);
        let el = document.getElementById("login-button");
        el.innerHTML = "Disconnect";
        el.onclick = disconnect;
        document.getElementById("menu-more").style.display = "block";
    }});
}

function disconnect(){
    $.ajax({url: 'logout?token=' + token, success: function(result){
        token = null;
        let el = document.getElementById("login-button");
        el.innerHTML = "Login";
        el.onclick = login;
        document.getElementById("content-drive").innerHTML = "";
        document.getElementById("dir_name").innerHTML = "";
        document.getElementById("menu-more").style.display = "none";
    }});
}

function showSharedContent() {
    let el = document.getElementById("shared-content");
    $.ajax({url: '/show-shared-file?token=' + token,
        success: function(result){
            console.log(result);
            for (let i in result){
                new_file(result[i].file_name, result[i].file_id, "shared-content");
            }
        }
    });
}

function newFolder() {
    let foldername = document.getElementById("foldername").value;
    let path = document.getElementById("path-dir-drive").textContent;
    $.ajax({url: 'create-path' + path + "/" + foldername + '/' + token,
        success: function(result){
            change_path(path);
        }
    });
}

function newFile() {
    filename = document.getElementById("filename").value;
    console.log(filename);
}

function getInfo(file_id){
    $.ajax({url: 'get-info?file_id=' + file_id + '&token=' + token,
        success: function(result){
            show_info(result[0]);
        }
    });
}

function download(file_id){
    console.log("Download : " + file_id);
}
 No newline at end of file
+56 −0
Original line number Diff line number Diff line
* {
    margin: 2.5px;
    padding: 2px;
    box-sizing: border-box;
}

button {
    border: none;
    padding: 5px;
}

button:hover {
    background-color: grey;
}

#menu {
    border: solid grey 2px;
    width: 30%;
    float: left;
}

#drive {
    border: solid grey 2px;
    width: 30%;
    float: left;
}

#info {
    border: solid grey 2px;
    width: 30%;
    float: left;
}

#shared {
    border: solid grey 2px;
    width: 30%;
    float: left;
}

.folder {
    float: left;
}

.folder p{
    font-size: 10pt;
    text-align: center;
}

.file {
    float: left;
}

.file p{
    font-size: 10pt;
    text-align: center;
}
 No newline at end of file
+448 −0
Original line number Diff line number Diff line
"use strict";
const CryptoJS = require("crypto-js");
const http = require("http");
var fileupload = require("express-fileupload");
var multer  = require('multer')


var storage = multer.diskStorage(
    {
        destination: './files/',
        filename: function ( req, file, cb ) {
            cb( null, Math.round(Math.random()*100) + Date.now().toString() );
        }
    }
);
var upload = multer( { storage: storage } );


const express = require('express');
const app = express();
const port = 8080;
const sql = require('./sql-request');


///// JWT part /////

var valid_tokens = [];

String.prototype.hashCode = function() {
    var hash = 0, i, chr;
    if (this.length === 0) return hash;
    for (i = 0; i < this.length; i++) {
        chr   = this.charCodeAt(i);
        hash  = ((hash << 5) - hash) + chr;
        hash |= 0; // Convert to 32bit integer
    }
    return hash;
};

function tob64(elem){
    return Buffer.from(elem.toString()).toString('base64').slice(0, -2);
}

function Header(typ, alg){
    this.typ = typ;
    this.alg = alg;

    this.toString = function(){ return "{" + this.typ + "," + this.alg + "}"};
}

function Payload(user, pass_enc){
    this.user = user;
    this.pass_enc = pass_enc;

    this.toString = function(){ return "{" + this.user + "," + this.pass_enc + "}"};

}

function Signature(token){
    const secret = "our super hyperdrive secret" + new Date();
    return CryptoJS.HmacSHA512(token, secret);
}

function JWT(pl_user, pl_pass){
    this.header = new Header("jwt", "HS512");
    this.payload = new Payload(pl_user, pl_pass.hashCode());
    let token = tob64(this.header) + "." + tob64(this.payload);
    let signature = new Signature("token");
    this.signedToken = token + "." + signature;
}


function add_token(token, user) {

    for (let i = 0; i < valid_tokens.length; i++) {
        if(Object.keys(valid_tokens[i])[0] == token){
            valid_tokens.splice(i, 1);
            console.log("Unable to add token. (token already present)");
            break;
        }
    }
    let obj = {}; obj[token.toString()] = user;
    valid_tokens.push(obj);
    console.log(valid_tokens)

    console.log("Successfully added token.");

    
}

function remove_token(token) {

    for (let i = 0; i < valid_tokens.length; i++) {
        if(Object.keys(valid_tokens[i])[0] == token){
            valid_tokens.splice(i, 1);
            console.log("Successfully removed token from valid_tokens.");
            return true;
        }
    }

    console.log("Unable to remove token from valid_tokens. (Token not present)");


}

// verify the token
// return : user if exist
function verify_token(token) {
    for (let i = 0; i < valid_tokens.length; i++) {
        if(Object.keys(valid_tokens[i])[0] == token)
            return valid_tokens[i][token];
    }
    return false;
}


///// End JWT part /////


app.get('/', (req, res) => {
    res.sendFile(__dirname + '/front/index.html');
});

/* Login
 * param : pseudo
 * param : password
 */
// resCode : [ 0: User now logged in, 1: False password, 2: Invalid username, 3: Empty user or pass ]
app.get('/login', (req, res) => {

    const user = req.query['user'];
    const pass = req.query['pass'];
    sql.userExist(user, pass, (element) => {
        if (element)
            check_login(user, pass, element, res);
    });

});

function check_login(user, pass, userObject, res) {
    if (!user || !pass) {
        res.send({
            "route": "/login",
            "resCode": 4,
            "comment": "Please enter a username and a password."
        })
    }
    else{
        if (userObject){
            if (userObject.passwd == pass.hashCode()) {
                let jwt = new JWT(user, pass);

                res.send({
                    "route": "/login",
                    "resCode": 0,
                    "signedToken": jwt.signedToken,
                    "comment": `Password for user '${ user }' true.`
                })

                add_token(jwt.signedToken, user);

            }
            else {
                res.send({
                    "route": "/login",
                    "resCode": 1,
                    "comment": `Password for user '${ user }' false.`
                })
            }
        }
        else {
            res.send({
                "route": "/login",
                "resCode": 2,
                "comment": `Username '${ user }' don't exist.`
            })
        }
    }
}

// resCode : [ 0: Token is valid, 1: Token is not valid, 3: Empty token ]
app.get('/testmytoken', (req, res) => {

    let token = req.query['token'];

    if (!token) {
        res.send({
            "resCode": 3,
            "comment": "Please enter a token."
        })
    }
    
    if (verify_token(token)){
        res.send({
            "resCode": 0,
            "comment": "Your token is valid."
        })
    }
    else {
        res.send({
            "resCode": 1,
            "comment": "Your token is not valid."
        })
    }

})

// resCode : [ 0: Logout ok, 1: Already logged out, 3: Empty token ]
app.get('/logout/', (req, res) => {

    let token = req.query['token'];

    if (!token) {
        res.send({
            "resCode": 3,
            "comment": "Please enter a token."
        })
    }

    else {
        if (verify_token(token)){
            remove_token(token);
            res.send({
                "resCode": 0,
                "comment": "Your are now logged out."
            })
        }
        else {
            res.send({
                "resCode": 1,
                "comment": "Your are already logged out."
            })
        }
    }
    

})

/**
 * Request register
 * param : pseudo
 * param : password
 */
app.get('/register/', (req, res) => {
    sql.addUser(req.query['login'], req.query['pass']);
    res.send(`Request for a register (${req.query['login']}, ${req.query['pass']})`);
})

/**
 * Request to share a file with a user
 * param : file_id
 * param : user1
 * param : user2
 * user1 share a file_id with user2
 */
app.get('/share/:file_id/:to_user', (req, res) => {

    let token = req.query["token"]
    let user = verify_token(token);
    console.log("user : " + user)

    if (req.params['to_user'] && req.params['file_id']){
        let to_user = req.params['to_user'];
        let file_id = req.params['file_id'];
        sql.addSharing(user, to_user, file_id).then(function (r) {
            res.send(r);
        })
    }
    else{
        res.send("Unable to share. Please provide a user to share with and a file_id.");
    }
})

/**
 * Request to upload a file
 */
// app.get('/upload/', (req, res) => {
//     let d = new Date();
//     let date_upload = d.getTime();
//     // "abcd", "un", "/a", 46.2054, 6.1459, date_upload



//     res.send(`Request for an upload (${req.query['file']})`)
// });



app.post('/upload*', upload.single('my_file'), (req, res) => {
    // res.send(`Request for an upload (${req.query['file']})`)

    let token = req.query["token"]
    let user = verify_token(token)

    if (user){
        let path = req.params['0']

        if (req.file){
    
            var file_id = Math.round(Math.random() * 100) + Date.now();
            var file_name = "test"
    
    
              
    
            let lat;
            let lon;
    
            http.get('http://bot.whatismyipaddress.com', (result) => {
                result.setEncoding('utf8');
                result.on('data', function(chunk){
                    let ip = chunk;
                    http.get('http://ip-api.com/json/' + ip, (resp) => {
                        let data = '';
                        resp.on('data', (chunk) => {
                            data += chunk;
                        });
        
                        resp.on('end', () => {
                            lat = JSON.parse(data).lat.toFixed(3);
                            lon = JSON.parse(data).lon.toFixed(3);
    
                            // add to BDD
                            sql.addFile(file_id, file_name, user, path, lat, lon, (result) => {
                                res.send(result)
                            })
    
                        });
                    });
                });
            });
        }
        else{
            console.log("Please enter a file");
        }
    }
    else{
        res.send("Please be connected")
    }
    

})

app.get('/download/:file_id', (req, res) => {
    let token = req.query["token"]
    

    let user = verify_token(token);
    if (user){
        sql.verifyFileID(user, file_id, (filename) => {
            console.log(filename)
            if (filename){
                res.download("files/" + file_id, filename);
            }
            else{
                res.send("Can't download (not your file).")
            }
        })
    }
    else{
        res.send("Can't download (please be connected).")
    }
})

/**
 * This function return the content of a path
 * param path : Path of the folder we want to show
 */
app.get('/change-path*', (req, res) => {
    let path = req.params['0'].split("/");
    path.pop();
    path = path.join("/");
    let tok = req.params['0'].split("/").pop();
    let name = verify_token(tok);
    if (name) {
        sql.changeDirectory(name, path,
        (content) => {
            res.send(content);
        });
    }
})

app.get('/create-path*', (req, res) => {
    let c = req.params['0'];

    let tok = c.split("/").pop();
    let path = c.split("/");
    path.pop();
    path = path.join("/");

    let parent = path.split("/");
    parent.pop();
    parent = parent.join("/");

    let name = verify_token(tok);
    if (name) {
        sql.addPath(path, name, parent, (resp, msg) => {
            console.log(resp, msg);
            res.send(resp + " : " + msg);
        });
    }
})

/**
 * Get info of a file
 * @param {string} file_id Id of the file we want the infos
 * @param {string} token Token of the client
 */
app.get('/get-info', (req, res) => {
    let token = req.query["token"];
    let file_id = req.query["file_id"];
    let name = verify_token(token);
    console.log(token);
    if (name){
        sql.getInfo(file_id, name, (resp, msg) => {
            res.send(resp);
        });
    }
});

/**
 * 
 */
app.get('/show-shared-file', (req, res) => {
    let token = req.query["token"];
    let name = verify_token(token);
    if (name){
        sql.getSharedFile(name, (result) => {
            if (result){
                let content = [];
                for (let i in result){
                    console.log(result[i]);
                    content.push({
                        login: result[i].pseudo_2,
                        file_id: result[i].file_id,
                        file_name: result[i].file_name
                    });
                }
                res.send(content);
            }
        });
    }
});

app.use(express.static('front'));
app.use(fileupload());
var upload = multer({ dest: "files/" })
app.listen(port, () => console.log(`Hyperdrive listening on port ${port}!`))
+236 −0
Original line number Diff line number Diff line
1.3.7 / 2019-04-29
==================

  * deps: negotiator@0.6.2
    - Fix sorting charset, encoding, and language with extra parameters

1.3.6 / 2019-04-28
==================

  * deps: mime-types@~2.1.24
    - deps: mime-db@~1.40.0

1.3.5 / 2018-02-28
==================

  * deps: mime-types@~2.1.18
    - deps: mime-db@~1.33.0

1.3.4 / 2017-08-22
==================

  * deps: mime-types@~2.1.16
    - deps: mime-db@~1.29.0

1.3.3 / 2016-05-02
==================

  * deps: mime-types@~2.1.11
    - deps: mime-db@~1.23.0
  * deps: negotiator@0.6.1
    - perf: improve `Accept` parsing speed
    - perf: improve `Accept-Charset` parsing speed
    - perf: improve `Accept-Encoding` parsing speed
    - perf: improve `Accept-Language` parsing speed

1.3.2 / 2016-03-08
==================

  * deps: mime-types@~2.1.10
    - Fix extension of `application/dash+xml`
    - Update primary extension for `audio/mp4`
    - deps: mime-db@~1.22.0

1.3.1 / 2016-01-19
==================

  * deps: mime-types@~2.1.9
    - deps: mime-db@~1.21.0

1.3.0 / 2015-09-29
==================

  * deps: mime-types@~2.1.7
    - deps: mime-db@~1.19.0
  * deps: negotiator@0.6.0
    - Fix including type extensions in parameters in `Accept` parsing
    - Fix parsing `Accept` parameters with quoted equals
    - Fix parsing `Accept` parameters with quoted semicolons
    - Lazy-load modules from main entry point
    - perf: delay type concatenation until needed
    - perf: enable strict mode
    - perf: hoist regular expressions
    - perf: remove closures getting spec properties
    - perf: remove a closure from media type parsing
    - perf: remove property delete from media type parsing

1.2.13 / 2015-09-06
===================

  * deps: mime-types@~2.1.6
    - deps: mime-db@~1.18.0

1.2.12 / 2015-07-30
===================

  * deps: mime-types@~2.1.4
    - deps: mime-db@~1.16.0

1.2.11 / 2015-07-16
===================

  * deps: mime-types@~2.1.3
    - deps: mime-db@~1.15.0

1.2.10 / 2015-07-01
===================

  * deps: mime-types@~2.1.2
    - deps: mime-db@~1.14.0

1.2.9 / 2015-06-08
==================

  * deps: mime-types@~2.1.1
    - perf: fix deopt during mapping

1.2.8 / 2015-06-07
==================

  * deps: mime-types@~2.1.0
    - deps: mime-db@~1.13.0
  * perf: avoid argument reassignment & argument slice
  * perf: avoid negotiator recursive construction
  * perf: enable strict mode
  * perf: remove unnecessary bitwise operator

1.2.7 / 2015-05-10
==================

  * deps: negotiator@0.5.3
    - Fix media type parameter matching to be case-insensitive

1.2.6 / 2015-05-07
==================

  * deps: mime-types@~2.0.11
    - deps: mime-db@~1.9.1
  * deps: negotiator@0.5.2
    - Fix comparing media types with quoted values
    - Fix splitting media types with quoted commas

1.2.5 / 2015-03-13
==================

  * deps: mime-types@~2.0.10
    - deps: mime-db@~1.8.0

1.2.4 / 2015-02-14
==================

  * Support Node.js 0.6
  * deps: mime-types@~2.0.9
    - deps: mime-db@~1.7.0
  * deps: negotiator@0.5.1
    - Fix preference sorting to be stable for long acceptable lists

1.2.3 / 2015-01-31
==================

  * deps: mime-types@~2.0.8
    - deps: mime-db@~1.6.0

1.2.2 / 2014-12-30
==================

  * deps: mime-types@~2.0.7
    - deps: mime-db@~1.5.0

1.2.1 / 2014-12-30
==================

  * deps: mime-types@~2.0.5
    - deps: mime-db@~1.3.1

1.2.0 / 2014-12-19
==================

  * deps: negotiator@0.5.0
    - Fix list return order when large accepted list
    - Fix missing identity encoding when q=0 exists
    - Remove dynamic building of Negotiator class

1.1.4 / 2014-12-10
==================

  * deps: mime-types@~2.0.4
    - deps: mime-db@~1.3.0

1.1.3 / 2014-11-09
==================

  * deps: mime-types@~2.0.3
    - deps: mime-db@~1.2.0

1.1.2 / 2014-10-14
==================

  * deps: negotiator@0.4.9
    - Fix error when media type has invalid parameter

1.1.1 / 2014-09-28
==================

  * deps: mime-types@~2.0.2
    - deps: mime-db@~1.1.0
  * deps: negotiator@0.4.8
    - Fix all negotiations to be case-insensitive
    - Stable sort preferences of same quality according to client order

1.1.0 / 2014-09-02
==================

  * update `mime-types`

1.0.7 / 2014-07-04
==================

  * Fix wrong type returned from `type` when match after unknown extension

1.0.6 / 2014-06-24
==================

  * deps: negotiator@0.4.7

1.0.5 / 2014-06-20
==================

 * fix crash when unknown extension given

1.0.4 / 2014-06-19
==================

  * use `mime-types`

1.0.3 / 2014-06-11
==================

  * deps: negotiator@0.4.6
    - Order by specificity when quality is the same

1.0.2 / 2014-05-29
==================

  * Fix interpretation when header not in request
  * deps: pin negotiator@0.4.5

1.0.1 / 2014-01-18
==================

  * Identity encoding isn't always acceptable
  * deps: negotiator@~0.4.0

1.0.0 / 2013-12-27
==================

  * Genesis
+23 −0
Original line number Diff line number Diff line
(The MIT License)

Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+142 −0
Original line number Diff line number Diff line
# accepts

[![NPM Version][npm-version-image]][npm-url]
[![NPM Downloads][npm-downloads-image]][npm-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]

Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator).
Extracted from [koa](https://www.npmjs.com/package/koa) for general use.

In addition to negotiator, it allows:

- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])`
  as well as `('text/html', 'application/json')`.
- Allows type shorthands such as `json`.
- Returns `false` when no types match
- Treats non-existent headers as `*`

## Installation

This is a [Node.js](https://nodejs.org/en/) module available through the
[npm registry](https://www.npmjs.com/). Installation is done using the
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

```sh
$ npm install accepts
```

## API

<!-- eslint-disable no-unused-vars -->

```js
var accepts = require('accepts')
```

### accepts(req)

Create a new `Accepts` object for the given `req`.

#### .charset(charsets)

Return the first accepted charset. If nothing in `charsets` is accepted,
then `false` is returned.

#### .charsets()

Return the charsets that the request accepts, in the order of the client's
preference (most preferred first).

#### .encoding(encodings)

Return the first accepted encoding. If nothing in `encodings` is accepted,
then `false` is returned.

#### .encodings()

Return the encodings that the request accepts, in the order of the client's
preference (most preferred first).

#### .language(languages)

Return the first accepted language. If nothing in `languages` is accepted,
then `false` is returned.

#### .languages()

Return the languages that the request accepts, in the order of the client's
preference (most preferred first).

#### .type(types)

Return the first accepted type (and it is returned as the same text as what
appears in the `types` array). If nothing in `types` is accepted, then `false`
is returned.

The `types` array can contain full MIME types or file extensions. Any value
that is not a full MIME types is passed to `require('mime-types').lookup`.

#### .types()

Return the types that the request accepts, in the order of the client's
preference (most preferred first).

## Examples

### Simple type negotiation

This simple example shows how to use `accepts` to return a different typed
respond body based on what the client wants to accept. The server lists it's
preferences in order and will get back the best match between the client and
server.

```js
var accepts = require('accepts')
var http = require('http')

function app (req, res) {
  var accept = accepts(req)

  // the order of this list is significant; should be server preferred order
  switch (accept.type(['json', 'html'])) {
    case 'json':
      res.setHeader('Content-Type', 'application/json')
      res.write('{"hello":"world!"}')
      break
    case 'html':
      res.setHeader('Content-Type', 'text/html')
      res.write('<b>hello, world!</b>')
      break
    default:
      // the fallback is text/plain, so no need to specify it above
      res.setHeader('Content-Type', 'text/plain')
      res.write('hello, world!')
      break
  }

  res.end()
}

http.createServer(app).listen(3000)
```

You can test this out with the cURL program:
```sh
curl -I -H'Accept: text/html' http://localhost:3000/
```

## License

[MIT](LICENSE)

[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master
[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master
[node-version-image]: https://badgen.net/npm/node/accepts
[node-version-url]: https://nodejs.org/en/download
[npm-downloads-image]: https://badgen.net/npm/dm/accepts
[npm-url]: https://npmjs.org/package/accepts
[npm-version-image]: https://badgen.net/npm/v/accepts
[travis-image]: https://badgen.net/travis/jshttp/accepts/master
[travis-url]: https://travis-ci.org/jshttp/accepts
+238 −0
Original line number Diff line number Diff line
/*!
 * accepts
 * Copyright(c) 2014 Jonathan Ong
 * Copyright(c) 2015 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict'

/**
 * Module dependencies.
 * @private
 */

var Negotiator = require('negotiator')
var mime = require('mime-types')

/**
 * Module exports.
 * @public
 */

module.exports = Accepts

/**
 * Create a new Accepts object for the given req.
 *
 * @param {object} req
 * @public
 */

function Accepts (req) {
  if (!(this instanceof Accepts)) {
    return new Accepts(req)
  }

  this.headers = req.headers
  this.negotiator = new Negotiator(req)
}

/**
 * Check if the given `type(s)` is acceptable, returning
 * the best match when true, otherwise `undefined`, in which
 * case you should respond with 406 "Not Acceptable".
 *
 * The `type` value may be a single mime type string
 * such as "application/json", the extension name
 * such as "json" or an array `["json", "html", "text/plain"]`. When a list
 * or array is given the _best_ match, if any is returned.
 *
 * Examples:
 *
 *     // Accept: text/html
 *     this.types('html');
 *     // => "html"
 *
 *     // Accept: text/*, application/json
 *     this.types('html');
 *     // => "html"
 *     this.types('text/html');
 *     // => "text/html"
 *     this.types('json', 'text');
 *     // => "json"
 *     this.types('application/json');
 *     // => "application/json"
 *
 *     // Accept: text/*, application/json
 *     this.types('image/png');
 *     this.types('png');
 *     // => undefined
 *
 *     // Accept: text/*;q=.5, application/json
 *     this.types(['html', 'json']);
 *     this.types('html', 'json');
 *     // => "json"
 *
 * @param {String|Array} types...
 * @return {String|Array|Boolean}
 * @public
 */

Accepts.prototype.type =
Accepts.prototype.types = function (types_) {
  var types = types_

  // support flattened arguments
  if (types && !Array.isArray(types)) {
    types = new Array(arguments.length)
    for (var i = 0; i < types.length; i++) {
      types[i] = arguments[i]
    }
  }

  // no types, return all requested types
  if (!types || types.length === 0) {
    return this.negotiator.mediaTypes()
  }

  // no accept header, return first given type
  if (!this.headers.accept) {
    return types[0]
  }

  var mimes = types.map(extToMime)
  var accepts = this.negotiator.mediaTypes(mimes.filter(validMime))
  var first = accepts[0]

  return first
    ? types[mimes.indexOf(first)]
    : false
}

/**
 * Return accepted encodings or best fit based on `encodings`.
 *
 * Given `Accept-Encoding: gzip, deflate`
 * an array sorted by quality is returned:
 *
 *     ['gzip', 'deflate']
 *
 * @param {String|Array} encodings...
 * @return {String|Array}
 * @public
 */

Accepts.prototype.encoding =
Accepts.prototype.encodings = function (encodings_) {
  var encodings = encodings_

  // support flattened arguments
  if (encodings && !Array.isArray(encodings)) {
    encodings = new Array(arguments.length)
    for (var i = 0; i < encodings.length; i++) {
      encodings[i] = arguments[i]
    }
  }

  // no encodings, return all requested encodings
  if (!encodings || encodings.length === 0) {
    return this.negotiator.encodings()
  }

  return this.negotiator.encodings(encodings)[0] || false
}

/**
 * Return accepted charsets or best fit based on `charsets`.
 *
 * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
 * an array sorted by quality is returned:
 *
 *     ['utf-8', 'utf-7', 'iso-8859-1']
 *
 * @param {String|Array} charsets...
 * @return {String|Array}
 * @public
 */

Accepts.prototype.charset =
Accepts.prototype.charsets = function (charsets_) {
  var charsets = charsets_

  // support flattened arguments
  if (charsets && !Array.isArray(charsets)) {
    charsets = new Array(arguments.length)
    for (var i = 0; i < charsets.length; i++) {
      charsets[i] = arguments[i]
    }
  }

  // no charsets, return all requested charsets
  if (!charsets || charsets.length === 0) {
    return this.negotiator.charsets()
  }

  return this.negotiator.charsets(charsets)[0] || false
}

/**
 * Return accepted languages or best fit based on `langs`.
 *
 * Given `Accept-Language: en;q=0.8, es, pt`
 * an array sorted by quality is returned:
 *
 *     ['es', 'pt', 'en']
 *
 * @param {String|Array} langs...
 * @return {Array|String}
 * @public
 */

Accepts.prototype.lang =
Accepts.prototype.langs =
Accepts.prototype.language =
Accepts.prototype.languages = function (languages_) {
  var languages = languages_

  // support flattened arguments
  if (languages && !Array.isArray(languages)) {
    languages = new Array(arguments.length)
    for (var i = 0; i < languages.length; i++) {
      languages[i] = arguments[i]
    }
  }

  // no languages, return all requested languages
  if (!languages || languages.length === 0) {
    return this.negotiator.languages()
  }

  return this.negotiator.languages(languages)[0] || false
}

/**
 * Convert extnames to mime.
 *
 * @param {String} type
 * @return {String}
 * @private
 */

function extToMime (type) {
  return type.indexOf('/') === -1
    ? mime.lookup(type)
    : type
}

/**
 * Check if mime is valid.
 *
 * @param {String} type
 * @return {String}
 * @private
 */

function validMime (type) {
  return typeof type === 'string'
}
Original line number Diff line number Diff line
{
  "_args": [
    [
      "accepts@1.3.7",
      "/Users/klaus/Documents/Web/Back/2019_tp2/projet"
    ]
  ],
  "_from": "accepts@1.3.7",
  "_id": "accepts@1.3.7",
  "_inBundle": false,
  "_integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
  "_location": "/accepts",
  "_phantomChildren": {},
  "_requested": {
    "type": "version",
    "registry": true,
    "raw": "accepts@1.3.7",
    "name": "accepts",
    "escapedName": "accepts",
    "rawSpec": "1.3.7",
    "saveSpec": null,
    "fetchSpec": "1.3.7"
  },
  "_requiredBy": [
    "/express"
  ],
  "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
  "_spec": "1.3.7",
  "_where": "/Users/klaus/Documents/Web/Back/2019_tp2/projet",
  "bugs": {
    "url": "https://github.com/jshttp/accepts/issues"
  },
  "contributors": [
    {
      "name": "Douglas Christopher Wilson",
      "email": "doug@somethingdoug.com"
    },
    {
      "name": "Jonathan Ong",
      "email": "me@jongleberry.com",
      "url": "http://jongleberry.com"
    }
  ],
  "dependencies": {
    "mime-types": "~2.1.24",
    "negotiator": "0.6.2"
  },
  "description": "Higher-level content negotiation",
  "devDependencies": {
    "deep-equal": "1.0.1",
    "eslint": "5.16.0",
    "eslint-config-standard": "12.0.0",
    "eslint-plugin-import": "2.17.2",
    "eslint-plugin-markdown": "1.0.0",
    "eslint-plugin-node": "8.0.1",
    "eslint-plugin-promise": "4.1.1",
    "eslint-plugin-standard": "4.0.0",
    "mocha": "6.1.4",
    "nyc": "14.0.0"
  },
  "engines": {
    "node": ">= 0.6"
  },
  "files": [
    "LICENSE",
    "HISTORY.md",
    "index.js"
  ],
  "homepage": "https://github.com/jshttp/accepts#readme",
  "keywords": [
    "content",
    "negotiation",
    "accept",
    "accepts"
  ],
  "license": "MIT",
  "name": "accepts",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/jshttp/accepts.git"
  },
  "scripts": {
    "lint": "eslint --plugin markdown --ext js,md .",
    "test": "mocha --reporter spec --check-leaks --bail test/",
    "test-cov": "nyc --reporter=html --reporter=text npm test",
    "test-travis": "nyc --reporter=text npm test"
  },
  "version": "1.3.7"
}
Original line number Diff line number Diff line
The MIT License (MIT)

Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Original line number Diff line number Diff line
# Array Flatten

[![NPM version][npm-image]][npm-url]
[![NPM downloads][downloads-image]][downloads-url]
[![Build status][travis-image]][travis-url]
[![Test coverage][coveralls-image]][coveralls-url]

> Flatten an array of nested arrays into a single flat array. Accepts an optional depth.

## Installation

```
npm install array-flatten --save
```

## Usage

```javascript
var flatten = require('array-flatten')

flatten([1, [2, [3, [4, [5], 6], 7], 8], 9])
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9]

flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2)
//=> [1, 2, 3, [4, [5], 6], 7, 8, 9]

(function () {
  flatten(arguments) //=> [1, 2, 3]
})(1, [2, 3])
```

## License

MIT

[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat
[npm-url]: https://npmjs.org/package/array-flatten
[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat
[downloads-url]: https://npmjs.org/package/array-flatten
[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat
[travis-url]: https://travis-ci.org/blakeembrey/array-flatten
[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat
[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master
Original line number Diff line number Diff line
'use strict'

/**
 * Expose `arrayFlatten`.
 */
module.exports = arrayFlatten

/**
 * Recursive flatten function with depth.
 *
 * @param  {Array}  array
 * @param  {Array}  result
 * @param  {Number} depth
 * @return {Array}
 */
function flattenWithDepth (array, result, depth) {
  for (var i = 0; i < array.length; i++) {
    var value = array[i]

    if (depth > 0 && Array.isArray(value)) {
      flattenWithDepth(value, result, depth - 1)
    } else {
      result.push(value)
    }
  }

  return result
}

/**
 * Recursive flatten function. Omitting depth is slightly faster.
 *
 * @param  {Array} array
 * @param  {Array} result
 * @return {Array}
 */
function flattenForever (array, result) {
  for (var i = 0; i < array.length; i++) {
    var value = array[i]

    if (Array.isArray(value)) {
      flattenForever(value, result)
    } else {
      result.push(value)
    }
  }

  return result
}

/**
 * Flatten an array, with the ability to define a depth.
 *
 * @param  {Array}  array
 * @param  {Number} depth
 * @return {Array}
 */
function arrayFlatten (array, depth) {
  if (depth == null) {
    return flattenForever(array, [])
  }

  return flattenWithDepth(array, [], depth)
}
Original line number Diff line number Diff line
{
  "_args": [
    [
      "array-flatten@1.1.1",
      "/Users/klaus/Documents/Web/Back/2019_tp2/projet"
    ]
  ],
  "_from": "array-flatten@1.1.1",
  "_id": "array-flatten@1.1.1",
  "_inBundle": false,
  "_integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
  "_location": "/array-flatten",
  "_phantomChildren": {},
  "_requested": {
    "type": "version",
    "registry": true,
    "raw": "array-flatten@1.1.1",
    "name": "array-flatten",
    "escapedName": "array-flatten",
    "rawSpec": "1.1.1",
    "saveSpec": null,
    "fetchSpec": "1.1.1"
  },
  "_requiredBy": [
    "/express"
  ],
  "_resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
  "_spec": "1.1.1",
  "_where": "/Users/klaus/Documents/Web/Back/2019_tp2/projet",
  "author": {
    "name": "Blake Embrey",
    "email": "hello@blakeembrey.com",
    "url": "http://blakeembrey.me"
  },
  "bugs": {
    "url": "https://github.com/blakeembrey/array-flatten/issues"
  },
  "description": "Flatten an array of nested arrays into a single flat array",
  "devDependencies": {
    "istanbul": "^0.3.13",
    "mocha": "^2.2.4",
    "pre-commit": "^1.0.7",
    "standard": "^3.7.3"
  },
  "files": [
    "array-flatten.js",
    "LICENSE"
  ],
  "homepage": "https://github.com/blakeembrey/array-flatten",
  "keywords": [
    "array",
    "flatten",
    "arguments",
    "depth"
  ],
  "license": "MIT",
  "main": "array-flatten.js",
  "name": "array-flatten",
  "repository": {
    "type": "git",
    "url": "git://github.com/blakeembrey/array-flatten.git"
  },
  "scripts": {
    "test": "istanbul cover _mocha -- -R spec"
  },
  "version": "1.1.1"
}
Original line number Diff line number Diff line
#### 7.2.1
* 24/05/2018
* Add `browser` field to *package.json*.

#### 7.2.0
* 22/05/2018
* #166 Correct *.mjs* file. Remove extension from `main` field in *package.json*.

#### 7.1.0
* 18/05/2018
* Add `module` field to *package.json* for *bignumber.mjs*.

#### 7.0.2
* 17/05/2018
* #165 Bugfix: upper-case letters for bases 11-36 in a custom alphabet.
* Add note to *README* regarding creating BigNumbers from Number values.

#### 7.0.1
* 26/04/2018
* #158 Fix global object variable name typo.

#### 7.0.0
* 26/04/2018
* #143 Remove global BigNumber from typings.
* #144 Enable compatibility with `Object.freeze(Object.prototype)`.
* #148 #123 #11 Only throw on a number primitive with more than 15 significant digits if `BigNumber.DEBUG` is `true`.
* Only throw on an invalid BigNumber value if `BigNumber.DEBUG` is `true`. Return BigNumber `NaN` instead.
* #154 `exponentiatedBy`: allow BigNumber exponent.
* #156 Prevent Content Security Policy *unsafe-eval* issue.
* `toFraction`: allow `Infinity` maximum denominator.
* Comment-out some excess tests to reduce test time.
* Amend indentation and other spacing.

#### 6.0.0
* 26/01/2018
* #137 Implement `APLHABET` configuration option.
* Remove `ERRORS` configuration option.
* Remove `toDigits` method; extend `precision` method accordingly.
* Remove s`round` method; extend `decimalPlaces` method accordingly.
* Remove methods: `ceil`, `floor`, and `truncated`.
* Remove method aliases: `add`, `cmp`, `isInt`, `isNeg`, `trunc`, `mul`, `neg` and `sub`.
* Rename methods: `shift` to `shiftedBy`, `another` to `clone`, `toPower` to `exponentiatedBy`, and `equals` to `isEqualTo`.
* Rename methods: add `is` prefix to `greaterThan`, `greaterThanOrEqualTo`, `lessThan` and `lessThanOrEqualTo`.
* Add methods: `multipliedBy`, `isBigNumber`, `isPositive`, `integerValue`, `maximum` and `minimum`.
* Refactor test suite.
* Add *CHANGELOG.md*.
* Rewrite *bignumber.d.ts*.
* Redo API image.

#### 5.0.0
* 27/11/2017
* #81 Don't throw on constructor call without `new`.

#### 4.1.0
* 26/09/2017
* Remove node 0.6 from *.travis.yml*.
* Add *bignumber.mjs*.

#### 4.0.4
* 03/09/2017
* Add missing aliases to *bignumber.d.ts*.

#### 4.0.3
* 30/08/2017
* Add types: *bignumber.d.ts*.

#### 4.0.2
* 03/05/2017
* #120 Workaround Safari/Webkit bug.

#### 4.0.1
* 05/04/2017
* #121 BigNumber.default to BigNumber['default'].

#### 4.0.0
* 09/01/2017
* Replace BigNumber.isBigNumber method with isBigNumber prototype property.

#### 3.1.2
* 08/01/2017
* Minor documentation edit.

#### 3.1.1
* 08/01/2017
* Uncomment `isBigNumber` tests.
* Ignore dot files.

#### 3.1.0
* 08/01/2017
* Add `isBigNumber` method.

#### 3.0.2
* 08/01/2017
* Bugfix: Possible incorrect value of `ERRORS` after a `BigNumber.another` call (due to `parseNumeric` declaration in outer scope).

#### 3.0.1
* 23/11/2016
* Apply fix for old ipads with `%` issue, see #57 and #102.
* Correct error message.

#### 3.0.0
* 09/11/2016
* Remove `require('crypto')` - leave it to the user.
* Add `BigNumber.set` as `BigNumber.config` alias.
* Default `POW_PRECISION` to `0`.

#### 2.4.0
* 14/07/2016
* #97 Add exports to support ES6 imports.

#### 2.3.0
* 07/03/2016
* #86 Add modulus parameter to `toPower`.

#### 2.2.0
* 03/03/2016
* #91 Permit larger JS integers.

#### 2.1.4
* 15/12/2015
* Correct UMD.

#### 2.1.3
* 13/12/2015
* Refactor re global object and crypto availability when bundling.

#### 2.1.2
* 10/12/2015
* Bugfix: `window.crypto` not assigned to `crypto`.

#### 2.1.1
* 09/12/2015
* Prevent code bundler from adding `crypto` shim.

#### 2.1.0
* 26/10/2015
* For `valueOf` and `toJSON`, include the minus sign with negative zero.

#### 2.0.8
* 2/10/2015
* Internal round function bugfix.

#### 2.0.6
* 31/03/2015
* Add bower.json. Tweak division after in-depth review.

#### 2.0.5
* 25/03/2015
* Amend README. Remove bitcoin address.

#### 2.0.4
* 25/03/2015
* Critical bugfix #58: division.

#### 2.0.3
* 18/02/2015
* Amend README. Add source map.

#### 2.0.2
* 18/02/2015
* Correct links.

#### 2.0.1
* 18/02/2015
* Add `max`, `min`, `precision`, `random`, `shiftedBy`, `toDigits` and `truncated` methods.
* Add the short-forms: `add`, `mul`, `sd`, `sub` and `trunc`.
* Add an `another` method to enable multiple independent constructors to be created.
* Add support for the base 2, 8 and 16 prefixes `0b`, `0o` and `0x`.
* Enable a rounding mode to be specified as a second parameter to `toExponential`, `toFixed`, `toFormat` and `toPrecision`.
* Add a `CRYPTO` configuration property so cryptographically-secure pseudo-random number generation can be specified.
* Add a `MODULO_MODE` configuration property to enable the rounding mode used by the `modulo` operation to be specified.
* Add a `POW_PRECISION` configuration property to enable the number of significant digits calculated by the power operation to be limited.
* Improve code quality.
* Improve documentation.

#### 2.0.0
* 29/12/2014
* Add `dividedToIntegerBy`, `isInteger` and `toFormat` methods.
* Remove the following short-forms: `isF`, `isZ`, `toE`, `toF`, `toFr`, `toN`, `toP`, `toS`.
* Store a BigNumber's coefficient in base 1e14, rather than base 10.
* Add fast path for integers to BigNumber constructor.
* Incorporate the library into the online documentation.

#### 1.5.0
* 13/11/2014
* Add `toJSON` and `decimalPlaces` methods.

#### 1.4.1
* 08/06/2014
* Amend README.

#### 1.4.0
* 08/05/2014
* Add `toNumber`.

#### 1.3.0
* 08/11/2013
* Ensure correct rounding of `sqrt` in all, rather than almost all, cases.
* Maximum radix to 64.

#### 1.2.1
* 17/10/2013
* Sign of zero when x < 0 and x + (-x) = 0.

#### 1.2.0
* 19/9/2013
* Throw Error objects for stack.

#### 1.1.1
* 22/8/2013
* Show original value in constructor error message.

#### 1.1.0
* 1/8/2013
* Allow numbers with trailing radix point.

#### 1.0.1
* Bugfix: error messages with incorrect method name

#### 1.0.0
* 8/11/2012
* Initial release
Original line number Diff line number Diff line
The MIT Licence.

Copyright (c) 2018 Michael Mclaughlin

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Original line number Diff line number Diff line
![bignumber.js](https://raw.githubusercontent.com/MikeMcl/bignumber.js/gh-pages/bignumberjs.png)

A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic.

[![Build Status](https://travis-ci.org/MikeMcl/bignumber.js.svg)](https://travis-ci.org/MikeMcl/bignumber.js)

<br />

## Features

  - Integers and decimals
  - Simple API but full-featured
  - Faster, smaller, and perhaps easier to use than JavaScript versions of Java's BigDecimal
  - 8 KB minified and gzipped
  - Replicates the `toExponential`, `toFixed`, `toPrecision` and `toString` methods of JavaScript's Number type
  - Includes a `toFraction` and a correctly-rounded `squareRoot` method
  - Supports cryptographically-secure pseudo-random number generation
  - No dependencies
  - Wide platform compatibility: uses JavaScript 1.5 (ECMAScript 3) features only
  - Comprehensive [documentation](http://mikemcl.github.io/bignumber.js/) and test set

![API](https://raw.githubusercontent.com/MikeMcl/bignumber.js/gh-pages/API.png)

If a smaller and simpler library is required see [big.js](https://github.com/MikeMcl/big.js/).
It's less than half the size but only works with decimal numbers and only has half the methods.
It also does not allow `NaN` or `Infinity`, or have the configuration options of this library.

See also [decimal.js](https://github.com/MikeMcl/decimal.js/), which among other things adds support for non-integer powers, and performs all operations to a specified number of significant digits.

## Load

The library is the single JavaScript file *bignumber.js* (or minified, *bignumber.min.js*).

Browser:

```html
<script src='path/to/bignumber.js'></script>
```

[Node.js](http://nodejs.org):

```bash
$ npm install --save bignumber.js
```

```javascript
var BigNumber = require('bignumber.js');
```

ES6 module (*bignumber.mjs*):

```javascript
//import BigNumber from 'bignumber.js';
import {BigNumber} from 'bignumber.js';
```

AMD loader libraries such as [requireJS](http://requirejs.org/):

```javascript
require(['bignumber'], function(BigNumber) {
    // Use BigNumber here in local scope. No global BigNumber.
});
```

## Use

*In all examples below, `var`, semicolons and `toString` calls are not shown.
If a commented-out value is in quotes it means `toString` has been called on the preceding expression.*

The library exports a single function: `BigNumber`, the constructor of BigNumber instances.

It accepts a value of type Number, String or BigNumber,

```javascript
x = new BigNumber(123.4567)
y = BigNumber('123456.7e-3')
z = new BigNumber(x)
x.isEqualTo(y) && y.isEqualTo(z) && x.isEqualTo(z)      // true
```

and a base can be specified.

```javascript
a = new BigNumber(1011, 2)          // "11"
b = new BigNumber('zz.9', 36)       // "1295.25"
c = x.plus(y)                       // "1306.25"
```

Note that a BigNumber is created from a Number's decimal `toString()` value not from its underlying binary value. If the latter is required, then pass the Number's `toString(2)` value and specify base 2.

```javascript
new BigNumber(Number.MAX_VALUE.toString(2), 2)
``` 

If the limited precision of Number values is not well understood, **it is recommended to pass String values rather than Number values** to avoid a potential loss of precision.

```javascript
// Precision loss from using numeric literals with more than 15 significant digits.   
new BigNumber(1.0000000000000001);                 // '1'
new BigNumber(88259496234518.57);                  // '88259496234518.56'
new BigNumber(99999999999999999999);               // '100000000000000000000'

// Precision loss from using numeric literals outside the range of Number values.
new BigNumber(2e+308);                             // 'Infinity'
new BigNumber(1e-324);                             // '0'

// Precision loss from the unexpected result of arithmetic with Number values.
new BigNumber(0.7 + 0.1);                          // '0.7999999999999999' 
```

A BigNumber is immutable in the sense that it is not changed by its methods.

```javascript
0.3 - 0.1                           // 0.19999999999999998
x = new BigNumber(0.3)
x.minus(0.1)                        // "0.2"
x                                   // "0.3"
```

The methods that return a BigNumber can be chained.

```javascript
x.dividedBy(y).plus(z).times(9)
x.times('1.23456780123456789e+9').plus(9876.5432321).dividedBy('4444562598.111772').integerValue()
```

Some of the longer method names have a shorter alias.

```javascript
x.squareRoot().dividedBy(y).exponentiatedBy(3).isEqualTo( x.sqrt().div(y).pow(3) )    // true
x.modulo(y).multipliedBy(z).eq( x.mod(y).times(z) )                                   // true
```

As with JavaScript's Number type, there are `toExponential`, `toFixed` and `toPrecision` methods

```javascript
x = new BigNumber(255.5)
x.toExponential(5)                  // "2.55500e+2"
x.toFixed(5)                        // "255.50000"
x.toPrecision(5)                    // "255.50"
x.toNumber()                        //  255.5
```

 and a base can be specified for `toString`.

 ```javascript
 x.toString(16)                     // "ff.8"
 ```

There is also a `toFormat` method which may be useful for internationalisation

```javascript
y = new BigNumber('1234567.898765')
y.toFormat(2)                       // "1,234,567.90"
```

The maximum number of decimal places of the result of an operation involving division (i.e. a division, square root, base conversion or negative power operation) is set using the `config` method of the `BigNumber` constructor.

The other arithmetic operations always give the exact result.

```javascript
BigNumber.config({ DECIMAL_PLACES: 10, ROUNDING_MODE: 4 })

x = new BigNumber(2);
y = new BigNumber(3);
z = x.dividedBy(y)                        // "0.6666666667"
z.squareRoot()                            // "0.8164965809"
z.exponentiatedBy(-3)                     // "3.3749999995"
z.toString(2)                             // "0.1010101011"
z.multipliedBy(z)                         // "0.44444444448888888889"
z.multipliedBy(z).decimalPlaces(10)       // "0.4444444445"
```

There is a `toFraction` method with an optional *maximum denominator* argument

```javascript
y = new BigNumber(355)
pi = y.dividedBy(113)               // "3.1415929204"
pi.toFraction()                     // [ "7853982301", "2500000000" ]
pi.toFraction(1000)                 // [ "355", "113" ]
```

and `isNaN` and `isFinite` methods, as `NaN` and `Infinity` are valid `BigNumber` values.

```javascript
x = new BigNumber(NaN)                                           // "NaN"
y = new BigNumber(Infinity)                                      // "Infinity"
x.isNaN() && !y.isNaN() && !x.isFinite() && !y.isFinite()        // true
```

The value of a BigNumber is stored in a decimal floating point format in terms of a coefficient, exponent and sign.

```javascript
x = new BigNumber(-123.456);
x.c                                 // [ 123, 45600000000000 ]  coefficient (i.e. significand)
x.e                                 // 2                        exponent
x.s                                 // -1                       sign
```

For advanced usage, multiple BigNumber constructors can be created, each with their own independent configuration which applies to all BigNumber's created from it.

```javascript
// Set DECIMAL_PLACES for the original BigNumber constructor
BigNumber.config({ DECIMAL_PLACES: 10 })

// Create another BigNumber constructor, optionally passing in a configuration object
BN = BigNumber.clone({ DECIMAL_PLACES: 5 })

x = new BigNumber(1)
y = new BN(1)

x.div(3)                            // '0.3333333333'
y.div(3)                            // '0.33333'
```

For futher information see the [API](http://mikemcl.github.io/bignumber.js/) reference in the *doc* directory.

## Test

The *test/modules* directory contains the test scripts for each method.

The tests can be run with Node.js or a browser. For Node.js use

    $ npm test

or

    $ node test/test

To test a single method, use, for example

    $ node test/methods/toFraction

For the browser, open *test/test.html*.

## Performance

See the [README](https://github.com/MikeMcl/bignumber.js/tree/master/perf) in the *perf* directory.

## Build

For Node, if [uglify-js](https://github.com/mishoo/UglifyJS2) is installed

    npm install uglify-js -g

then

    npm run build

will create *bignumber.min.js*.

A source map will also be created in the root directory.

## Feedback

Open an issue, or email

Michael

<a href="mailto:M8ch88l@gmail.com">M8ch88l@gmail.com</a>

## Licence

The MIT Licence.

See [LICENCE](https://github.com/MikeMcl/bignumber.js/blob/master/LICENCE).
Original line number Diff line number Diff line
/* bignumber.js v7.2.1 https://github.com/MikeMcl/bignumber.js/LICENCE */
!function(e){"use strict";function r(e){function l(e,r){var n,t,i,s,f,u,c,h,p=this;if(!(p instanceof l))return new l(e,r);if(null==r){if(e instanceof l)return p.s=e.s,p.e=e.e,void(p.c=(e=e.c)?e.slice():e);if(u="number"==typeof e,u&&0*e==0){if(p.s=0>1/e?(e=-e,-1):1,e===~~e){for(s=0,f=e;f>=10;f/=10,s++);return p.e=s,void(p.c=[e])}h=e+""}else{if(!a.test(h=e+""))return _(p,h,u);p.s=45==h.charCodeAt(0)?(h=h.slice(1),-1):1}(s=h.indexOf("."))>-1&&(h=h.replace(".","")),(f=h.search(/e/i))>0?(0>s&&(s=f),s+=+h.slice(f+1),h=h.substring(0,f)):0>s&&(s=h.length)}else{if(o(r,2,q.length,"Base"),h=e+"",10==r)return p=new l(e instanceof l?e:h),R(p,B+p.e+1,U);if(u="number"==typeof e){if(0*e!=0)return _(p,h,u,r);if(p.s=0>1/e?(h=h.slice(1),-1):1,l.DEBUG&&h.replace(/^0\.0*|\./,"").length>15)throw Error(w+e);u=!1}else p.s=45===h.charCodeAt(0)?(h=h.slice(1),-1):1;for(n=q.slice(0,r),s=f=0,c=h.length;c>f;f++)if(n.indexOf(t=h.charAt(f))<0){if("."==t){if(f>s){s=c;continue}}else if(!i&&(h==h.toUpperCase()&&(h=h.toLowerCase())||h==h.toLowerCase()&&(h=h.toUpperCase()))){i=!0,f=-1,s=0;continue}return _(p,e+"",u,r)}h=P(h,r,10,p.s),(s=h.indexOf("."))>-1?h=h.replace(".",""):s=h.length}for(f=0;48===h.charCodeAt(f);f++);for(c=h.length;48===h.charCodeAt(--c););if(h=h.slice(f,++c)){if(c-=f,u&&l.DEBUG&&c>15&&(e>v||e!==g(e)))throw Error(w+p.s*e);if(s=s-f-1,s>C)p.c=p.e=null;else if(x>s)p.c=[p.e=0];else{if(p.e=s,p.c=[],f=(s+1)%m,0>s&&(f+=m),c>f){for(f&&p.c.push(+h.slice(0,f)),c-=m;c>f;)p.c.push(+h.slice(f,f+=m));h=h.slice(f),f=m-h.length}else f-=c;for(;f--;h+="0");p.c.push(+h)}}else p.c=[p.e=0]}function E(e,r,n,i){var s,f,a,h,g;if(null==n?n=U:o(n,0,8),!e.c)return e.toString();if(s=e.c[0],a=e.e,null==r)g=t(e.c),g=1==i||2==i&&I>=a?u(g,a):c(g,a,"0");else if(e=R(new l(e),r,n),f=e.e,g=t(e.c),h=g.length,1==i||2==i&&(f>=r||I>=f)){for(;r>h;g+="0",h++);g=u(g,f)}else if(r-=a,g=c(g,f,"0"),f+1>h){if(--r>0)for(g+=".";r--;g+="0");}else if(r+=f-h,r>0)for(f+1==h&&(g+=".");r--;g+="0");return e.s<0&&s?"-"+g:g}function b(e,r){var n,t,i=0;for(s(e[0])&&(e=e[0]),n=new l(e[0]);++i<e.length;){if(t=new l(e[i]),!t.s){n=t;break}r.call(n,t)&&(n=t)}return n}function A(e,r,n){for(var t=1,i=r.length;!r[--i];r.pop());for(i=r[0];i>=10;i/=10,t++);return(n=t+n*m-1)>C?e.c=e.e=null:x>n?e.c=[e.e=0]:(e.e=n,e.c=r),e}function R(e,r,n,t){var i,o,s,f,u,c,l,a=e.c,p=O;if(a){e:{for(i=1,f=a[0];f>=10;f/=10,i++);if(o=r-i,0>o)o+=m,s=r,u=a[c=0],l=u/p[i-s-1]%10|0;else if(c=h((o+1)/m),c>=a.length){if(!t)break e;for(;a.length<=c;a.push(0));u=l=0,i=1,o%=m,s=o-m+1}else{for(u=f=a[c],i=1;f>=10;f/=10,i++);o%=m,s=o-m+i,l=0>s?0:u/p[i-s-1]%10|0}if(t=t||0>r||null!=a[c+1]||(0>s?u:u%p[i-s-1]),t=4>n?(l||t)&&(0==n||n==(e.s<0?3:2)):l>5||5==l&&(4==n||t||6==n&&(o>0?s>0?u/p[i-s]:0:a[c-1])%10&1||n==(e.s<0?8:7)),1>r||!a[0])return a.length=0,t?(r-=e.e+1,a[0]=p[(m-r%m)%m],e.e=-r||0):a[0]=e.e=0,e;if(0==o?(a.length=c,f=1,c--):(a.length=c+1,f=p[m-o],a[c]=s>0?g(u/p[i-s]%p[s])*f:0),t)for(;;){if(0==c){for(o=1,s=a[0];s>=10;s/=10,o++);for(s=a[0]+=f,f=1;s>=10;s/=10,f++);o!=f&&(e.e++,a[0]==d&&(a[0]=1));break}if(a[c]+=f,a[c]!=d)break;a[c--]=0,f=1}for(o=a.length;0===a[--o];a.pop());}e.e>C?e.c=e.e=null:e.e<x&&(e.c=[e.e=0])}return e}var S,P,_,D=l.prototype={constructor:l,toString:null,valueOf:null},L=new l(1),B=20,U=4,I=-7,T=21,x=-1e7,C=1e7,M=!1,G=1,F=0,k={decimalSeparator:".",groupSeparator:",",groupSize:3,secondaryGroupSize:0,fractionGroupSeparator:" ",fractionGroupSize:0},q="0123456789abcdefghijklmnopqrstuvwxyz";return l.clone=r,l.ROUND_UP=0,l.ROUND_DOWN=1,l.ROUND_CEIL=2,l.ROUND_FLOOR=3,l.ROUND_HALF_UP=4,l.ROUND_HALF_DOWN=5,l.ROUND_HALF_EVEN=6,l.ROUND_HALF_CEIL=7,l.ROUND_HALF_FLOOR=8,l.EUCLID=9,l.config=l.set=function(e){var r,n;if(null!=e){if("object"!=typeof e)throw Error(p+"Object expected: "+e);if(e.hasOwnProperty(r="DECIMAL_PLACES")&&(n=e[r],o(n,0,y,r),B=n),e.hasOwnProperty(r="ROUNDING_MODE")&&(n=e[r],o(n,0,8,r),U=n),e.hasOwnProperty(r="EXPONENTIAL_AT")&&(n=e[r],s(n)?(o(n[0],-y,0,r),o(n[1],0,y,r),I=n[0],T=n[1]):(o(n,-y,y,r),I=-(T=0>n?-n:n))),e.hasOwnProperty(r="RANGE"))if(n=e[r],s(n))o(n[0],-y,-1,r),o(n[1],1,y,r),x=n[0],C=n[1];else{if(o(n,-y,y,r),!n)throw Error(p+r+" cannot be zero: "+n);x=-(C=0>n?-n:n)}if(e.hasOwnProperty(r="CRYPTO")){if(n=e[r],n!==!!n)throw Error(p+r+" not true or false: "+n);if(n){if("undefined"==typeof crypto||!crypto||!crypto.getRandomValues&&!crypto.randomBytes)throw M=!n,Error(p+"crypto unavailable");M=n}else M=n}if(e.hasOwnProperty(r="MODULO_MODE")&&(n=e[r],o(n,0,9,r),G=n),e.hasOwnProperty(r="POW_PRECISION")&&(n=e[r],o(n,0,y,r),F=n),e.hasOwnProperty(r="FORMAT")){if(n=e[r],"object"!=typeof n)throw Error(p+r+" not an object: "+n);k=n}if(e.hasOwnProperty(r="ALPHABET")){if(n=e[r],"string"!=typeof n||/^.$|\.|(.).*\1/.test(n))throw Error(p+r+" invalid: "+n);q=n}}return{DECIMAL_PLACES:B,ROUNDING_MODE:U,EXPONENTIAL_AT:[I,T],RANGE:[x,C],CRYPTO:M,MODULO_MODE:G,POW_PRECISION:F,FORMAT:k,ALPHABET:q}},l.isBigNumber=function(e){return e instanceof l||e&&e._isBigNumber===!0||!1},l.maximum=l.max=function(){return b(arguments,D.lt)},l.minimum=l.min=function(){return b(arguments,D.gt)},l.random=function(){var e=9007199254740992,r=Math.random()*e&2097151?function(){return g(Math.random()*e)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(e){var n,t,i,s,f,u=0,c=[],a=new l(L);if(null==e?e=B:o(e,0,y),s=h(e/m),M)if(crypto.getRandomValues){for(n=crypto.getRandomValues(new Uint32Array(s*=2));s>u;)f=131072*n[u]+(n[u+1]>>>11),f>=9e15?(t=crypto.getRandomValues(new Uint32Array(2)),n[u]=t[0],n[u+1]=t[1]):(c.push(f%1e14),u+=2);u=s/2}else{if(!crypto.randomBytes)throw M=!1,Error(p+"crypto unavailable");for(n=crypto.randomBytes(s*=7);s>u;)f=281474976710656*(31&n[u])+1099511627776*n[u+1]+4294967296*n[u+2]+16777216*n[u+3]+(n[u+4]<<16)+(n[u+5]<<8)+n[u+6],f>=9e15?crypto.randomBytes(7).copy(n,u):(c.push(f%1e14),u+=7);u=s/7}if(!M)for(;s>u;)f=r(),9e15>f&&(c[u++]=f%1e14);for(s=c[--u],e%=m,s&&e&&(f=O[m-e],c[u]=g(s/f)*f);0===c[u];c.pop(),u--);if(0>u)c=[i=0];else{for(i=-1;0===c[0];c.splice(0,1),i-=m);for(u=1,f=c[0];f>=10;f/=10,u++);m>u&&(i-=m-u)}return a.e=i,a.c=c,a}}(),P=function(){function e(e,r,n,t){for(var i,o,s=[0],f=0,u=e.length;u>f;){for(o=s.length;o--;s[o]*=r);for(s[0]+=t.indexOf(e.charAt(f++)),i=0;i<s.length;i++)s[i]>n-1&&(null==s[i+1]&&(s[i+1]=0),s[i+1]+=s[i]/n|0,s[i]%=n)}return s.reverse()}var r="0123456789";return function(n,i,o,s,f){var u,a,h,g,p,w,d,m,v=n.indexOf("."),O=B,N=U;for(v>=0&&(g=F,F=0,n=n.replace(".",""),m=new l(i),w=m.pow(n.length-v),F=g,m.c=e(c(t(w.c),w.e,"0"),10,o,r),m.e=m.c.length),d=e(n,i,o,f?(u=q,r):(u=r,q)),h=g=d.length;0==d[--g];d.pop());if(!d[0])return u.charAt(0);if(0>v?--h:(w.c=d,w.e=h,w.s=s,w=S(w,m,O,N,o),d=w.c,p=w.r,h=w.e),a=h+O+1,v=d[a],g=o/2,p=p||0>a||null!=d[a+1],p=4>N?(null!=v||p)&&(0==N||N==(w.s<0?3:2)):v>g||v==g&&(4==N||p||6==N&&1&d[a-1]||N==(w.s<0?8:7)),1>a||!d[0])n=p?c(u.charAt(1),-O,u.charAt(0)):u.charAt(0);else{if(d.length=a,p)for(--o;++d[--a]>o;)d[a]=0,a||(++h,d=[1].concat(d));for(g=d.length;!d[--g];);for(v=0,n="";g>=v;n+=u.charAt(d[v++]));n=c(n,h,u.charAt(0))}return n}}(),S=function(){function e(e,r,n){var t,i,o,s,f=0,u=e.length,c=r%N,l=r/N|0;for(e=e.slice();u--;)o=e[u]%N,s=e[u]/N|0,t=l*o+s*c,i=c*o+t%N*N+f,f=(i/n|0)+(t/N|0)+l*s,e[u]=i%n;return f&&(e=[f].concat(e)),e}function r(e,r,n,t){var i,o;if(n!=t)o=n>t?1:-1;else for(i=o=0;n>i;i++)if(e[i]!=r[i]){o=e[i]>r[i]?1:-1;break}return o}function t(e,r,n,t){for(var i=0;n--;)e[n]-=i,i=e[n]<r[n]?1:0,e[n]=i*t+e[n]-r[n];for(;!e[0]&&e.length>1;e.splice(0,1));}return function(i,o,s,f,u){var c,a,h,p,w,v,O,N,y,E,b,A,S,P,_,D,L,B=i.s==o.s?1:-1,U=i.c,I=o.c;if(!(U&&U[0]&&I&&I[0]))return new l(i.s&&o.s&&(U?!I||U[0]!=I[0]:I)?U&&0==U[0]||!I?0*B:B/0:NaN);for(N=new l(B),y=N.c=[],a=i.e-o.e,B=s+a+1,u||(u=d,a=n(i.e/m)-n(o.e/m),B=B/m|0),h=0;I[h]==(U[h]||0);h++);if(I[h]>(U[h]||0)&&a--,0>B)y.push(1),p=!0;else{for(P=U.length,D=I.length,h=0,B+=2,w=g(u/(I[0]+1)),w>1&&(I=e(I,w,u),U=e(U,w,u),D=I.length,P=U.length),S=D,E=U.slice(0,D),b=E.length;D>b;E[b++]=0);L=I.slice(),L=[0].concat(L),_=I[0],I[1]>=u/2&&_++;do{if(w=0,c=r(I,E,D,b),0>c){if(A=E[0],D!=b&&(A=A*u+(E[1]||0)),w=g(A/_),w>1)for(w>=u&&(w=u-1),v=e(I,w,u),O=v.length,b=E.length;1==r(v,E,O,b);)w--,t(v,O>D?L:I,O,u),O=v.length,c=1;else 0==w&&(c=w=1),v=I.slice(),O=v.length;if(b>O&&(v=[0].concat(v)),t(E,v,b,u),b=E.length,-1==c)for(;r(I,E,D,b)<1;)w++,t(E,b>D?L:I,b,u),b=E.length}else 0===c&&(w++,E=[0]);y[h++]=w,E[0]?E[b++]=U[S]||0:(E=[U[S]],b=1)}while((S++<P||null!=E[0])&&B--);p=null!=E[0],y[0]||y.splice(0,1)}if(u==d){for(h=1,B=y[0];B>=10;B/=10,h++);R(N,s+(N.e=h+a*m-1)+1,f,p)}else N.e=a,N.r=+p;return N}}(),_=function(){var e=/^(-?)0([xbo])(?=\w[\w.]*$)/i,r=/^([^.]+)\.$/,n=/^\.([^.]+)$/,t=/^-?(Infinity|NaN)$/,i=/^\s*\+(?=[\w.])|^\s+|\s+$/g;return function(o,s,f,u){var c,a=f?s:s.replace(i,"");if(t.test(a))o.s=isNaN(a)?null:0>a?-1:1,o.c=o.e=null;else{if(!f&&(a=a.replace(e,function(e,r,n){return c="x"==(n=n.toLowerCase())?16:"b"==n?2:8,u&&u!=c?e:r}),u&&(c=u,a=a.replace(r,"$1").replace(n,"0.$1")),s!=a))return new l(a,c);if(l.DEBUG)throw Error(p+"Not a"+(u?" base "+u:"")+" number: "+s);o.c=o.e=o.s=null}}}(),D.absoluteValue=D.abs=function(){var e=new l(this);return e.s<0&&(e.s=1),e},D.comparedTo=function(e,r){return i(this,new l(e,r))},D.decimalPlaces=D.dp=function(e,r){var t,i,s,f=this;if(null!=e)return o(e,0,y),null==r?r=U:o(r,0,8),R(new l(f),e+f.e+1,r);if(!(t=f.c))return null;if(i=((s=t.length-1)-n(this.e/m))*m,s=t[s])for(;s%10==0;s/=10,i--);return 0>i&&(i=0),i},D.dividedBy=D.div=function(e,r){return S(this,new l(e,r),B,U)},D.dividedToIntegerBy=D.idiv=function(e,r){return S(this,new l(e,r),0,1)},D.exponentiatedBy=D.pow=function(e,r){var n,t,i,o,s,u,c,a,w=this;if(e=new l(e),e.c&&!e.isInteger())throw Error(p+"Exponent not an integer: "+e);if(null!=r&&(r=new l(r)),s=e.e>14,!w.c||!w.c[0]||1==w.c[0]&&!w.e&&1==w.c.length||!e.c||!e.c[0])return a=new l(Math.pow(+w.valueOf(),s?2-f(e):+e)),r?a.mod(r):a;if(u=e.s<0,r){if(r.c?!r.c[0]:!r.s)return new l(NaN);t=!u&&w.isInteger()&&r.isInteger(),t&&(w=w.mod(r))}else{if(e.e>9&&(w.e>0||w.e<-1||(0==w.e?w.c[0]>1||s&&w.c[1]>=24e7:w.c[0]<8e13||s&&w.c[0]<=9999975e7)))return i=w.s<0&&f(e)?-0:0,w.e>-1&&(i=1/i),new l(u?1/i:i);F&&(i=h(F/m+2))}for(s?(n=new l(.5),c=f(e)):c=e%2,u&&(e.s=1),a=new l(L);;){if(c){if(a=a.times(w),!a.c)break;i?a.c.length>i&&(a.c.length=i):t&&(a=a.mod(r))}if(s){if(e=e.times(n),R(e,e.e+1,1),!e.c[0])break;s=e.e>14,c=f(e)}else{if(e=g(e/2),!e)break;c=e%2}w=w.times(w),i?w.c&&w.c.length>i&&(w.c.length=i):t&&(w=w.mod(r))}return t?a:(u&&(a=L.div(a)),r?a.mod(r):i?R(a,F,U,o):a)},D.integerValue=function(e){var r=new l(this);return null==e?e=U:o(e,0,8),R(r,r.e+1,e)},D.isEqualTo=D.eq=function(e,r){return 0===i(this,new l(e,r))},D.isFinite=function(){return!!this.c},D.isGreaterThan=D.gt=function(e,r){return i(this,new l(e,r))>0},D.isGreaterThanOrEqualTo=D.gte=function(e,r){return 1===(r=i(this,new l(e,r)))||0===r},D.isInteger=function(){return!!this.c&&n(this.e/m)>this.c.length-2},D.isLessThan=D.lt=function(e,r){return i(this,new l(e,r))<0},D.isLessThanOrEqualTo=D.lte=function(e,r){return-1===(r=i(this,new l(e,r)))||0===r},D.isNaN=function(){return!this.s},D.isNegative=function(){return this.s<0},D.isPositive=function(){return this.s>0},D.isZero=function(){return!!this.c&&0==this.c[0]},D.minus=function(e,r){var t,i,o,s,f=this,u=f.s;if(e=new l(e,r),r=e.s,!u||!r)return new l(NaN);if(u!=r)return e.s=-r,f.plus(e);var c=f.e/m,a=e.e/m,h=f.c,g=e.c;if(!c||!a){if(!h||!g)return h?(e.s=-r,e):new l(g?f:NaN);if(!h[0]||!g[0])return g[0]?(e.s=-r,e):new l(h[0]?f:3==U?-0:0)}if(c=n(c),a=n(a),h=h.slice(),u=c-a){for((s=0>u)?(u=-u,o=h):(a=c,o=g),o.reverse(),r=u;r--;o.push(0));o.reverse()}else for(i=(s=(u=h.length)<(r=g.length))?u:r,u=r=0;i>r;r++)if(h[r]!=g[r]){s=h[r]<g[r];break}if(s&&(o=h,h=g,g=o,e.s=-e.s),r=(i=g.length)-(t=h.length),r>0)for(;r--;h[t++]=0);for(r=d-1;i>u;){if(h[--i]<g[i]){for(t=i;t&&!h[--t];h[t]=r);--h[t],h[i]+=d}h[i]-=g[i]}for(;0==h[0];h.splice(0,1),--a);return h[0]?A(e,h,a):(e.s=3==U?-1:1,e.c=[e.e=0],e)},D.modulo=D.mod=function(e,r){var n,t,i=this;return e=new l(e,r),!i.c||!e.s||e.c&&!e.c[0]?new l(NaN):!e.c||i.c&&!i.c[0]?new l(i):(9==G?(t=e.s,e.s=1,n=S(i,e,0,3),e.s=t,n.s*=t):n=S(i,e,0,G),e=i.minus(n.times(e)),e.c[0]||1!=G||(e.s=i.s),e)},D.multipliedBy=D.times=function(e,r){var t,i,o,s,f,u,c,a,h,g,p,w,v,O,y,E=this,b=E.c,R=(e=new l(e,r)).c;if(!(b&&R&&b[0]&&R[0]))return!E.s||!e.s||b&&!b[0]&&!R||R&&!R[0]&&!b?e.c=e.e=e.s=null:(e.s*=E.s,b&&R?(e.c=[0],e.e=0):e.c=e.e=null),e;for(i=n(E.e/m)+n(e.e/m),e.s*=E.s,c=b.length,g=R.length,g>c&&(v=b,b=R,R=v,o=c,c=g,g=o),o=c+g,v=[];o--;v.push(0));for(O=d,y=N,o=g;--o>=0;){for(t=0,p=R[o]%y,w=R[o]/y|0,f=c,s=o+f;s>o;)a=b[--f]%y,h=b[f]/y|0,u=w*a+h*p,a=p*a+u%y*y+v[s]+t,t=(a/O|0)+(u/y|0)+w*h,v[s--]=a%O;v[s]=t}return t?++i:v.splice(0,1),A(e,v,i)},D.negated=function(){var e=new l(this);return e.s=-e.s||null,e},D.plus=function(e,r){var t,i=this,o=i.s;if(e=new l(e,r),r=e.s,!o||!r)return new l(NaN);if(o!=r)return e.s=-r,i.minus(e);var s=i.e/m,f=e.e/m,u=i.c,c=e.c;if(!s||!f){if(!u||!c)return new l(o/0);if(!u[0]||!c[0])return c[0]?e:new l(u[0]?i:0*o)}if(s=n(s),f=n(f),u=u.slice(),o=s-f){for(o>0?(f=s,t=c):(o=-o,t=u),t.reverse();o--;t.push(0));t.reverse()}for(o=u.length,r=c.length,0>o-r&&(t=c,c=u,u=t,r=o),o=0;r;)o=(u[--r]=u[r]+c[r]+o)/d|0,u[r]=d===u[r]?0:u[r]%d;return o&&(u=[o].concat(u),++f),A(e,u,f)},D.precision=D.sd=function(e,r){var n,t,i,s=this;if(null!=e&&e!==!!e)return o(e,1,y),null==r?r=U:o(r,0,8),R(new l(s),e,r);if(!(n=s.c))return null;if(i=n.length-1,t=i*m+1,i=n[i]){for(;i%10==0;i/=10,t--);for(i=n[0];i>=10;i/=10,t++);}return e&&s.e+1>t&&(t=s.e+1),t},D.shiftedBy=function(e){return o(e,-v,v),this.times("1e"+e)},D.squareRoot=D.sqrt=function(){var e,r,i,o,s,f=this,u=f.c,c=f.s,a=f.e,h=B+4,g=new l("0.5");if(1!==c||!u||!u[0])return new l(!c||0>c&&(!u||u[0])?NaN:u?f:1/0);if(c=Math.sqrt(+f),0==c||c==1/0?(r=t(u),(r.length+a)%2==0&&(r+="0"),c=Math.sqrt(r),a=n((a+1)/2)-(0>a||a%2),c==1/0?r="1e"+a:(r=c.toExponential(),r=r.slice(0,r.indexOf("e")+1)+a),i=new l(r)):i=new l(c+""),i.c[0])for(a=i.e,c=a+h,3>c&&(c=0);;)if(s=i,i=g.times(s.plus(S(f,s,h,1))),t(s.c).slice(0,c)===(r=t(i.c)).slice(0,c)){if(i.e<a&&--c,r=r.slice(c-3,c+1),"9999"!=r&&(o||"4999"!=r)){(!+r||!+r.slice(1)&&"5"==r.charAt(0))&&(R(i,i.e+B+2,1),e=!i.times(i).eq(f));break}if(!o&&(R(s,s.e+B+2,0),s.times(s).eq(f))){i=s;break}h+=4,c+=4,o=1}return R(i,i.e+B+1,U,e)},D.toExponential=function(e,r){return null!=e&&(o(e,0,y),e++),E(this,e,r,1)},D.toFixed=function(e,r){return null!=e&&(o(e,0,y),e=e+this.e+1),E(this,e,r)},D.toFormat=function(e,r){var n=this.toFixed(e,r);if(this.c){var t,i=n.split("."),o=+k.groupSize,s=+k.secondaryGroupSize,f=k.groupSeparator,u=i[0],c=i[1],l=this.s<0,a=l?u.slice(1):u,h=a.length;if(s&&(t=o,o=s,s=t,h-=t),o>0&&h>0){for(t=h%o||o,u=a.substr(0,t);h>t;t+=o)u+=f+a.substr(t,o);s>0&&(u+=f+a.slice(t)),l&&(u="-"+u)}n=c?u+k.decimalSeparator+((s=+k.fractionGroupSize)?c.replace(new RegExp("\\d{"+s+"}\\B","g"),"$&"+k.fractionGroupSeparator):c):u}return n},D.toFraction=function(e){var r,n,i,o,s,f,u,c,a,h,g,w,d=this,v=d.c;if(null!=e&&(c=new l(e),!c.isInteger()&&(c.c||1!==c.s)||c.lt(L)))throw Error(p+"Argument "+(c.isInteger()?"out of range: ":"not an integer: ")+e);if(!v)return d.toString();for(n=new l(L),h=i=new l(L),o=a=new l(L),w=t(v),f=n.e=w.length-d.e-1,n.c[0]=O[(u=f%m)<0?m+u:u],e=!e||c.comparedTo(n)>0?f>0?n:h:c,u=C,C=1/0,c=new l(w),a.c[0]=0;g=S(c,n,0,1),s=i.plus(g.times(o)),1!=s.comparedTo(e);)i=o,o=s,h=a.plus(g.times(s=h)),a=s,n=c.minus(g.times(s=n)),c=s;return s=S(e.minus(i),o,0,1),a=a.plus(s.times(h)),i=i.plus(s.times(o)),a.s=h.s=d.s,f*=2,r=S(h,o,f,U).minus(d).abs().comparedTo(S(a,i,f,U).minus(d).abs())<1?[h.toString(),o.toString()]:[a.toString(),i.toString()],C=u,r},D.toNumber=function(){return+this},D.toPrecision=function(e,r){return null!=e&&o(e,1,y),E(this,e,r,2)},D.toString=function(e){var r,n=this,i=n.s,s=n.e;return null===s?i?(r="Infinity",0>i&&(r="-"+r)):r="NaN":(r=t(n.c),null==e?r=I>=s||s>=T?u(r,s):c(r,s,"0"):(o(e,2,q.length,"Base"),r=P(c(r,s,"0"),10,e,i,!0)),0>i&&n.c[0]&&(r="-"+r)),r},D.valueOf=D.toJSON=function(){var e,r=this,n=r.e;return null===n?r.toString():(e=t(r.c),e=I>=n||n>=T?u(e,n):c(e,n,"0"),r.s<0?"-"+e:e)},D._isBigNumber=!0,null!=e&&l.set(e),l}function n(e){var r=0|e;return e>0||e===r?r:r-1}function t(e){for(var r,n,t=1,i=e.length,o=e[0]+"";i>t;){for(r=e[t++]+"",n=m-r.length;n--;r="0"+r);o+=r}for(i=o.length;48===o.charCodeAt(--i););return o.slice(0,i+1||1)}function i(e,r){var n,t,i=e.c,o=r.c,s=e.s,f=r.s,u=e.e,c=r.e;if(!s||!f)return null;if(n=i&&!i[0],t=o&&!o[0],n||t)return n?t?0:-f:s;if(s!=f)return s;if(n=0>s,t=u==c,!i||!o)return t?0:!i^n?1:-1;if(!t)return u>c^n?1:-1;for(f=(u=i.length)<(c=o.length)?u:c,s=0;f>s;s++)if(i[s]!=o[s])return i[s]>o[s]^n?1:-1;return u==c?0:u>c^n?1:-1}function o(e,r,n,t){if(r>e||e>n||e!==(0>e?h(e):g(e)))throw Error(p+(t||"Argument")+("number"==typeof e?r>e||e>n?" out of range: ":" not an integer: ":" not a primitive number: ")+e)}function s(e){return"[object Array]"==Object.prototype.toString.call(e)}function f(e){var r=e.c.length-1;return n(e.e/m)==r&&e.c[r]%2!=0}function u(e,r){return(e.length>1?e.charAt(0)+"."+e.slice(1):e)+(0>r?"e":"e+")+r}function c(e,r,n){var t,i;if(0>r){for(i=n+".";++r;i+=n);e=i+e}else if(t=e.length,++r>t){for(i=n,r-=t;--r;i+=n);e+=i}else t>r&&(e=e.slice(0,r)+"."+e.slice(r));return e}var l,a=/^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i,h=Math.ceil,g=Math.floor,p="[BigNumber Error] ",w=p+"Number primitive has more than 15 significant digits: ",d=1e14,m=14,v=9007199254740991,O=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],N=1e7,y=1e9;l=r(),l["default"]=l.BigNumber=l,"function"==typeof define&&define.amd?define(function(){return l}):"undefined"!=typeof module&&module.exports?module.exports=l:(e||(e="undefined"!=typeof self&&self?self:window),e.BigNumber=l)}(this);
//# sourceMappingURL=bignumber.js.map
 No newline at end of file
Original line number Diff line number Diff line
{
  "name": "bignumber.js",
  "main": "bignumber.js",
  "version": "7.2.1",
  "homepage": "https://github.com/MikeMcl/bignumber.js",
  "authors": [
    "Michael Mclaughlin <M8ch88l@gmail.com>"
  ],
  "description": "A library for arbitrary-precision decimal and non-decimal arithmetic",
  "moduleType": [
    "amd",
    "globals",
    "node"
  ],
   "keywords": [
    "arbitrary",
    "precision",
    "arithmetic",
    "big",
    "number",
    "decimal",
    "float",
    "biginteger",
    "bigdecimal",
    "bignumber",
    "bigint",
    "bignum"
  ],
  "license": "MIT",
  "ignore": [
    ".*",
    "*.json",
    "test"
  ]
}
Original line number Diff line number Diff line
{
  "_args": [
    [
      "bignumber.js@7.2.1",
      "/Users/klaus/Documents/Web/Back/2019_tp2/projet"
    ]
  ],
  "_from": "bignumber.js@7.2.1",
  "_id": "bignumber.js@7.2.1",
  "_inBundle": false,
  "_integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==",
  "_location": "/bignumber.js",
  "_phantomChildren": {},
  "_requested": {
    "type": "version",
    "registry": true,
    "raw": "bignumber.js@7.2.1",
    "name": "bignumber.js",
    "escapedName": "bignumber.js",
    "rawSpec": "7.2.1",
    "saveSpec": null,
    "fetchSpec": "7.2.1"
  },
  "_requiredBy": [
    "/mysql"
  ],
  "_resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz",
  "_spec": "7.2.1",
  "_where": "/Users/klaus/Documents/Web/Back/2019_tp2/projet",
  "author": {
    "name": "Michael Mclaughlin",
    "email": "M8ch88l@gmail.com"
  },
  "browser": "bignumber.js",
  "bugs": {
    "url": "https://github.com/MikeMcl/bignumber.js/issues"
  },
  "description": "A library for arbitrary-precision decimal and non-decimal arithmetic",
  "engines": {
    "node": "*"
  },
  "homepage": "https://github.com/MikeMcl/bignumber.js#readme",
  "keywords": [
    "arbitrary",
    "precision",
    "arithmetic",
    "big",
    "number",
    "decimal",
    "float",
    "biginteger",
    "bigdecimal",
    "bignumber",
    "bigint",
    "bignum"
  ],
  "license": "MIT",
  "main": "bignumber",
  "module": "bignumber.mjs",
  "name": "bignumber.js",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/MikeMcl/bignumber.js.git"
  },
  "scripts": {
    "build": "uglifyjs bignumber.js --source-map bignumber.js.map -c -m -o bignumber.min.js --preamble \"/* bignumber.js v7.2.1 https://github.com/MikeMcl/bignumber.js/LICENCE */\"",
    "test": "node test/test"
  },
  "types": "bignumber.d.ts",
  "version": "7.2.1"
}
+23 −0
Original line number Diff line number Diff line
(The MIT License)

Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Original line number Diff line number Diff line
# body-parser

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]

Node.js body parsing middleware.

Parse incoming request bodies in a middleware before your handlers, available
under the `req.body` property.

**Note** As `req.body`'s shape is based on user-controlled input, all
properties and values in this object are untrusted and should be validated
before trusting. For example, `req.body.foo.toString()` may fail in multiple
ways, for example the `foo` property may not be there or may not be a string,
and `toString` may not be a function and instead a string or other user input.

[Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/).

_This does not handle multipart bodies_, due to their complex and typically
large nature. For multipart bodies, you may be interested in the following
modules:

  * [busboy](https://www.npmjs.org/package/busboy#readme) and
    [connect-busboy](https://www.npmjs.org/package/connect-busboy#readme)
  * [multiparty](https://www.npmjs.org/package/multiparty#readme) and
    [connect-multiparty](https://www.npmjs.org/package/connect-multiparty#readme)
  * [formidable](https://www.npmjs.org/package/formidable#readme)
  * [multer](https://www.npmjs.org/package/multer#readme)

This module provides the following parsers:

  * [JSON body parser](#bodyparserjsonoptions)
  * [Raw body parser](#bodyparserrawoptions)
  * [Text body parser](#bodyparsertextoptions)
  * [URL-encoded form body parser](#bodyparserurlencodedoptions)

Other body parsers you might be interested in:

- [body](https://www.npmjs.org/package/body#readme)
- [co-body](https://www.npmjs.org/package/co-body#readme)

## Installation

```sh
$ npm install body-parser
```

## API

<!-- eslint-disable no-unused-vars -->

```js
var bodyParser = require('body-parser')
```

The `bodyParser` object exposes various factories to create middlewares. All
middlewares will populate the `req.body` property with the parsed body when
the `Content-Type` request header matches the `type` option, or an empty
object (`{}`) if there was no body to parse, the `Content-Type` was not matched,
or an error occurred.

The various errors returned by this module are described in the
[errors section](#errors).

### bodyParser.json([options])

Returns middleware that only parses `json` and only looks at requests where
the `Content-Type` header matches the `type` option. This parser accepts any
Unicode encoding of the body and supports automatic inflation of `gzip` and
`deflate` encodings.

A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`).

#### Options

The `json` function takes an optional `options` object that may contain any of
the following keys:

##### inflate

When set to `true`, then deflated (compressed) bodies will be inflated; when
`false`, deflated bodies are rejected. Defaults to `true`.

##### limit

Controls the maximum request body size. If this is a number, then the value
specifies the number of bytes; if it is a string, the value is passed to the
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults
to `'100kb'`.

##### reviver

The `reviver` option is passed directly to `JSON.parse` as the second
argument. You can find more information on this argument
[in the MDN documentation about JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter).

##### strict

When set to `true`, will only accept arrays and objects; when `false` will
accept anything `JSON.parse` accepts. Defaults to `true`.

##### type

The `type` option is used to determine what media type the middleware will
parse. This option can be a string, array of strings, or a function. If not a
function, `type` option is passed directly to the
[type-is](https://www.npmjs.org/package/type-is#readme) library and this can
be an extension name (like `json`), a mime type (like `application/json`), or
a mime type with a wildcard (like `*/*` or `*/json`). If a function, the `type`
option is called as `fn(req)` and the request is parsed if it returns a truthy
value. Defaults to `application/json`.

##### verify

The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`,
where `buf` is a `Buffer` of the raw request body and `encoding` is the
encoding of the request. The parsing can be aborted by throwing an error.

### bodyParser.raw([options])

Returns middleware that parses all bodies as a `Buffer` and only looks at
requests where the `Content-Type` header matches the `type` option. This
parser supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This will be a `Buffer` object
of the body.

#### Options

The `raw` function takes an optional `options` object that may contain any of
the following keys:

##### inflate

When set to `true`, then deflated (compressed) bodies will be inflated; when
`false`, deflated bodies are rejected. Defaults to `true`.

##### limit

Controls the maximum request body size. If this is a number, then the value
specifies the number of bytes; if it is a string, the value is passed to the
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults
to `'100kb'`.

##### type

The `type` option is used to determine what media type the middleware will
parse. This option can be a string, array of strings, or a function.
If not a function, `type` option is passed directly to the
[type-is](https://www.npmjs.org/package/type-is#readme) library and this
can be an extension name (like `bin`), a mime type (like
`application/octet-stream`), or a mime type with a wildcard (like `*/*` or
`application/*`). If a function, the `type` option is called as `fn(req)`
and the request is parsed if it returns a truthy value. Defaults to
`application/octet-stream`.

##### verify

The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`,
where `buf` is a `Buffer` of the raw request body and `encoding` is the
encoding of the request. The parsing can be aborted by throwing an error.

### bodyParser.text([options])

Returns middleware that parses all bodies as a string and only looks at
requests where the `Content-Type` header matches the `type` option. This
parser supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` string containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This will be a string of the
body.

#### Options

The `text` function takes an optional `options` object that may contain any of
the following keys:

##### defaultCharset

Specify the default character set for the text content if the charset is not
specified in the `Content-Type` header of the request. Defaults to `utf-8`.

##### inflate

When set to `true`, then deflated (compressed) bodies will be inflated; when
`false`, deflated bodies are rejected. Defaults to `true`.

##### limit

Controls the maximum request body size. If this is a number, then the value
specifies the number of bytes; if it is a string, the value is passed to the
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults
to `'100kb'`.

##### type

The `type` option is used to determine what media type the middleware will
parse. This option can be a string, array of strings, or a function. If not
a function, `type` option is passed directly to the
[type-is](https://www.npmjs.org/package/type-is#readme) library and this can
be an extension name (like `txt`), a mime type (like `text/plain`), or a mime
type with a wildcard (like `*/*` or `text/*`). If a function, the `type`
option is called as `fn(req)` and the request is parsed if it returns a
truthy value. Defaults to `text/plain`.

##### verify

The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`,
where `buf` is a `Buffer` of the raw request body and `encoding` is the
encoding of the request. The parsing can be aborted by throwing an error.

### bodyParser.urlencoded([options])

Returns middleware that only parses `urlencoded` bodies and only looks at
requests where the `Content-Type` header matches the `type` option. This
parser accepts only UTF-8 encoding of the body and supports automatic
inflation of `gzip` and `deflate` encodings.

A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This object will contain
key-value pairs, where the value can be a string or array (when `extended` is
`false`), or any type (when `extended` is `true`).

#### Options

The `urlencoded` function takes an optional `options` object that may contain
any of the following keys:

##### extended

The `extended` option allows to choose between parsing the URL-encoded data
with the `querystring` library (when `false`) or the `qs` library (when
`true`). The "extended" syntax allows for rich objects and arrays to be
encoded into the URL-encoded format, allowing for a JSON-like experience
with URL-encoded. For more information, please
[see the qs library](https://www.npmjs.org/package/qs#readme).

Defaults to `true`, but using the default has been deprecated. Please
research into the difference between `qs` and `querystring` and choose the
appropriate setting.

##### inflate

When set to `true`, then deflated (compressed) bodies will be inflated; when
`false`, deflated bodies are rejected. Defaults to `true`.

##### limit

Controls the maximum request body size. If this is a number, then the value
specifies the number of bytes; if it is a string, the value is passed to the
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults
to `'100kb'`.

##### parameterLimit

The `parameterLimit` option controls the maximum number of parameters that
are allowed in the URL-encoded data. If a request contains more parameters
than this value, a 413 will be returned to the client. Defaults to `1000`.

##### type

The `type` option is used to determine what media type the middleware will
parse. This option can be a string, array of strings, or a function. If not
a function, `type` option is passed directly to the
[type-is](https://www.npmjs.org/package/type-is#readme) library and this can
be an extension name (like `urlencoded`), a mime type (like
`application/x-www-form-urlencoded`), or a mime type with a wildcard (like
`*/x-www-form-urlencoded`). If a function, the `type` option is called as
`fn(req)` and the request is parsed if it returns a truthy value. Defaults
to `application/x-www-form-urlencoded`.

##### verify

The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`,
where `buf` is a `Buffer` of the raw request body and `encoding` is the
encoding of the request. The parsing can be aborted by throwing an error.

## Errors

The middlewares provided by this module create errors depending on the error
condition during parsing. The errors will typically have a `status`/`statusCode`
property that contains the suggested HTTP response code, an `expose` property
to determine if the `message` property should be displayed to the client, a
`type` property to determine the type of error without matching against the
`message`, and a `body` property containing the read body, if available.

The following are the common errors emitted, though any error can come through
for various reasons.

### content encoding unsupported

This error will occur when the request had a `Content-Encoding` header that
contained an encoding but the "inflation" option was set to `false`. The
`status` property is set to `415`, the `type` property is set to
`'encoding.unsupported'`, and the `charset` property will be set to the
encoding that is unsupported.

### request aborted

This error will occur when the request is aborted by the client before reading
the body has finished. The `received` property will be set to the number of
bytes received before the request was aborted and the `expected` property is
set to the number of expected bytes. The `status` property is set to `400`
and `type` property is set to `'request.aborted'`.

### request entity too large

This error will occur when the request body's size is larger than the "limit"
option. The `limit` property will be set to the byte limit and the `length`
property will be set to the request body's length. The `status` property is
set to `413` and the `type` property is set to `'entity.too.large'`.

### request size did not match content length

This error will occur when the request's length did not match the length from
the `Content-Length` header. This typically occurs when the request is malformed,
typically when the `Content-Length` header was calculated based on characters
instead of bytes. The `status` property is set to `400` and the `type` property
is set to `'request.size.invalid'`.

### stream encoding should not be set

This error will occur when something called the `req.setEncoding` method prior
to this middleware. This module operates directly on bytes only and you cannot
call `req.setEncoding` when using this module. The `status` property is set to
`500` and the `type` property is set to `'stream.encoding.set'`.

### too many parameters

This error will occur when the content of the request exceeds the configured
`parameterLimit` for the `urlencoded` parser. The `status` property is set to
`413` and the `type` property is set to `'parameters.too.many'`.

### unsupported charset "BOGUS"

This error will occur when the request had a charset parameter in the
`Content-Type` header, but the `iconv-lite` module does not support it OR the
parser does not support it. The charset is contained in the message as well
as in the `charset` property. The `status` property is set to `415`, the
`type` property is set to `'charset.unsupported'`, and the `charset` property
is set to the charset that is unsupported.

### unsupported content encoding "bogus"

This error will occur when the request had a `Content-Encoding` header that
contained an unsupported encoding. The encoding is contained in the message
as well as in the `encoding` property. The `status` property is set to `415`,
the `type` property is set to `'encoding.unsupported'`, and the `encoding`
property is set to the encoding that is unsupported.

## Examples

### Express/Connect top-level generic

This example demonstrates adding a generic JSON and URL-encoded parser as a
top-level middleware, which will parse the bodies of all incoming requests.
This is the simplest setup.

```js
var express = require('express')
var bodyParser = require('body-parser')

var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())

app.use(function (req, res) {
  res.setHeader('Content-Type', 'text/plain')
  res.write('you posted:\n')
  res.end(JSON.stringify(req.body, null, 2))
})
```

### Express route-specific

This example demonstrates adding body parsers specifically to the routes that
need them. In general, this is the most recommended way to use body-parser with
Express.

```js
var express = require('express')
var bodyParser = require('body-parser')

var app = express()

// create application/json parser
var jsonParser = bodyParser.json()

// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })

// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
  res.send('welcome, ' + req.body.username)
})

// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
  // create user in req.body
})
```

### Change accepted type for parsers

All the parsers accept a `type` option which allows you to change the
`Content-Type` that the middleware will parse.

```js
var express = require('express')
var bodyParser = require('body-parser')

var app = express()

// parse various different custom JSON types as JSON
app.use(bodyParser.json({ type: 'application/*+json' }))

// parse some custom thing into a Buffer
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))

// parse an HTML body into a string
app.use(bodyParser.text({ type: 'text/html' }))
```

## License

[MIT](LICENSE)

[npm-image]: https://img.shields.io/npm/v/body-parser.svg
[npm-url]: https://npmjs.org/package/body-parser
[travis-image]: https://img.shields.io/travis/expressjs/body-parser/master.svg
[travis-url]: https://travis-ci.org/expressjs/body-parser
[coveralls-image]: https://img.shields.io/coveralls/expressjs/body-parser/master.svg
[coveralls-url]: https://coveralls.io/r/expressjs/body-parser?branch=master
[downloads-image]: https://img.shields.io/npm/dm/body-parser.svg
[downloads-url]: https://npmjs.org/package/body-parser
+23 −0
Original line number Diff line number Diff line
(The MIT License)

Copyright (c) 2012-2014 TJ Holowaychuk <tj@vision-media.ca>
Copyright (c) 2015 Jed Watson <jed.watson@me.com>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+576 −0

File added.

Preview size limit exceeded, changes collapsed.

projet/package.json

0 → 100644
+18 −0

File added.

Preview size limit exceeded, changes collapsed.

projet/sql-request.js

0 → 100644
+300 −0

File added.

Preview size limit exceeded, changes collapsed.