commit 913b02c9ce579663f67d001b8aa97100fce4a002 Author: Juan Carlos Valencia Oropeza Date: Sat Apr 27 23:14:07 2024 -0400 plantilla inicial Backend diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..3ae039c --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets":["latest"] +} diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..c84d74d --- /dev/null +++ b/.eslintrc @@ -0,0 +1,91 @@ +{ + "globals": { + "myModule": true + }, + "env": { + "es6": true + }, + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module", + "ecmaFeatures": { + "jsx": true, + "generators": false, + "objectLiteralDuplicateProperties": false + } + }, + "rules": { + // enforces no braces where they can be omitted + // http://eslint.org/docs/rules/arrow-body-style + "arrow-body-style": [2, "as-needed"], + // require parens in arrow function arguments + "arrow-parens": 0, + // require space before/after arrow function"s arrow + // https://github.com/eslint/eslint/blob/master/docs/rules/arrow-spacing.md + "arrow-spacing": [2, { "before": true, "after": true }], + // require trailing commas in multiline object literals + "comma-dangle": [2, "always-multiline"], + // verify super() callings in constructors + "constructor-super": 0, + // enforce the spacing around the * in generator functions + "generator-star-spacing": 0, + // disallow modifying variables of class declarations + "no-class-assign": 0, + // disallow arrow functions where they could be confused with comparisons + // http://eslint.org/docs/rules/no-confusing-arrow + "no-confusing-arrow": [2, { + "allowParens": true, + }], + // disallow modifying variables that are declared using const + "no-const-assign": 2, + // disallow duplicate class members + // http://eslint.org/docs/rules/no-dupe-class-members + "no-dupe-class-members": 2, + // disallow importing from the same path more than once + // http://eslint.org/docs/rules/no-duplicate-imports + "no-duplicate-imports": 2, + // disallow symbol constructor + // http://eslint.org/docs/rules/no-new-symbol + "no-new-symbol": 2, + // disallow specific globals + "no-restricted-globals": 0, + // disallow specific imports + // http://eslint.org/docs/rules/no-restricted-imports + "no-restricted-imports": 0, + // disallow to use this/super before super() calling in constructors. + "no-this-before-super": 0, + // require let or const instead of var + "no-var": 2, + // disallow unnecessary constructor + // http://eslint.org/docs/rules/no-useless-constructor + "no-useless-constructor": 2, + // require method and property shorthand syntax for object literals + // https://github.com/eslint/eslint/blob/master/docs/rules/object-shorthand.md + "object-shorthand": [2, "always"], + // suggest using arrow functions as callbacks + "prefer-arrow-callback": 2, + // suggest using of const declaration for variables that are never modified after declared + "prefer-const": 2, + // suggest using the spread operator instead of .apply() + "prefer-spread": 0, + // suggest using Reflect methods where applicable + "prefer-reflect": 0, + // use rest parameters instead of arguments + // http://eslint.org/docs/rules/prefer-rest-params + "prefer-rest-params": 2, + // suggest using template literals instead of string concatenation + // http://eslint.org/docs/rules/prefer-template + "prefer-template": 2, + // disallow generator functions that do not have yield + "require-yield": 0, + // import sorting + // http://eslint.org/docs/rules/sort-imports + "sort-imports": 0, + // enforce usage of spacing in template strings + // http://eslint.org/docs/rules/template-curly-spacing + "template-curly-spacing": 2, + // enforce spacing around the * in yield* expressions + // http://eslint.org/docs/rules/yield-star-spacing + "yield-star-spacing": [2, "after"] + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba8a5a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +logs/* +node_modules/ +public/informes/*.pdf +public/plantillas/*.pdf +public/documentos/*.pdf +public/externos/*.pdf +public/apidoc/*.* +public/apidoc/* +public/documentos/* +src/config/config.json +src/config/config.js +npm-debug.log +*.env +.jshintrc +.vscode +package-lock.json \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f65a9b5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +# Registro de cambios +PLANTILLAS - Sistema de documentos administrativos diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f9cef0b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,88 @@ +FROM node:12.14.1-stretch-slim + +ARG TINI_VERSION=v0.19.0 + +LABEL maintainer="Carlos Remuzzi cremuzzi@agetic.gob.bo" +LABEL org.label-schema.description="Backend del sistema de plantillas de AGETIC" +LABEL org.label-schema.name="plantillas-backend" +LABEL org.label-schema.schema-version="1.0" +LABEL org.label-schema.vcs-ref=$GITLAB_SHA +LABEL org.label-schema.vcs-url="https://gitlab.softwarelibre.gob.bo/agetic/plantillas/plantillas-backend" +LABEL org.label-schema.vendor="AGETIC" + +ENV BACKEND_PUERTO=8000 \ + CITE_DIGITOS=5 \ + CITE_GUIA=ENTIDAD \ + CONFIG_JSON_PATH=/home/node/app/src/config/config.json.sample \ + CONFIG_JS_PATH=/home/node/app/src/config/config.js.sample \ + CORREO_HOST=localhost \ + CORREO_IGNORETLS=false \ + CORREO_ORIGEN=ejemplo@correo.gob.bo \ + CORREO_PUERTO=25 \ + CORREO_REMITENTE=Nombre-del-Remitente \ + CORREO_SECURE=false \ + CORREO_TLS_RECHAZAR=false \ + DB_HOST=plantillas_db \ + DB_NOMBRE=plantillas \ + DB_PASSWORD=plantillas \ + DB_PUERTO=5432 \ + DB_USUARIO=plantillas \ + DOCUMENTO_GET=false \ + HOST_BACKEND=0.0.0.0 \ + HOST_FRONTEND=0.0.0.0 \ + IDENTIFICADOR_DIRECCION_UNIDAD=2 \ + IDENTIFICADOR_DIRECTOR=2 \ + JWT_SECRET=esta-cadena-tiene-que-ser-modificada-en-produccion \ + JWT_SESSION=false \ + JWT_TIEMPO=60 \ + LDAP_BIND_DN=cn=admin,dc=entidad,dc=gob,dc=bo \ + LDAP_BIND_PASSWORD=admin \ + LDAP_SEARCHBASE=ou=usuarios,dc=entidad,dc=gob,dc=bo \ + LDAP_URL=ldaps://ldap.example.abc:1234 \ + NODE_ENV=production \ + NOTIFICACION_CORREO_TOKEN=correo-token \ + NOTIFICACION_CORREO_URL=http://192.168.1.2/correo \ + NOTIFICACION_SMS_TOKEN=sms-token \ + NOTIFICACION_SMS_URL=http://192.168.1.2/sms \ + RUTA_ARCHIVOS_EXTERNOS=./public/externos/ \ + RUTA_DOCUMENTOS=./public/documentos/ + +RUN apt-get update \ + && mkdir -p /usr/share/man/man1 \ + && apt-get install --no-install-recommends -y \ + build-essential \ + curl \ + openjdk-8-jre-headless \ + python \ + && npm install -g \ + pg \ + pg-hstore \ + sequelize \ + sequelize-cli \ + && curl -fsL https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini -o /usr/local/bin/tini \ + && chmod +x /usr/local/bin/tini \ + && mkdir /home/node/app \ + && chown -R node:node /home/node/app + +WORKDIR /home/node/app + +USER node + +COPY --chown=node:node package.json . +COPY --chown=node:node ./parches/ ./parches/ + +RUN npm i \ + && npm run parchar + +COPY --chown=node:node . . + +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +COPY --chown=node:node seeder.sh /home/node/app/seeder.sh + +VOLUME ["/home/node/app/public"] + +EXPOSE 8000 + +ENTRYPOINT ["/usr/local/bin/tini","--","/usr/local/bin/entrypoint.sh"] + +CMD ["node","index.js"] diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..c24548c --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,377 @@ +.:: Plantillas Formly Backend ::. +================================================ + +A continuación se detalla la instalación de la aplicación desde cero. +El presente manual fue probado en un servidor con Debian 9. + + +# INSTALACIÓN DESDE CERO + +## 1. Instalación de paquetes mínimos + +```sh +sudo apt-get update +sudo apt-get install build-essential libssl-dev +sudo apt-get install curl +sudo apt-get install ca-certificates +sudo apt-get install libfontconfig1-dev libfreetype6-dev fontconfig +sudo apt-get install unzip +sudo apt-get install git +sudo apt-get install openjdk-8-jdk-headless +``` +Si no se cuenta con un servidor LDAP externo, para instalar realizar lo siguiente: +```sh +sudo apt -y install slapd ldap-utils +``` +Se puede verificar y validar la instalación con el siguiente comando, que desplega la estructura de la configuración. +```sh +sudo slapcat + +dn: dc=agetic,dc=gob,dc=bo +objectClass: top +objectClass: dcObject +objectClass: organization +o: agetic.gob.bo +dc: agetic +structuralObjectClass: organization +entryUUID: 71da7e0e-d7ac-1039-9bfa-61fe9051f214 +creatorsName: cn=admin,dc=agetic,dc=gob,dc=bo +createTimestamp: 20200130130159Z +entryCSN: 20200130130159.199740Z#000000#000#000000 +modifiersName: cn=admin,dc=agetic,dc=gob,dc=bo +modifyTimestamp: 20200130130159Z +.... +``` + +Configurar la estructura del sistema de acuerdo a su Entidad, revisar la documentación [OpenLdap](https://www.openldap.org). + +Se recomienta utilizar un cliente para la administración del ldap +- [Apache Directory](https://directory.apache.org/). +- [phpLdapAdmin](http://phpldapadmin.sourceforge.net/wiki/index.php/Main_Page). + +**Nota Importante: Se recomienda utilizar la versión última del LDAP, que específicamente incorpore el protocolo TLS versión 1.2, debido a que la versión de node 12.x no soporta versiones anteriores.** + +## 2. Instalación de PostgreSql +```sh +sudo apt-get install postgresql-9.6 +``` +Crear la base de datos +```sh +# Cambio al usuario root +sudo su + +# Acceso al usuario postgres +su postgres + +# Acceso a línea de comandos de postgres +psql +``` +Cambio de contraseña desde línea de comandos de postgres + +```sql +ALTER ROLE miUsuario PASSWORD 'miSuperPassword'; +``` +Reiniciar el servicio desde el usuario de la máquina virtual ([miUsuarioSistema]) +```sh +sudo /etc/init.d/postgresql restart +``` +Creando la base de datos +```sh +sudo su +su postgres +su psql +``` +```sql +CREATE DATABASE miBaseDeDatos OWNER miUsuario; +``` +Lista las bases de datos existentes, verificar si __miBaseDeDatos__ está en la lista. +```sql +\l +\q +``` + + +## 3. Instalación de Node, Node Version Manager NVM + +```sh +# Instalar nvm, via curl +curl https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash + +# Una vez finalizada REINICIAR la terminal para verificar la instalación +nvm --version +``` + +Instalación de Node v12.4.1 LTS +```sh +nvm install 12.14.1 +nvm use 12.14.1 + +# Verificar la instalación +node --version +``` +Instalación de dependencias globales para base de datos vía npm +```sh +npm i -g sequelize sequelize-cli +npm i -g pg pg-hstore +npm i -g apidoc +``` +## 4. Descargar el proyecto +```sh +git clone +cd +``` + +## 5. Instalación de la Fuente + +```sh +# Crear una nueva carpeta +sudo mkdir /usr/share/fonts/truetype/opensans +``` + +Copiar la fuente desde __recursos/open-sans.zip__ a __/usr/share/fonts/truetype/opensans__ + +```sh +sudo cp recursos/open-sans.zip /usr/share/fonts/truetype/opensans +cd /usr/share/fonts/truetype/opensans +sudo unzip open-sans.zip +cd - +``` + +## 6. Archivos de configuración + +```sh +# Archivo de configuración para la base de datos +cp src/config/config.json.sample src/config/config.json + +# Archivo de configuración para el sistema, conexion ldap, variables de sistema +cp src/config/config.js.sample src/config/config.js +``` + +## 7. Instalar dependencias e inicializar la db + +```sh +# Instalar las dependencias del proyecto +npm i + +# Modificar los sequelize handlers del proyecto +npm run parchar + +# Inicializar la base de datos y poblar la base de datos +npm run setup +``` + +## 8 Ejecución de la aplicación + +- Modo desarrollo + + ```sh + npm start + ``` + o si prefiere usar nodemon: + + ***Usando nodemon*** + ```sh + # Para este caso es necesario tener instalado nodemon de manera global + # npm i nodemon -g + npm run startdev + ``` + Para más información sobre [__NODEMON__](https://nodemon.io/) +- Modo producción + + ** Para este modo revise la configuración en src/config/config.json en la sección __production__ + ```sh + # Instalar pm2 + npm i -g pm2 + + # Iniciar el proyecto + pm2 start prod.json + + # Listar todas las aplicaciones en ejecución, ahi estará la aplicación plantillas-backend + pm2 list + + ``` + Configurar el autoinicio, solo la primera vez + ```sh + # Configurar el autoinicio + pm2 startup + + # Generara un comando Similar al siguiente + # [PM2] To setup the Startup Script, copy/paste the following command: + # sudo env PATH=$PATH:/home/miUsuario/.nvm/versions/node/v12.14.1/bin /home/miUsuario/.nvm/versions/node/v12.14.1/lib/node_modules/pm2/bin/pm2 startup systemd -u d3x --hp /home/miUsuario + + # Ejecutamos el comando que nos genero sudo env PATH=$PATH:/ho...... + # Luego ejecutamos, que guarda la lista de procesos + pm2 save + + ``` + + Para más información sobre [__PM2__](https://pm2.keymetrics.io/) + + +## Modalidad de autenticación. + +La autenticación se puede configurar de tres formas diferentes: + + a. Haciendo uso sólamente de la autenticación del sistema. + b. Haciendo uso del servicio de autenticación LDAP. + c. Haciendo uso del servicio de autenticación de Ciudadanía Digital. + +Las tres opciones son excluyentes. + +### a. Haciendo uso sólamente de la autenticación del sistema. +Para esto se puede dejar el código tal cual está. Sin embargo, se recomienda eliminar en el archivo ***/src/routes/seguridad/jwtokenRT.js*** las líneas 228 a la 233, que si bien son líneas comentadas, una vez en producción no serán de utilidad. + +### b. Haciendo uso del servicio de autenticación LDAP. +Para poder usar esta configuración, se debe realizar lo siguiente: + +> Editar el archivo ***/src/routes/seguridad/jwtokenRT.js***, en el segmento de cógido (líneas 228-237) que contiene lo siguiente : + +```sh +228 // La siguiente línea trabaja con LDAP, realiza una autenticación con el servidor LDAP y si el usuario no existe en el sistema, lo adiciona a partir de la información +229 // del servidor LDAP. Descomentar la línea y comentar app.post("/autenticar", (req,res) => { +230 // app.post("/autenticar", interceptar, (req,res) => { +231 +232 // La siguiente línea trabaja directamente con el sistema, es una autenticación directa con la base de datos del sistema. Funcionará si la línea app.post("/autenticar", interceptar, (req,res) => { +233 // está comentada. +234 app.post("/autenticar", (req,res) => { +235 xautenticacion(req, res, 1); +236 }); +237 +``` +> Tal como lo explican los comentarios, se debe descomentar la línea 230 y en su lugar comentar la línea 234. Para la puesta en producción, se deben eliminar las líneas 228, 229, 231, 232, 233 y 234. Quedando así, el siguiente segmento de código: + +``` sh +app.post("/autenticar", interceptar, (req,res) => { + xautenticacion(req, res, 1); +}); +``` +Se requiere de la configuración de LDAP, que ya fue explicada en este archivo. +### c. Haciendo uso del servicio de autenticación de Ciudadanía Digital. + +Para esta opción, en el archivo ***/src/routes/seguridad/jwtokenRT.js***, eliminar las líneas 40 a la 251. Es decir, todo lo referente a la ruta de "/autenticar". Es importante eliminar estas líneas, para la seguridad y el correcto funcionamiento del sistema. + +Requiere de la configuración de LDAP, que ya fue explicada en este archivo. + + +## Usuarios de prueba + +Con el propósito de realizar pruebas, con la ejecución los seeders, se está habilitando el usuario ***sys_default***, con el rol de ADMIN para que dicho usuario pueda realizar la configuración general del sistema, como por ejemplo el alta a otros usuarios con rol admin y demás. + +Para el modo LDAP o Ciudadanía Digital es necesario que se cuente con un usuario LDAP habilitado para el usuario por defecto, donde se pide que el nombre de usuario sea: sys_default y la contraseña por defecto: Developer. + +A continuación el ejemplo de la configuración del usuario sería de la siguiente manera: +```sh +dn: uid=sys_default,ou=usuarios,dc=nodomain +objectClass: top +objectClass: inetOrgPerson +uid: sys_default +structuralObjectClass: inetOrgPerson +entryUUID: 1afa454c-d7e3-1039-9933-b525709c0f84 +creatorsName: cn=admin,dc=nodomain +createTimestamp: 20200130193315Z +userPassword:: e01ENX1aeXl2Si9VMlBjZ3p2YVVKbDNYb2tRPT0= +cn: Sys +sn: Default +description: Usuario por defecto del sistema +employeeNumber: 1 +employeeType: ninguno +givenName: Sys +mail: sys@local.com +o: ENTIDAD +ou: UNIDAD +registeredAddress: sys@local.com +telephoneNumber: 000000 +title: CARGO +entryCSN: 20200130194031.077493Z#000000#000#000000 +modifiersName: cn=admin,dc=nodomain +modifyTimestamp: 20200130194031Z +``` +**NOTA IMPORTANTE:** Luego de realizar las pruebas necesarias se recomienda dar de baja al usuario respectivo. + + +#### * Extra + +- Si se presenta algun error relacionado con el uso de "libfontconfig0" por parte de phantom.js, instalar el mismo con: + ```sh + sudo apt-get install libfontconfig1-dev + ``` + +- Si se presenta el error "Can't find Python executable python", instalar python con: + ```sh + sudo apt-get install python + ``` + +- En la carpeta /public/images reemplazar las imágenes logo.svg, membrete.png a usar de manera predeterminada. + + - membrete.png ancho: 574 píxeles, alto: 801 píxeles + - logo.svg ancho: 200 píxeles, alto: 80 píxeles + + +# INSTALACIÓN CON DOCKER + +## Compilación + +Puedes hacer una compilación rápida de la imagen con el comando: + +```sh +docker build -t plantillas-backend . +``` + +## Uso de la imagen + +La imagen necesita minimamente las siguientes variables de entorno: + +* `DB_HOST` : nombre de host o ip de la base dato postgres +* `DB_NOMBRE` : nombre de la base datos postgres +* `DB_PASSWORD` : password de la base dato postgres +* `DB_PUERTO` : puerto de la base dato postgres +* `DB_USUARIO` : usuario de la base dato postgres + +y expone adentro del contenedor el puerto **8000**. + +Por ejemplo puedes levantar una instancia del backend con el siguiente comando: + +```sh +docker run \ + --name plantillas_backend \ + -e DB_HOST=1.2.3.4 \ + -e DB_NOMBRE=plantillas \ + -e DB_PASSWORD=plantillas \ + -e DB_PUERTO=5432 \ + -e DB_USUARIO=plantillas \ + -p 5001:8000 \ + plantillas-backend +``` + +en este ejemplo estamos asumiendo que nuestra base dato postgres se encuentra disponible sobre la ip **1.2.3.4** y puerto **5432** y estamos exponiendo el puerto **5001** desde el puerto interno 8000. Una vez ejecutado el comando, podrás consumir el backend de plantillas desde la url http://127.0.0.1:5001 en el caso estes en el mismo host. + +despues del primer arranque es necesario inicializar la base de datos con el siguiente comando: + +```sh +docker exec plantillas_backend sh seeder.sh +``` + +## Persistencia de datos + +El sistema plantillas-backend dockerizado genera y almacena documentos pdf en su propio filesystem efimero bajo la ruta: + +`/home/node/app/public` + +Para garantizar la persistencia de los documentos es suficiente crear y montar un volumen docker externo conectado a esta ruta, +por ejemplo con los comandos: + +```sh +docker volume create plantillas-documentos + +docker run \ + --name plantillas_backend \ + -e DB_HOST=1.2.3.4 \ + -e DB_NOMBRE=plantillas \ + -e DB_PASSWORD=plantillas \ + -e DB_PUERTO=5432 \ + -e DB_USUARIO=plantillas \ + -p 5001:80 \ + -v plantillas-documentos:/home/node/app/public \ + plantillas-backend +``` + diff --git a/LICENCIA.md b/LICENCIA.md new file mode 100644 index 0000000..e370580 --- /dev/null +++ b/LICENCIA.md @@ -0,0 +1,651 @@ + Agencia para el Desarrollo de la Sociedad de la Información en Bolivia + + LICENCIA PÚBLICA GENERAL + de Consideraciones y Registro de Software Libre en Bolivia (LPG-Bolivia) + + Versión 1, 13 de mayo de 2014. + + Introducción + +Esta licencia está basada en la Licencia Pública General GNU (GNU GPL) de la +Fundación para el Software Libre (www.fsf.org), la cual ha sido adaptada por la +Agencia para el Desarrollo de la Sociedad de la Información en Bolivia (ADSIB) +a la normativa legal vigente en Bolivia, enmarcada en la Ley General de +Telecomunicaciones, Tecnologías de Información y Comunicación, Ley No. 164 de 8 +de agosto de 2011 y el Reglamento para el Desarrollo de Tecnologías de +Información y Comunicación aprobado por el Decreto Supremo No. 1793 de 13 de +noviembre de 2013. + +Ésta no constituye una traducción oficial de la GNU GPL al español. No ha sido +publicada por la Fundación para el Software Libre, y no establece legalmente +las condiciones de distribución para el software que usa la GNU GPL –estas +condiciones se establecen solamente por el texto original de la GNU GPL de la +Fundación para el Software Libre (www.fsf.org). + +Esta licencia se aplica conforme a la legislación vigente y en orden de +prelación normativa dando prioridad a lo normativa superior y sin vulnerar +cualquier derecho consagrado por la Constitución y las Leyes del Estado +Plurinacional de Bolivia. + +Esta licencia se basa en la traducción elaborada por Gonzalo Abella, Javier +Aguirre, Héctor J. Macho Borja Menéndez, Javier Moset, Ángel Torrado. + + Preámbulo + +La Licencia Pública General Bolivia (LPG - Bolivia) es una licencia libre para +software y otro tipo de obras. + +Las licencias para la mayoría del software y otras obras de carácter práctico +están diseñadas para privarle de la libertad de compartir y modificar las +obras. Por el contrario, esta Licencia Pública General pretende garantizar su +libertad de compartir y modificar todas las versiones de un programa –para +cerciorar que permanece como software libre para todos sus usuarios. + +Cuando hablamos de software libre, nos referimos a libertad de acción, no de +precio. La LPG - Bolivia está diseñada para garantizar la libertad de +distribuir copias de software libre (y cobrar por ello si quiere), de recibir +el código fuente o poder conseguirlo si así lo desea, de modificar el software +o usar parte del mismo en nuevos programas libres, y a saber que puede hacer +estas cosas. + +Para proteger sus derechos, necesitamos evitar que otros le nieguen esos +derechos o le pidan renunciar a ellos. Por lo tanto, usted tiene ciertas +responsabilidades cuando distribuye copias del software, o si lo modifica: +responsabilidades que persiguen respetar la libertad de otros. + +Si distribuye copias de un programa, bien sea gratis o por una tasa, debe +transferirles a los que lo reciban las mismas libertades que usted recibió. +Debe asegurarse que ellos, también, reciben o pueden obtener el código fuente. +Y debe mostrarles estos términos para que ellos puedan conocer sus derechos. + +Los desarrolladores que usan la LPG-Bolivia protegen tus derechos con dos +pasos: (1) haciendo valer el derecho de propiedad intelectual en el software y +(2) le ofrecen esta Licencia que le da el permiso legal para copiarlo, +distribuirlo y/o modificarlo. + +Para la protección de autores y desarrolladores, la LPG-Bolivia explica +claramente que no hay garantía para este software libre. Por el bien de +usuarios como de autores o titulares, la LPG-Bolivia establece que las +versiones modificadas sean identificadas como tales, de forma que sus problemas +no puedan ser atribuidos de forma errónea a autores de versiones previas. + +Algunos dispositivos están diseñados para denegar a los usuarios el acceso a +instalar o ejecutar versiones modificadas del software en su interior, a pesar +de que el fabricante puede hacerlo. Esto es fundamentalmente incompatible con +el objetivo de proteger la libertad de los usuarios de modificar el software. +Este tipo de abuso sistemático ocurre en el ámbito de los productos de uso +personal, que es precisamente donde es más inaceptable. Por consiguiente, hemos +diseñado esta versión de la LPG-Bolivia para prohibir estas prácticas en esos +productos. + +Finalmente, todo programa está constantemente amenazado por las patentes de +software. El Estado buscará los medios mas idóneos para evitar el especial +peligro que suponen las patentes, que aplicadas a un programa libre puedan +hacerlo propietario en la práctica. Para prevenir eso, la LPG-Bolivia establece +que las patentes no pueden usarse para convertir un programa en no-libre. + +Los términos exactos y las condiciones para la copia, distribución y +modificación se exponen a continuación. + + Términos y Condiciones + +0. Definiciones + +“Licencia” se refiere a la Licencia Pública General Bolivia (LPG-Bolivia) +"Copyright", “Derechos de Autor (“Copyright”)” incluye a las leyes similares a +la de derechos de autor (“copyright”) que se apliquen a otro tipo de obras. + +“El Programa” se refiere a cualquier obra con derechos de autor bajo esta +Licencia. Cada “licenciatario” o “destinatario” es tratado como “usted”. Los +“licenciatarios”, y los “destinatarios” pueden ser individuos u organizaciones. + +“Modificar” una obra quiere decir copiar o adaptar parte o la totalidad de la +obra de una forma que se requieran permisos de derechos de autor (“copyright”), +distintos de los de hacer una copia exacta. La obra resultante es llamada +“versión modificada” de la obra previa o una obra “basada en” la obra previa. + +“Obra amparada” significa o el Programa sin modificar o una obra basada en el +Programa. + +"Difundir" una obra significa hacer cualquier cosa con él que, sin permiso, le +haga directa o indirectamente responsable de infringir leyes de derechos de +autor (“copyright”), excepto la ejecución en un ordenador o la modificación de +una copia privada. La difusión incluye la copia, distribución (con o sin +modificaciones) y publicación. + +"Transmitir" una obra quiere decir cualquier tipo de difusión que permita a +otras partes hacer o recibir copias. La mera interacción con un usuario a +través de una red informática, sin transferir una copia, no es transmitir. + +Una interfaz interactiva de usuario muestra “Avisos Legales Apropiados” en la +medida que incluye una característica visible, práctica y destacada que (1) +muestra un aviso apropiado de derechos de autor (“copyright”), y (2) informa al +usuario de que no hay garantía para la obra (excepto las garantías +proporcionadas), que los licenciatarios deben transmitir la obra bajo esta +Licencia, y cómo ver una copia de esta Licencia. Si la interfaz presenta una +lista de comandos de usuario u opciones, como un menú, un elemento destacado en +la lista satisface este criterio. + +1. Código Fuente + +El "código fuente" de una obra es el formato preferido de la misma para +realizar modificaciones sobre ella. "Código objeto" se refiere a cualquier +formato de la obra que no sea código fuente. + +Una "Interfaz Estándar" se refiere a una interfaz que sea un estándar oficial +definido por una institución de estándares reconocida, o bien, en el caso de +interfaces específicas para un determinado lenguaje de programación, una cuyo +uso esté generalizado entre los desarrolladores que trabajan con ese lenguaje. + +Las “Bibliotecas del Sistema” de una obra ejecutable incluyen cualquier cosa, +diferente de la obra como un todo, que (a) está incluida en la forma normal de +empaquetado de un Componente Importante, pero que no forme parte de ese +Componente Importante, y (b) sirve solo para habilitar el uso de la obra con +ese Componente Importante, o para implementar una Interfaz Estándar para la +cual una implementación está disponible para el público en forma de código +fuente. Un “Componente Importante”, en este contexto, significa un componente +importante esencial (kernel, sistema de ventanas, etcétera) del sistema +operativo en concreto (si hubiese) en el cual el ejecutable funciona o un +compilador utilizado para producir la obra, o un intérprete de código objeto +utilizado para hacerla funcionar. + +La “Fuente Correspondiente” de una obra en forma de código objeto significa +todo el código fuente necesario para generar, instalar, y (para una obra +ejecutable) hacer funcionar el código objeto y modificar la obra, incluyendo +los scripts o guiones o archivos de órdenes para controlar dichas actividades. +Sin embargo, ello no incluye la obra de las Bibliotecas del Sistema o +herramientas de propósito general o programas de libre disponibilidad general, +los cuales son usados sin modificaciones para la realización de dichas +actividades, pero que no son parte de la obra. Por ejemplo, la Fuente +Correspondiente incluye ficheros de definición de interfaces asociados a los +ficheros fuente para la obra, y el código fuente para bibliotecas compartidas y +subprogramas enlazados dinámicamente que la obra requiere específicamente por +diseño, tales como la comunicación de datos intrínseca o flujo de control entre +aquellos subprogramas y otras partes de la obra. + +La Fuente Correspondiente no incluye necesariamente aquello que los usuarios +pueden regenerar automáticamente a partir de otras partes de la Fuente +Correspondiente. + +La Fuente Correspondiente de una obra en forma de código fuente es la obra en +sí. + +2. Permisos Básicos + +Todos los derechos concedidos bajo esta Licencia se conceden durante la +duración de los derechos de autor (“copyright”) del Programa, y son +irrevocables siempre que se cumplan las condiciones establecidas. Esta Licencia +afirma explícitamente su permiso ilimitado para ejecutar el Programa sin +modificar. El resultado de la ejecución de una obra amparada está cubierta por +esta Licencia solo si el mismo, dado su contenido, constituye una obra +amparada. Esta Licencia reconoce sus derechos de uso razonable u otro +equivalente, según lo establecido por la ley de derechos de autor +(“copyright”). + +Usted podrá realizar, ejecutar y difundir obras amparadas que usted no +transmita sin condición alguna, siempre y cuando la Licencia vigente no +establezca otra cosa. Podrá transmitir obras amparadas a terceros con el único +propósito de que ellos hagan modificaciones exclusivamente para usted, o +proporcionarle ayuda para ejecutar estas obras, siempre y cuando cumpla con los +términos de esta Licencia en la transmisión de todo el material del cual usted +no controle los derechos de autor (“copyright”). Aquellos que realicen o +ejecuten las obras amparadas para usted, deben hacerlo exclusivamente en su +nombre, bajo su dirección y control, en términos que prohiban realizar ninguna +copia de su materia registrado bajo derechos de autor (“copyright”) fuera de la +relación con usted. + +La transmisión bajo otras circunstancias se permite únicamente bajo las +condiciones establecidas más abajo. No está permitido sublicenciar; la claúsula +10 lo hace innecesario. + +3. Protección de Derechos Legales de los Usuarios Frente a Leyes Anti-Evación. + +Ninguna obra amparada debe considerarse parte de una medida tecnológica +efectiva, a tenor de lo establecido en cualquier ley aplicable que cumpla las +obligaciones establecidas en el artículo 11 del tratado de derechos de autor +(“copyright”) de WIPO adoptado el 20 de diciembre de 1996, por el hoy Estado +Plurinacional de Bolivia o leyes similares que prohíban o restrinjan la evasión +de tales medidas. + +Cuando transmita una obra amparada, renuncia a cualquier poder legal para +prohibir la evasión de medidas tecnológicas, mientras tales evasiones se +realicen en ejercicio de derechos amparados por esta Licencia respecto a la +obra amparada; además, usted renuncia a cualquier intención de limitar el uso o +modificación de la obra con el objetivo de imponer, en contra de los usuarios +de la obra, sus derechos legales o los de terceros para prohibir la evasión de +medidas tecnológicas. + +4. Transmisión de Copias Literales + +Usted podrá transmitir copias literales del código fuente del Programa tal cual +lo ha recibido, por cualquier medio, siempre que publique visible y +apropiadamente en cada copia el correspondiente aviso de derechos de autor +(“copyright”); mantenga intactos todos los avisos que establezcan que esta +Licencia y cualquier cláusula no-permisiva añadida acorde con la cláusula 7 +aplicables al código; mantenga intactos todos los avisos de ausencia de +garantía; y proporcione a todos los destinatarios una copia de esta Licencia +junto con el Programa. + +Usted podrá cobrar cualquier importe o no cobrar nada por cada copia que +transmita y podrá ofrecer soporte o protección de garantía mediante un pago. + +5. Transmisión de Versiones Modificadas del Código + +Usted puede transmitir una obra basada en el Programa, o las modificaciones +para generarla a partir del Programa, en la forma de código fuente bajo los +términos de la sección 4, siempre que cumpla además todas las condiciones +siguientes: + +a) La obra debe incluir avisos destacados indicando que usted la ha modificado +y dando una fecha pertinente. + +b) La obra debe incluir avisos destacados indicando que está liberada o +publicada bajo esta Licencia y cualquier otra condición añadida bajo la sección +7. Este requerimiento modifica los requerimientos de la sección 4 de “mantener +intactos todos los avisos”. + +c) Usted debe licenciar la obra entera, como un todo, bajo esta Licencia para +cualquier persona que esté en posesión de una copia. Esta Licencia se aplicará +por consiguiente junto con cualquier término adicional aplicable bajo la +sección 7, a la totalidad de la obra y a todos sus componentes, +independientemente de como estén empaquetados. Esta Licencia no autoriza a +licenciar la obra de otra forma, pero no invalida esos permisos si usted los ha +recibido de forma separada. + +d) Si la obra tiene interfaces de usuario interactivas, cada una debe mostrar +los Avisos Legales Apropiados; sin embargo, si el Programa tiene interfaces +interactivas que no muestran los Avisos Legales Apropiados, tampoco es +necesario que su obra lo haga. + +Una recopilación de una obra amparada con otras obras separadas e +independientes, que no son por su naturaleza extensiones de la obra amparada, y +que no se combinan con ella con el fin de formar un programa más grande, en o +sobre un volumen de un medio de almacenamiento o distribución, es llamado un +“agregado” si la recopilación y sus resultantes derechos de autor (“copyright”) +no son usados para limitar el acceso o los derechos legales de los usuarios de +la recopilación más allá de lo que las obras individuales permitan. La +inclusión de una obra amparada en un agregado no provoca que esta Licencia se +aplique a los otros componentes del agregado. + +6. Transmisión de Código No-Fuente + +Usted podrá transmitir el código objeto de una obra amparada en virtud de los +términos de las cláusulas 4 y 5, siempre que también transmita las Fuentes +Correspondientes en código legible por máquina, de acuerdo con los términos +establecidos en esta Licencia, de alguna de las siguientes maneras: + +a) Transmitir el código objeto en, o embebido en, un producto físico +(incluyendo medios de distribución físicos), acompañado de las Fuentes +Correspondientes en un medio físico duradero y que sea utilizado habitualmente +para el intercambio de software. + +b) Transmitir el código objeto en, o embebido en, un producto físico +(incluyendo medios de distribución físicos), acompañado de una oferta por +escrito, válido durante al menos tres años y válido mientras usted ofrezca +recambios o soporte para ese modelo de producto, de dar a cualquiera que posea +el código objeto bien (1) una copia de las Fuentes Correspondientes a todo el +software del producto que esté cubierto por esta Licencia, en un medio físico +duradero habitual para el intercambio de software, a un precio razonable, +directamente relacionado al costo de efectuar la transmisión física de la +Fuente Correspondiente, o (2) acceso para copiar la Fuente Correspondiente de +un servidor de red sin costo alguno. + +c) Transmitir copias individuales del código objeto junto con una copia del +ofrecimiento escrito de proveer la Fuente Correspondiente. Esta alternativa +sólo está permitida ocasionalmente y sin fines comerciales, y solamente si +usted recibió el código objeto junto con una oferta parecida, de acuerdo con la +subcláusula 6b. + +d) Transmitir el código objeto ofreciendo acceso desde un lugar determinado +(gratuitamente o mediante pago) y ofrecer acceso equivalente a la Fuente +Correspondiente de la misma manera en el mismo lugar sin cargo adicional. No es +necesario exigir a los destinatarios que copien la Fuente Correspondiente junto +con el código objeto. Si el lugar para copiar el código objeto es un servidor +de red, la Fuente Correspondiente puede estar en un servidor diferente +(gestionado por usted o un tercero) que ofrezca facilidades de copia +equivalentes, siempre que mantenga instrucciones claras junto al código objeto +especificando dónde encontrar la Fuente Correspondiente. Independientemente de +qué servidor albergue la Fuente Correspondiente, usted seguirá estando obligado +a asegurar que está disponible durante el tiempo que sea necesario para +satisfacer estos requisitos. + +e) Transmitir el código mediante transferencias de red entre pares o usuarios +(peer-to-peer), siempre que informe a los otros pares o usuarios dónde se +ofrece el código objeto y la Fuente Correspondiente de la obra al público +general de forma gratuita bajo la subsección 6d. + +Una porción separable del código objeto, cuyo código fuente está excluido de la +Fuente Correspondiente como una Biblioteca del Sistema, no necesita ser +incluida en la transmisión del código objeto de la obra. + +Un “Producto de Usuario” es o (1) un “producto de consumo”, lo que significa +cualquier propiedad tangible personal que es usada habitualmente con fines +personales, familiares o domésticos, o (2) cualquier cosa diseñada o vendida +para ser incorporada en una vivienda. Al determinar si un producto es un +producto de consumo, los casos dudosos serán resueltos en favor de la +cobertura. Para un producto concreto recibido por un usuario concreto, “uso +habitual” se refiere a un uso típico o común de esa clase de producto, sin +tener en cuenta la situación del usuario concreto o la forma en la que el +usuario concreto realmente use, o espera o se espera que use, el producto. Un +producto es un producto de consumo independientemente de si el producto tiene +usos esencialmente comerciales, industriales o distintos del consumo, a menos +que dichos usos constituyan el único modo de uso significativo del producto. + +Las "Instrucciones de Instalación" para un Producto de Usuario se refieren a +cualquier método, procedimiento, clave de autorización u otro tipo de +información necesaria para instalar y ejecutar una versión modificada de una +obra amparada en ese Producto de Usuario, a partir de una versión modificada de +su Fuente Correspondiente. Las instrucciones deben ser suficientes para +asegurar que el funcionamiento continuo del código objeto modificado no es +evitado, condicionado o interferido por el hecho de haber sufrido tal +modificación. + +Si transmite el código objeto de una obra en o con un Producto de Usuario o +específicamente para ser usado en el mismo, y la transmisión forma parte de una +transacción donde los derechos de posesión y uso del Producto de Usuario se +transfieren al destinatario a perpetuidad o por un periodo establecido +(independientemente de las características de la transacción), la Fuente +Correspondiente transmitida bajo esta sección debe estar acompañada de las +Instrucciones de Instalación. Pero este requisito no se aplica si ni usted ni +ningún tercero tiene la capacidad de instalar código objeto modificado en el +Producto de Usuario. + +El requisito de proveer de las Instrucciones de Instalación no incluye la +necesidad de continuar proporcionando asistencia, garantía o actualizaciones +para una obra que ha sido modificada o instalada por el destinatario, o para el +Producto de Usuario en el cual ha sido modificada o instalada. El acceso a una +red puede ser denegado cuando la modificación en sí afecta materialmente y +adversamente el funcionamiento de la red o viola las reglas y protocolos de +comunicación de la red. + +Las Fuentes Correspondientes transmitidas y las Instrucciones de Instalación +proporcionadas de acuerdo con esta sección deben figurar en un formato +documentado públicamente (y con una implementación disponible para el público +en forma de código fuente), y no deben necesitar contraseñas o claves de acceso +especiales para la extracción, lectura o copia. + +7. Condiciones adicionales + +Los “Permisos adicionales” son condiciones que complementan los términos de +esta Licencia haciendo excepciones de una o más de una de sus condiciones. Los +permisos adicionales que son aplicables al Programa entero deberán ser tratados +como si estuvieran incluidos en esta Licencia, hasta los límites de validez +impuestos por las leyes aplicables. Si los permisos adicionales sólo son +aplicables a parte del Programa, esa parte debe ser usada por separado bajo +esos permisos, pero el Programa completo queda bajo la autoridad de esta +Licencia sin considerar los permisos adicionales. + +Cuando transmita una copia de una obra amparada, puede opcionalmente quitar +cualesquiera permisos adicionales de esa copia, o de cualquier parte de ella. +(Los permisos adicionales pueden ser escritos para requerir su propia +eliminación bajo ciertos casos cuando se modifica la obra.) Puede incorporar +permisos adicionales a material añadido por usted a una obra amparada, sobre el +cual usted tiene o puede establecer los permisos de derechos de autor +(“copyright”) correspondientes. + +Sin contravenir cualquier otra disposición de esta Licencia, para el material +que añada a una obra cubierta por la misma, usted puede (si está autorizado por +los titulares de los derechos de autor (“copyright”) del material) complementar +los términos de esta Licencia en los siguientes términos: + +a) Declarando la ausencia de garantía o limitación de responsabilidad en forma +diferente a la de los términos establecidos en las cláusulas 14 y 15 de esta +Licencia; u + +b) Requiriendo la obligación de mantener determinados avisos legales razonables +o atribuciones de autoría en el material o en los Avisos Legales Apropiados +mostrados por las obras que lo contengan. + +c) Prohibir la tergiversación del origen del material o requerir que las +versiones modificadas del material se señalen de manera razonable como +diferentes de la versión original; o + +d) Limitar la utilización de los nombres de los autores o licenciantes del +material con fines publicitarios o comerciales; o + +e) Negarse a ofrecer derechos bajo leyes de registro para el uso de algunos +nombres comerciales, marcas registradas o marcas de servicio; o + +f) Exigir la compensación de los licenciantes y autores de ese material por +cualquiera que distribuya el material (o versiones modificadas del mismo) +estableciendo obligaciones contractuales de responsabilidad sobre el +destinatario, por cualquier responsabilidad que estas obligaciones +contractuales impongan directamente sobre los licenciantes y autores. + +Cualesquiera otras condiciones adicionales no-permisivas son consideradas +"restricciones adicionales" en el contexto de la cláusula 10. Si el Programa, +tal cual lo recibió, o cualquier parte del mismo, contiene un aviso indicando +que está amparado por esta Licencia junto a una cláusula de restricción +adicional, usted podrá suprimir esa cláusula. Si un documento de licencia +contiene una restricción de este tipo pero permite modificar la Licencia o la +transmisión de la obra en virtud de la presente Licencia, puede añadir material +regido por esa licencia a una obra amparada, siempre que dicha restricción no +se mantenga tras la modificación de la licencia o la transmisión. + +Si se añaden términos a una obra amparada de acuerdo con los términos de esta +sección, debe colocar, en los archivos fuente involucrados, una declaración de +los términos adicionales aplicables a esos archivos, o un aviso indicando donde +encontrar los términos aplicables. + +Las condiciones adicionales, permisivas o no, deben aparecer por escrito como +licencias separadas o figurar como excepciones; de todas formas, los requisitos +anteriores se aplican igualmente. + +8. Cancelación + +Usted no podrá difundir o modificar una obra amparada salvo lo expresamente +permitido por esta Licencia. Cualquier intento diferente de difusión o +modificación será considerado nulo y automáticamente cancelará sus derechos +respecto a esta Licencia (incluyendo cualquier patente conseguida según el +párrafo tercero de la cláusula 11). + +Sin embargo, si usted deja de violar esta Licencia, entonces su Licencia desde +el titular de los derechos de autor (“copyright”) correspondiente será +restituida (a) provisionalmente, a menos que y hasta que el titular de los +derechos de autor (“copyright”) explícita y permanentemente de por cancelada su +licencia, y (b) permanentemente, si el titular del derecho de autor no le ha +notificado su violación por algún medio razonable antes de los 60 días +siguientes a la cesación. + +Además, su Licencia de un titular de los derechos de autor (“copyright”) +correspondientes será restituida permanentemente si el titular de los derechos +de autor (“copyright”) le notifica la violación por algún medio razonable, +siendo ésta la primera vez que recibe la notificación de violación de esta +Licencia (para cualquier obra) de ese titular de los derechos de autor +(“copyright”), y usted subsana la violación antes de 30 días después de la +recepción de la notificación. + +La cancelación de sus derechos bajo esta sección no da por canceladas las +licencias de terceros que hayan recibido copias o derechos de usted bajo esta +Licencia. Si sus derechos han sido cancelados y no fueran renovados de manera +permanente, usted no cumple los requisitos para recibir nuevas licencias para +el mismo material bajo la sección 10. + +9. Aceptación por Tenencia de Copias. + +No está obligado a aceptar esta Licencia por recibir o ejecutar una copia del +Programa. La difusión de una obra amparada surgida simplemente como +consecuencia de la transferencias de red entre pares o usuarios (peer-to-peer) +para obtener una copia tampoco requiere aceptación. Sin embargo, únicamente +esta Licencia le otorga permiso para difundir o modificar cualquier obra +amparada. Estas acciones infringen los derechos de autor (“copyright”) si usted +no acepta esta Licencia. Por lo tanto, al modificar o difundir una obra +amparada, usted indica que acepta esta Licencia para hacerlo. + +10. Licencia Automática para Destinatarios Subsiguientes + +Cada vez que transmita una obra amparada, el destinatario recibirá +automáticamente una Licencia desde los licenciadores originales, para ejecutar, +modificar y difundir esa obra, al amparo de los términos de esta Licencia. +Usted no será responsable de asegurar el cumplimiento por terceros de esta +Licencia. + +Una “transacción de entidad” es una transacción que transfiere el control de +una organización, o sustancialmente todos los bienes de una, o subdivide una +organización, o fusiona organizaciones. Si la difusión de una obra amparada +surge de una transacción de entidad, cada parte involucrada en esa transacción +que reciba una copia de la obra, también recibe todas y cada una de las +licencias existentes de la obra que la entidad precedente tuviese o pudiese +ofrecer según el párrafo anterior, además del derecho a tomar posesión de la +Fuente Correspondiente de la obra a través del predecesor interesado, si está +en poder de dicha parte o se puede conseguir con un esfuerzo razonable. + +Usted no podrá imponer restricciones adicionales por el ejercicio de los +derechos otorgados o concedidos en virtud de la presente Licencia, no podrá +imponer a la Licencia pagos, derechos u otros cargos por la redistribución o +modificación a los subsiguientes beneficiarios o destinatarios de la obra según +los derechos otorgados bajo esta Licencia; además no podrá iniciar litigios +(incluyendo demandas o contrademandas en pleitos) alegando que se infringen +patentes por cambiar, usar, vender, ofrecer en venta o importar el Programa, o +cualquier parte del mismo. + +11. Patentes + +Un “colaborador” es un titular de los derechos de autor (“copyright”) que +autoriza, bajo los términos de la presente Licencia el uso del Programa o una +obra en la que se base el Programa. La obra así licenciada se denomina “versión +en colaboración” del colaborador. + +Las “demandas de patente esenciales” del colaborador son todas las +reivindicaciones de patentes poseídas o controladas por el colaborador, +existentes o adquiridas con posterioridad, que fueran infringidas de alguna +forma, permitida por esta Licencia, al hacer, usar o vender la versión en +colaboración, pero sin incluir demandas que sólo sean infringidas como +consecuencia de modificaciones posteriores de la versión en colaboración. Para +los propósitos de esta definición, “control” incluye el derecho de conceder +sublicencias de patente de forma consistente con los requisitos establecidos en +la presente Licencia. + +Cada colaborador le concede a usted una licencia de la patente no-exclusiva, +global y libre de regalías bajo las demandas de patente esenciales del +colaborador, para hacer, usar, modificar, vender, ofrecer para venta, importar +y otras formas de ejecución, modificación y difusión del contenido de la +versión en colaboración. + +En los siguientes tres párrafos, una “licencia de patente” se define como +cualquier acuerdo o compromiso expreso, cualquiera que sea su denominación, que +no imponga una patente (como el permiso expreso para ejecutar una patente o +acuerdos para no imponer demandas por infracción de patente). “Conceder” una +licencias de patente de este tipo a un tercero significa hacer tal tipo de +acuerdo o compromiso de no imponer una patente a ningún tercero. + +Si usted transmite una obra amparada, conociendo que está amparada por una +licencia de patente, y las Fuentes Correspondientes no se encuentran +disponibles de forma pública para su copia, sin cargo alguno y bajo los +términos de esta Licencia, ya sea a través de un servidor público o mediante +cualquier otro medio, entonces usted deberá (1) hacer que las Fuentes +Correspondientes sean públicas, o (2) tratar de eliminar los beneficios de la +licencia de patente para esta obra en particular, o (3) tratar de extender, de +manera compatible con los requisitos de esta Licencia, la licencia de patente a +los terceros o destinatarios subsiguientes. “Conocer que está afectado” +significa que usted tiene conocimiento real de que, para la licencia de +patente, la transmisión de la obra amparada en un país, o el uso de la obra +amparada por sus destinatarios en un país, infringiría una o más patentes +existentes en ese país que usted considera válidas por algún motivo. + +Si, de conformidad con alguna transacción o acuerdo (o en un proceso +relacionado con ellos), usted transmite o difunde con fines de distribución, +una obra amparada, concediendo una licencia de patente para algún tercero que +reciba la obra amparada, y autorizá a usar, difundir, modificar o transmitir +una copia específica de la obra amparada, entonces la licencia de patente que +usted otorgue se extiende automáticamente a todos los receptores de la obra +amparada y cualquier obra basada en ella. + +Una licencia de patente es “discriminatoria” si no incluye en el marco de su +cobertura los derechos otorgados por esta licencia, prohíbe el ejercicio o esta +condicionada al no ejercicio de uno o mas de los derechos específicamente +otorgados por esta licencia. Usted no debe transmitir una obra amparada si +usted es parte de un acuerdo con una tercera parte involucrada en el negocio de +distribución de software, bajo el cual usted debe realizar un pago a esa parte +basado en el rango de su actividad de transmisión de la obra y bajo la cual la +tercera parte adquiere, frente a cualquiera de las partes que pueda recibir de +usted la obra, una licencia de patente discriminatoria (a) en conexión con +copias de la obra amparada distribuida por usted (o copias hechas de esas +copias), o (b) principalmente o en conexión con productos específicos o +compilaciones que contienen la obra amparada. + +Nada en esta Licencia debe ser interpretado como excluyente o limitante a +cualquier licencia implicada u otras defensas a la violación que puedan hacerse +disponibles para usted bajo la ley de patentes aplicables. + +12. No Condicionamiento de la Libertad de Terceros + +Si a usted le son impuestas condiciones que contravienen las estipuladas en la +presente Licencia (ya sea por orden judicial, acuerdo u otros), no quedará +eximido de cumplir las condiciones de esta Licencia. Si usted no puede +transmitir una obra amparada cumpliendo sus obligaciones con esta Licencia, +entonces no podrá transmitirla de ninguna forma. Por ejemplo, si usted se +compromete con términos que le obligan a obtener derechos por la transmisión +que terceros a los cuales haya transmitido la obra amparada pudieran realizar, +la única forma de satisfacer ambos condicionantes y esta Licencia es abstenerse +completamente de transmitir el Programa. + +13. Versiones Actualizadas de esta Licencia + +La ADSIB puede publicar versiones revisadas y/o nuevas de la LPG - Bolivia. +Cada nueva versión será similar en espíritu a la versión actual, pero puede +diferir en detalles para abordar nuevos problemas o preocupaciones. + +Cada versión recibe un número de versión distintivo. Si el Programa especifica +que cierta versión numerada de la Licencia General Pública Bolivia o cualquier +versión posterior se aplica a él, usted tiene la opción de seguir los términos +y condiciones de esa versión numerada o de cualquier versión posterior +publicada por la ADSIB. Si el Programa no especifica un número de versión de la +LPG - Bolivia, usted puede escoger cualquier versión publicada por la ADSIB. + +Si el Programa especifica que un apoderado/representante puede decidir qué +versiones de la LPG - Bolivia pueden aplicarse en el futuro, la declaración +pública de aceptación que el apoderado/representante haga de una versión le +autoriza a usted con carácter permanente a elegir esa versión para el Programa. + +Las versiones posteriores de la Licencia pueden darle permisos adicionales o +diferentes. No obstante, no se impone a ningún autor o titular de los derechos +de autor obligaciones adicionales como resultado de su elección de seguir una +versión posterior. + +14. Ausencia de Garantía + +EL PROGRAMA NO TIENE GARANTÍA ALGUNA, HASTA LOS LÍMITES PERMITIDOS POR LAS +LEYES APLICABLES. SALVO CUANDO SE ESTABLEZCA LO CONTRARIO POR ESCRITO, LOS +TITULARES DE LOS DERECHOS DE AUTOR (“COPYRIGHT”) Y/O TERCEROS PROPORCIONAN EL +PROGRAMA “TAL CUAL” SIN GARANTÍAS DE NINGÚN TIPO, BIEN SEAN EXPLÍCITAS O +IMPLÍCITAS, INCLUYENDO, PERO NO LIMITADO A, LAS GARANTÍAS IMPLÍCITAS DE +COMERCIALIZACIÓN Y APTITUD PARA UN PROPÓSITO PARTICULAR. USTED ASUMIRÁ +CUALQUIER RIESGO RELATIVO A LA CALIDAD Y RENDIMIENTO DEL PROGRAMA. SI EL +PROGRAMA FUESE DEFECTUOSO, USTED ASUMIRÁ CUALQUIER COSTE DE SERVICIO, +REPARACIÓN O CORRECCIÓN. + +15. Límite de responsabilidad + +EN NINGÚN CASO, SALVO REQUERIMIENTO POR LEYES APLICABLES O MEDIANTE ACUERDO POR +ESCRITO NINGÚN TITULAR DE LOS DERECHOS DE AUTOR (“COPYRIGHT”), O NINGÚN TERCERO +QUE MODIFIQUE Y/O DISTRIBUYA EL PROGRAMA SEGÚN LO INDICADO ANTERIORMENTE, PODRÁ +HACERLE A USTED RESPONSABLE DE DAÑO ALGUNO, INCLUYENDO CUALQUIER DAÑO GENERAL, +ESPECIAL, OCASIONAL O DERIVADO QUE SURJA DEL USO O LA INCAPACIDAD DE USO DEL +PROGRAMA (INCLUYENDO PERO SIN LIMITARSE A LA PÉRDIDA DE DATOS O LA PRESENTACIÓN +NO PRECISA DE LOS MISMOS O A PÉRDIDAS SUFRIDAS POR USTED O TERCEROS O AL FALLO +DEL PROGRAMA AL INTERACTUAR CON OTROS PROGRAMAS), INCLUSO SI DICHO TITULAR O UN +TERCERO HA SIDO ADVERTIDO DE LA POSIBILIDAD DE TALES DAÑOS. + +16. Interpretación de las Cláusulas 14 y 15 + +Si el descargo de responsabilidad de garantía y el límite de responsabilidad +proporcionado anteriormente no tiene efectos legales de acuerdo a sus términos, +los juzgados deberán aplicar la ley local que más se asemeje a una renuncia +absoluta de la responsabilidad civil concerniente al Programa, a menos que una +garantía o una asunción de responsabilidad acompañe a la copia del Programa +como resultado del pago de una tasa. + +17. Del Licenciamiento GNU GPL. + +La presente licencia ha sido traducida y adaptada para la publicación y +distribución de software libre por parte de las entidades públicas del Estado +Plurinacional de Bolivia en el Repositorio Estatal de Software Libre, conforme +a lo establecido por la Ley No. 164 y el D.S. 1793, y busca ser lo más fiel +posible a la letra y espíritu de la GNU GPL. No obstante, como salvaguarda, +todo usuario esta autorizado a licenciar bajo la GNU GPL, publicada de forma +oficial por la Fundación para el Software Libre en su página web www.fsf.org, +cualquier obra que reciba bajo la presente licencia, según la legislación legal +correspondiente. + + FIN DE TÉRMINOS Y CONDICIONES diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7b9fd5c --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +## Sistema de documentos administrativos (Plantillas) + +1. Objetivos del sistema + + a. Objetivo Principal + El objetivo del sistema de documentos administrativos es tener una mejor administración de los documentos generados en la entidad, mediante el uso de tecnologías “open source” para la generación dinámica de documentos en base a plantillas configurables. + + b. Objetivos Secundarios + + - Desarrollar un motor de plantillas que permita la configuración de documentos. + - Desarrollar un módulo de asignación y control de CITE’s, basados por unidad y tipo de documento + - Desarrollar módulo de historicos que permite obtener informacion sobre el flujo de un documento + - Desarrollar los medios que permitan a un documento seguir los flujos establecidos. + - Desarrollar módulo de presupuesto, para el control de las partidas presupuestarias + +2. Tecnologías Utilizadas + + Las Tecnologías utilizadas en el desarrollo de sistema son : + - NodeJS como entorno base de desarrollo para ambos casos. + + BACKEND: + - ExpressJS como servidor de aplicaciones web. + - PostgreSQL como gestor de bases de datos. + - Sequelize como ORM(Object-Relational mapping). + - Passport JWT como mecanismos de autenticación. + - Babel compilador de ECMA6 a ECMA5 + - MomentJS manejador de la generacion de datos tipo fecha,hora,segundos,etc. + - Uuid(v4) generador aleatorio de caracteres. + - helmet como herramienta de configuración de seguridad. + + FRONTEND: + - Gulp como medio de automatización de tareas. + - Angular(v1.5) como entorno base + - Angular-Material como medio de desarrollo de la interfaz de usuario(maquetación) + - Angular-Formly como generador de componentes(Plantilla) + - html como herramienta de maquetación web + - css como herramienta de estilos + +3. Autenticación + + La autenticación se puede configurar: + - Haciendo uso del servicio de autenticación de Ciudadanía Digital. + - Haciendo uso del servicio de autenticación LDAP. + - Haciendo uso de la autenticación del sistema. + + Las tres opciones son excluyentes. + +4. Firma digital + + Para darle validez a toda la documentación generada en el sistema, la misma deberá ser firmada por los actores de cada documento. Para este efecto se usará FIRMATIC (Ver documentación en el repositorio) + +5. Frontend + + Este proyecto depende directamente de un frontend cuyo código se halla en este mismo repositorio (revise el proyecto_plantillas_frontend) + +6. Instalación del backend + + Para la instalación del proyecto backend revise el archivo [INSTALL.md](INSTALL.md). + Es importante mencionar que el proyecto backend debe ser instalado antes que el frontend. + +7. Manual de usuario + + El manual de usuario se encuentra en la carpeta ***docs*** del presente proyecto. \ No newline at end of file diff --git a/README_MODULO_PRESUPUESTO.md b/README_MODULO_PRESUPUESTO.md new file mode 100644 index 0000000..6a3e052 --- /dev/null +++ b/README_MODULO_PRESUPUESTO.md @@ -0,0 +1,39 @@ +## DESARROLLO +Para realizar un control integral del presupuesto se desarrollo el "__Módulo de Presupuesto__" en el sistema de Plantillas el cual, esta disponible en los roles de “_Configurador de Plantillas_” y “_Usuario_” a continuación se describe las opciones disponibles: + +1. ### ROL DE CONFIGURADOR DE PLANTILLAS + + En el Menú de creación de Plantillas se habilitara un componente web llamado "__Caja chica__", que debe ser insertado en la plantilla el cual contiene las siguientes modalidades de funcionamiento: + - GESTIÓN DE PARTIDAS: Habilita al componente para registrar el presupuesto inicial de determinadas partidas presupuestarias y/o las modificaciones presupuestarias a las mismas. + - COMPROMETIDO: Habilita al componente para registrar presupuesto comprometido. + - PAGADO: Habilita al componente para pagar partidas comprometidas. + +2. ### ROL DE USUARIO + + Para los usuarios del sistema de plantillas, una vez ingresando al sistema se le mostraran las 3 nuevas plantillas con una modalidad específica realizada por el configurador de Plantillas, a continuación se describen las modalidades: + + #### GESTIÓN DE PARTIDAS PRESUPUESTARIAS + + Seleccionando las opción de: + - INICIAR PARTIDAS: Debe llenar los datos de Partida (Número de la Partida Prespuestaria), Descripción (Nombre Referencial de la Partida) y Monto Inicial, en el cual tiene una validación para que no se pueda agregar la misma partida ya iniciada. + - MODIFICAR PARTIDAS: Debe agregar una Partida mediante el buscador de Partidas Presupuestarias, posteriormente llenar la Descripción y Monto. El Monto introducido es la afectación de adición (Valores Positivos) o resta (Valores Negativos) a la Partida Seleccionada, donde la validación condiciona a que la partida inicial o actual no tenga valor negativo después de una resta. + + #### COMPROMETIENDO PRESUPUESTO + + Con el buscador de partidas el usuario debe seleccionar las partidas a ser comprometidas en el documento, posteriormente puede agregar un _detalle_ y un _monto positivo_. El sistema automáticamente validará que no se pueda comprometer más allá del presupuesto actual de una partida. + + Se puede crear comprometidos de dos tipos: + - SIMPLE: Opción por defecto, el valor comprometido se cerrará con un solo pago si queda saldo este será transferido al presupuesto de la partida actual. + - MÚLTIPLE: Con esta opción el valor comprometido se cerrará tras múltiples pagos, para ello seleccionar la opción _Pagado múltiple_, + + #### PAGANDO PRESUPUESTO + + El usuario con el buscador de Documentos por CITE, debe seleccionar un documentos donde comprometió presupuesto y el sistema agregará de manera inmediata las partidas comprometidas que no fueron pagadas o finalizadas de dicho documento, posteriormente en la columna _Pagado_ se introducirá + los montos a pagar. + + En el caso de Pago Múltiple, un pago múltiple sera finalizado cuando se establezca un pago de valor 0. + + #### REVERSIÓN DE PRESUPUESTO + + Para realizar una reversión de un valor comprometido de pago simple o múltiple, se debe realizar un pago del valor comprometido con monto de valor 0. + \ No newline at end of file diff --git a/UPDATE.md b/UPDATE.md new file mode 100644 index 0000000..5073838 --- /dev/null +++ b/UPDATE.md @@ -0,0 +1,32 @@ +# .:: Plantillas Formly Backend ::. + +A continuación se detalla la actualización de la aplicación. + + +## A. ACTUALIZACIÓN DE LA APLICACIÓN + +Ejecutar el siguiente comando en el directorio : + +``` +git pull origin master +``` +## B. INSTALACION DE DEPENDENCIAS + +Ejecutar el siguiente comando en el directorio : + +``` +npm install +``` + +## C. APLICAR LAS MIGRACIONES +Ejecutar si fuera necesario, + +``` +npm run migrar +``` + +## D. REINICIAR EL SERVICIO + +``` +pm2 restart plantillas-backend +``` diff --git a/asignar-admin.js b/asignar-admin.js new file mode 100644 index 0000000..7768b06 --- /dev/null +++ b/asignar-admin.js @@ -0,0 +1,81 @@ +/** +Archivo con los metodos necesarios para la asignacion de un administrador +introducido por parametro e inactivacion del administrador por defecto. + */ + +const Promise = require('bluebird'); +const {Client} = require('pg'); +const config = require(`${__dirname}/src/config/config`)().database; + +console.log('Revisnado el config obtenido', config); +const configDB = `${config.params.dialect}://${config.username}:${config.password}@${config.params.host}:${config.params.port}/${config.name}`; + +const pgCliente = new Client(configDB); + +pgCliente.connect(); +const usuario = JSON.parse(process.env.npm_config_argv).remain[0]; +const fecha = new Date(); +const fechaEnviar = `${fecha.getFullYear()}-${fecha.getMonth()+1}-${fecha.getDate()}`; + +// Inactiva al usuario admin por defecto. +ejecutarConsulta("UPDATE usuario SET estado = 'INACTIVO' WHERE usuario = 'admin';") + +.then(() => + + // Busca el identificador del usuario. + ejecutarConsulta(`SELECT id_usuario from usuario where usuario ='${usuario}'`) + .then(pRespuestaUsuario => { + + if(pRespuestaUsuario.length>0){ + // Valida si el usuario ya posee el rol. + return ejecutarConsulta(`SELECT fid_usuario FROM usuario_rol WHERE fid_usuario=${pRespuestaUsuario[0].id_usuario} AND fid_rol=1;`) + .then(pRespuestaRol => { + // Si el usuario ya posee el rol administrador. + if(pRespuestaRol.length>0){ + console.log(`El usuario ${usuario} ya cuenta con los privilegios de administrador.`); + pgCliente.end(); + } + // Si no posee el rol administrador. + else{ + // Crea la relacion usuario-rol para otorgar rol administrador. + return ejecutarConsulta(`INSERT INTO usuario_rol(fid_usuario, fid_rol, estado, _usuario_creacion, _fecha_creacion,_fecha_modificacion) + VALUES (${pRespuestaUsuario[0].id_usuario}, 1, 'ACTIVO', 1,'${fechaEnviar}','${fechaEnviar}');`) + .then(pRespuestaCrear => { + console.log(`El usuario ${usuario}, ahora posee los privilegios de administrador.`); + pgCliente.end(); + }) + } + }) + } + else { + console.log(`El usuario ${usuario} no existe, verifique la informacion introducida.`); + pgCliente.end(); + } + }) + +) +.catch(pError => { + console.log("Error al ejecutar la consulta", pError); + pgCliente.end(); +}) + +/** + Funcion que ejecuta una promesa. + @param {pConsulta} Texto Cadena que contiene la consulta a ejecutar. + @return retorna una promesa. + */ +function ejecutarConsulta(pConsulta){ + + return new Promise((resolve,reject) => { + pgCliente.query(pConsulta) + .then(resp => { + if(resp.command == 'UPDATE') (resp.rowCount ==1)? resolve(true):resolve(false); + else if(resp.command == 'INSERT') (resp.rowCount ==1)?resolve(true):resolve(false); + else resolve(resp.rows); + }) + .catch(errorQuery => { + console.log('Error en el query', errorQuery); + resolve(false); + }); + }); +} diff --git a/codigo_estados_http.md b/codigo_estados_http.md new file mode 100644 index 0000000..4e81387 --- /dev/null +++ b/codigo_estados_http.md @@ -0,0 +1,82 @@ +# Estados HTTP +## 1xx Respuestas Informativas: + +| Código | Estado | Descripción | +| :-------------: |:-------------:| :-----| +|100| Continuar | El navegador puede continuar realizando su petición (se utiliza para indicar que la primera parte de la petición del navegador se ha recibido correctamente). | +|101|Conmutación de protocolos | El servidor acepta el cambio de protocolo propuesto por el navegador (puede ser por ejemplo un cambio de HTTP 1.0 a HTTP 1.1). | +|102| Procesando (WebDav) | EL servidor está procesando la petición del navegador pero todavía no ha terminado (esto evita que el navegador piense que la petición se ha perdido cuando no recibe ninguna respuesta).| +|103| Punto de control| Se va a reanudar una petición POST o PUT que fue abortada previamente.| + +## 2xx Peticiones Correctas: +| Código | Estado | Descripción | +| :-------------: |:-------------:| :-----| +|200 | OK | Respuesta estándar para peticiones correctas.| +|201|Creado|La petición ha sido completada y ha resultado en la creación de un nuevo recurso.| +|202|Aceptado| La petición ha sido aceptada para procesamiento, pero este no ha sido completado. La petición eventualmente pudiere o ser satisfecha, ya que podría ser no permitida o prohibida cuando el procesamiento tenga lugar.| +|203|Información no autorizada|La petición se ha completado con éxito, pero su contenido no se ha obtenido de la fuente originalmente solicitada sino de otro servidor.| +|204|Sin contenido|La petición se ha completado con éxito pero su respuesta no tiene ningún contenido( la respuesta sí que puede incluir información en sus cabeceras HTTP).| +|205|Reiniciar contenido|La petición se ha completado con éxito, pero su respuesta no tiene contenidos y además , el navegador tiene que inicializar la pagina desde la que se realizó la petición(uso en paginas con formularios cuyo contenido debe borrarse después de que el usuario lo envié).| +|206|Contenido parcial|La petición servirá parcialmente el contenido solicitado. Esta característica es utilizada por herramientas de descarga como wget para continuar la transferencia de descargas anteriormente interrumpidas o para dividir una descarga y procesar las partes simultáneamente.| +|207|Multi-estado WebDav|El cuerpo del mensaje que sigue es un mensaje xml y puede contener algún número e códigos de respuesta separados, dependiendo de cuántas sub-peticiones sean hechas.| +|208|Ya registrado WebDav|El listado de elementos dav ya se notifico previamente, por lo que no se van a volver a listar.| + +## 3xx Redirecciones: +| Código | Estado | Descripción | +| :-------------: |:-------------:| :-----------| +|300|Múltiples opciones|Indica opciones múltiples para el URI que el cliente podría seguir. Ejemplo, representar distintas opciones de formato para vídeo, listar archivos con distintas extensiones o word sense disambiguation.| +|301|Movido permanentemente|Esta y todas las peticiones futuras deberían ser dirigidas a la URI dada.| +|302|Encontrado|Indica el estado sobre el re-direcionamiento de una pagina o documento web.| +|303|Ver otros|La respuesta a la petición puede ser encontrada bajo otra URI utilizando el método GET.(desde HTTP 1.1).| +|304|Sin modificación|Indica que la petición a la URL no ha sido modificada desde que fue requerida por última vez. Típicamente el cliente HTTP provee un encabezado como if-Modified-Since para indicar una fecha y hora actual contra el cual el servidor pueda comparar.| +|305|Use proxy|El documento solicitado debería recuperarse mediante el proxy listado en la cabecera “Location”. Muchos clientes HTTP no se apegan a este estándar por motivos de seguridad; Estas respuestas solo deben generarse por servidores de origen.| +|307|Redirección temporal|Se trata de una redirección que debería haber sido hecha con otra URI, sin embargo aún puede ser procesada con la URI proporcionada. En contraste con la 303 el método no debería ser cambiado cuando el cliente repita la solicitud.| +|308|Redirección permanente|El recurso solicitado por el navegador se encuentra en otro lugar y este cambio es permanente. A diferencia del 301, no se permite cambiar el método HTTP para la nueva petición.| + + +## 4xxx Errores del Cliente: +| Código | Estado | Descripción | +| :-------------: |:-------------:| :-----------| +|400|Mala solicitud|La solicitud contiene sintaxis errónea y no debería repetirse.| +|401|No autorizado|Similar al 403, pero específicamente para su uso cuando la autentificación es posible pero ha fallado o aun no ha sido provista.| +|402|Pago obligatorio|La intención original era que este código pudiese ser usado como parte de alguna forma o esquema de dinero electrónico - - nunca se lo uso.| +|403|Prohibido|La solicitud fue legal, pero el servidor rehúsa responderla dado que el cliente no tiene los privilegios para hacerla.| +|404|No se encontró|Recurso no encontrado. Se utiliza cuando el servidor web no encuentra la pagina.| +|405|Método no permitido|Una petición fue hecha a una URI utilizando un método de solicitud no soportado por dicha URI.| +|406|No aceptable|El servidor no es capaz de devolver los datos en ninguno de los formatos aceptados por el cliente, indicados por éste en la cabecera “Accept” de la petición.| +|407|Requiere autenticación de proxy|Parecido al 401, pero el cliente deberá primero autenticarse con el proxy.| +|408|Tiempo de solicitud agotado|El cliente falló al continuar la petición. Excepto durante la ejecución de vídeos adobe flash cuando solo significa que el usuario cerro la ventana de vídeo o se movió a otro.| +|409|Conflicto|Indica que la solicitud no pudo ser procesada debido a un conflicto con el estado actual del recurso que esta identifica.| +|410|Sin disponibilidad|Indica que el recurso solicitado ya no esta disponible y no lo estará de nuevo. Deberia ser utilizado cuando un recurso ha sido quitado de forma permanente.| +|411|Requiere longitud de contenido|El servidor rechaza la petición del navegador porque no incluye la cabecera “Content-Length” adecuada.| +|412|Error de Pre-condicion|El servidor no es capaz de cumplir con algunas de las condiciones impuestas por el navegador.| +|413|Entidad de solicitud demasiado grande|La petición es demasiado grande y por ese motivo el servidor no la procesa.| +|414|URI de solicitud demasiado larga|La URI de la petición del navegador es demasiado grande y por ese motivo el servidor no la procesa.| +|415|Tipo de medio no soportado|La petición del navegador tiene un formato que no entiende el servidor.| +|416|Pedido fuera de rango|El cliente a preguntado por una parte de un archivo, pero el servidor no puede proporcionar esa parte.| +|417|Sin expectativa|La petición del navegador no se procesa porque el servidor no es capaz de cumplir con los requerimientos de la cabecera “Expect”.| +|418|Soy una Tetera|Soy una tetera, sirve para que no se prepare café en un a tetera.| +|422|Entidad WebDav No Procesable|La solicitud está bien formada pero fue imposible seguirla debido a errores semánticos.| +|423|WebDav bloqueado|El recurso al que se está teniendo acceso está bloqueado.| +|424|Fallo en la dependencia WebDav|La solicitud falló debido a una falla en la solicitud previa.| +|426|Requiere actualización|El cliente debería cambiarse a TLS/1.0| +|428| Condición previa Necesaria|El Servidor requiere que la petición del navegador sea condicional( Evita problemas producidos al modificar con PUT un recurso que ha sido modificado por otra parte).| +|429|Muchas solicitudes|Hay muchas conexiones desde esta dirección de internet.| +|431|Campos de encabezado de solicitud demasiado grande|El servidor no puede procesar la petición porque una de las cabeceras de la petición es demasiado grande. Este error también se produce cuando la suma del tamaño de todas las peticiones es demasiado grande.| +|451|No disponible por razones legales|El contenido ha sido eliminado como consecuencia de una orden judicial o sentencia emitida por un tribunal.| + +## 5xxx Errores de Servidor: +| Código | Estado | Descripción | +| :-------------: |:-------------:| :-----------| +|500|Error interno del servidor|Mensaje genérico "server is confused". Normalmente es el resultado de programas CGI o servlets que se quedan colgados o retornan cabeceras mal formateadas.| +|501|No implementado|El servidor no soporta alguna funcionalidad necesaria para responder a la solicitud del navegador.| +|502|Error en la puerta de enlace|El servidor está actuando de proxy o gateway y ha recibido una respuesta inválida del otro servidor, por lo que no puede responder adecuadamente a la petición del navegador.| +|503|Servicio no disponible|El Servidor no puede responder a la petición del navegador porque esta congestionado o esta realizando tareas de mantenimiento.| +|504|Tiempo de espera de Gateway|El servidor está actuando de proxy o gateway y no ha recibido a tiempo una respuesta del otro servidor.| +|505|Versión HTTP no soportada|El servidor no soporta o no quiere soportar la versión del protocolo HTTP utilizada en la petición del navegador.| +|506|Variante de negocio|El servidor a detectado una referencia circular al procesar la parte de la negociación del contenido de la petición.| +|507|Insuficiente espacio de almacenamiento WebDav|El servidor no puede crear o modificar el recurso solicitado porque no hay suficiente espacio de almacenamiento libre.| +|508|Bucle WebDav detectado|La petición no se puede procesar porque el servidor ha encontrado un bucle infinito al intentar procesarla.| +|509|Limite de ancho de banda|Limite de ancho de banda excedido – CÓDIGO NO OFICIAL.| +|510|No extendido|La petición del navegador debe añadir mas extensiones para que el servidor pueda procesarla.| +|511|Requiere autentificación en la red|El navegador debe autenticarse para poder realizar peticiones, se los usa con los portales cautivos que obligan a autenticarse antes de navegar.| diff --git a/docs/ManualUsuarioRol.odt b/docs/ManualUsuarioRol.odt new file mode 100644 index 0000000..bf54e55 Binary files /dev/null and b/docs/ManualUsuarioRol.odt differ diff --git a/docs/ManualUsuarioRol.pdf b/docs/ManualUsuarioRol.pdf new file mode 100644 index 0000000..eeda867 Binary files /dev/null and b/docs/ManualUsuarioRol.pdf differ diff --git a/docs/Modelo_ER_Plantillas.png b/docs/Modelo_ER_Plantillas.png new file mode 100644 index 0000000..300fbfb Binary files /dev/null and b/docs/Modelo_ER_Plantillas.png differ diff --git a/docs/arquitectura.png b/docs/arquitectura.png new file mode 100644 index 0000000..7c2ca12 Binary files /dev/null and b/docs/arquitectura.png differ diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..602344d --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +cp ${CONFIG_JSON_PATH} /home/node/app/src/config/config.json +cp ${CONFIG_JS_PATH} /home/node/app/src/config/config.js + +exec "$@" diff --git a/index.js b/index.js new file mode 100644 index 0000000..5c07105 --- /dev/null +++ b/index.js @@ -0,0 +1,20 @@ +const express = require("express"); +const consign = require("consign"); +const app= express(); + +console.log("inicio"); +consign() + .include("src/config/config.js") + .then("src/lib/util.js") + .then("src/lib/firma.js") + .then("src/lib/archivos.js") + .then("src/db.js") + .then("src/openid.js") + .then("src/auth.js") + .then("src/lib/middlewares.js") + .then("src/bl/seguridad/autorizacion.dao.js") + .then("src/bl/seguridad/autorizacion.controller.js") + .then("src/routes") + .then("src/lib/boot.js") + .into(app); +module.exports=app; diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..0438b79 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "commonjs" + } +} \ No newline at end of file diff --git a/librerias_frontend_extra/pdf.js-viewer/pdf.worker.js b/librerias_frontend_extra/pdf.js-viewer/pdf.worker.js new file mode 100644 index 0000000..8c59e5e --- /dev/null +++ b/librerias_frontend_extra/pdf.js-viewer/pdf.worker.js @@ -0,0 +1,51085 @@ +/* Copyright 2017 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define("pdfjs-dist/build/pdf.worker", [], factory); + else if(typeof exports === 'object') + exports["pdfjs-dist/build/pdf.worker"] = factory(); + else + root["pdfjs-dist/build/pdf.worker"] = root.pdfjsDistBuildPdfWorker = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __w_pdfjs_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __w_pdfjs_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __w_pdfjs_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __w_pdfjs_require__.c = installedModules; +/******/ +/******/ // identity function for calling harmony imports with the correct context +/******/ __w_pdfjs_require__.i = function(value) { return value; }; +/******/ +/******/ // define getter function for harmony exports +/******/ __w_pdfjs_require__.d = function(exports, name, getter) { +/******/ if(!__w_pdfjs_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __w_pdfjs_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __w_pdfjs_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __w_pdfjs_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __w_pdfjs_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __w_pdfjs_require__(__w_pdfjs_require__.s = 37); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) { +var compatibility = __w_pdfjs_require__(36); +var globalScope = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this; +var FONT_IDENTITY_MATRIX = [ + 0.001, + 0, + 0, + 0.001, + 0, + 0 +]; +var TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; +var ImageKind = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 +}; +var AnnotationType = { + TEXT: 1, + LINK: 2, + FREETEXT: 3, + LINE: 4, + SQUARE: 5, + CIRCLE: 6, + POLYGON: 7, + POLYLINE: 8, + HIGHLIGHT: 9, + UNDERLINE: 10, + SQUIGGLY: 11, + STRIKEOUT: 12, + STAMP: 13, + CARET: 14, + INK: 15, + POPUP: 16, + FILEATTACHMENT: 17, + SOUND: 18, + MOVIE: 19, + WIDGET: 20, + SCREEN: 21, + PRINTERMARK: 22, + TRAPNET: 23, + WATERMARK: 24, + THREED: 25, + REDACT: 26 +}; +var AnnotationFlag = { + INVISIBLE: 0x01, + HIDDEN: 0x02, + PRINT: 0x04, + NOZOOM: 0x08, + NOROTATE: 0x10, + NOVIEW: 0x20, + READONLY: 0x40, + LOCKED: 0x80, + TOGGLENOVIEW: 0x100, + LOCKEDCONTENTS: 0x200 +}; +var AnnotationFieldFlag = { + READONLY: 0x0000001, + REQUIRED: 0x0000002, + NOEXPORT: 0x0000004, + MULTILINE: 0x0001000, + PASSWORD: 0x0002000, + NOTOGGLETOOFF: 0x0004000, + RADIO: 0x0008000, + PUSHBUTTON: 0x0010000, + COMBO: 0x0020000, + EDIT: 0x0040000, + SORT: 0x0080000, + FILESELECT: 0x0100000, + MULTISELECT: 0x0200000, + DONOTSPELLCHECK: 0x0400000, + DONOTSCROLL: 0x0800000, + COMB: 0x1000000, + RICHTEXT: 0x2000000, + RADIOSINUNISON: 0x2000000, + COMMITONSELCHANGE: 0x4000000 +}; +var AnnotationBorderStyleType = { + SOLID: 1, + DASHED: 2, + BEVELED: 3, + INSET: 4, + UNDERLINE: 5 +}; +var StreamType = { + UNKNOWN: 0, + FLATE: 1, + LZW: 2, + DCT: 3, + JPX: 4, + JBIG: 5, + A85: 6, + AHX: 7, + CCF: 8, + RL: 9 +}; +var FontType = { + UNKNOWN: 0, + TYPE1: 1, + TYPE1C: 2, + CIDFONTTYPE0: 3, + CIDFONTTYPE0C: 4, + TRUETYPE: 5, + CIDFONTTYPE2: 6, + TYPE3: 7, + OPENTYPE: 8, + TYPE0: 9, + MMTYPE1: 10 +}; +var VERBOSITY_LEVELS = { + errors: 0, + warnings: 1, + infos: 5 +}; +var CMapCompressionType = { + NONE: 0, + BINARY: 1, + STREAM: 2 +}; +var OPS = { + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotations: 78, + endAnnotations: 79, + beginAnnotation: 80, + endAnnotation: 81, + paintJpegXObject: 82, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91 +}; +var verbosity = VERBOSITY_LEVELS.warnings; +function setVerbosityLevel(level) { + verbosity = level; +} +function getVerbosityLevel() { + return verbosity; +} +function info(msg) { + if (verbosity >= VERBOSITY_LEVELS.infos) { + console.log('Info: ' + msg); + } +} +function warn(msg) { + if (verbosity >= VERBOSITY_LEVELS.warnings) { + console.log('Warning: ' + msg); + } +} +function deprecated(details) { + console.log('Deprecated API usage: ' + details); +} +function error(msg) { + if (verbosity >= VERBOSITY_LEVELS.errors) { + console.log('Error: ' + msg); + console.log(backtrace()); + } + throw new Error(msg); +} +function backtrace() { + try { + throw new Error(); + } catch (e) { + return e.stack ? e.stack.split('\n').slice(2).join('\n') : ''; + } +} +function assert(cond, msg) { + if (!cond) { + error(msg); + } +} +var UNSUPPORTED_FEATURES = { + unknown: 'unknown', + forms: 'forms', + javaScript: 'javaScript', + smask: 'smask', + shadingPattern: 'shadingPattern', + font: 'font' +}; +function isSameOrigin(baseUrl, otherUrl) { + try { + var base = new URL(baseUrl); + if (!base.origin || base.origin === 'null') { + return false; + } + } catch (e) { + return false; + } + var other = new URL(otherUrl, base); + return base.origin === other.origin; +} +function isValidProtocol(url) { + if (!url) { + return false; + } + switch (url.protocol) { + case 'http:': + case 'https:': + case 'ftp:': + case 'mailto:': + case 'tel:': + return true; + default: + return false; + } +} +function createValidAbsoluteUrl(url, baseUrl) { + if (!url) { + return null; + } + try { + var absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url); + if (isValidProtocol(absoluteUrl)) { + return absoluteUrl; + } + } catch (ex) { + } + return null; +} +function shadow(obj, prop, value) { + Object.defineProperty(obj, prop, { + value: value, + enumerable: true, + configurable: true, + writable: false + }); + return value; +} +function getLookupTableFactory(initializer) { + var lookup; + return function () { + if (initializer) { + lookup = Object.create(null); + initializer(lookup); + initializer = null; + } + return lookup; + }; +} +var PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; +var PasswordException = function PasswordExceptionClosure() { + function PasswordException(msg, code) { + this.name = 'PasswordException'; + this.message = msg; + this.code = code; + } + PasswordException.prototype = new Error(); + PasswordException.constructor = PasswordException; + return PasswordException; +}(); +var UnknownErrorException = function UnknownErrorExceptionClosure() { + function UnknownErrorException(msg, details) { + this.name = 'UnknownErrorException'; + this.message = msg; + this.details = details; + } + UnknownErrorException.prototype = new Error(); + UnknownErrorException.constructor = UnknownErrorException; + return UnknownErrorException; +}(); +var InvalidPDFException = function InvalidPDFExceptionClosure() { + function InvalidPDFException(msg) { + this.name = 'InvalidPDFException'; + this.message = msg; + } + InvalidPDFException.prototype = new Error(); + InvalidPDFException.constructor = InvalidPDFException; + return InvalidPDFException; +}(); +var MissingPDFException = function MissingPDFExceptionClosure() { + function MissingPDFException(msg) { + this.name = 'MissingPDFException'; + this.message = msg; + } + MissingPDFException.prototype = new Error(); + MissingPDFException.constructor = MissingPDFException; + return MissingPDFException; +}(); +var UnexpectedResponseException = function UnexpectedResponseExceptionClosure() { + function UnexpectedResponseException(msg, status) { + this.name = 'UnexpectedResponseException'; + this.message = msg; + this.status = status; + } + UnexpectedResponseException.prototype = new Error(); + UnexpectedResponseException.constructor = UnexpectedResponseException; + return UnexpectedResponseException; +}(); +var NotImplementedException = function NotImplementedExceptionClosure() { + function NotImplementedException(msg) { + this.message = msg; + } + NotImplementedException.prototype = new Error(); + NotImplementedException.prototype.name = 'NotImplementedException'; + NotImplementedException.constructor = NotImplementedException; + return NotImplementedException; +}(); +var MissingDataException = function MissingDataExceptionClosure() { + function MissingDataException(begin, end) { + this.begin = begin; + this.end = end; + this.message = 'Missing data [' + begin + ', ' + end + ')'; + } + MissingDataException.prototype = new Error(); + MissingDataException.prototype.name = 'MissingDataException'; + MissingDataException.constructor = MissingDataException; + return MissingDataException; +}(); +var XRefParseException = function XRefParseExceptionClosure() { + function XRefParseException(msg) { + this.message = msg; + } + XRefParseException.prototype = new Error(); + XRefParseException.prototype.name = 'XRefParseException'; + XRefParseException.constructor = XRefParseException; + return XRefParseException; +}(); +var NullCharactersRegExp = /\x00/g; +function removeNullCharacters(str) { + if (typeof str !== 'string') { + warn('The argument for removeNullCharacters must be a string.'); + return str; + } + return str.replace(NullCharactersRegExp, ''); +} +function bytesToString(bytes) { + assert(bytes !== null && typeof bytes === 'object' && bytes.length !== undefined, 'Invalid argument for bytesToString'); + var length = bytes.length; + var MAX_ARGUMENT_COUNT = 8192; + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + var strBuf = []; + for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + var chunk = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk)); + } + return strBuf.join(''); +} +function stringToBytes(str) { + assert(typeof str === 'string', 'Invalid argument for stringToBytes'); + var length = str.length; + var bytes = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 0xFF; + } + return bytes; +} +function arrayByteLength(arr) { + if (arr.length !== undefined) { + return arr.length; + } + assert(arr.byteLength !== undefined); + return arr.byteLength; +} +function arraysToBytes(arr) { + if (arr.length === 1 && arr[0] instanceof Uint8Array) { + return arr[0]; + } + var resultLength = 0; + var i, ii = arr.length; + var item, itemLength; + for (i = 0; i < ii; i++) { + item = arr[i]; + itemLength = arrayByteLength(item); + resultLength += itemLength; + } + var pos = 0; + var data = new Uint8Array(resultLength); + for (i = 0; i < ii; i++) { + item = arr[i]; + if (!(item instanceof Uint8Array)) { + if (typeof item === 'string') { + item = stringToBytes(item); + } else { + item = new Uint8Array(item); + } + } + itemLength = item.byteLength; + data.set(item, pos); + pos += itemLength; + } + return data; +} +function string32(value) { + return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff); +} +function log2(x) { + var n = 1, i = 0; + while (x > n) { + n <<= 1; + i++; + } + return i; +} +function readInt8(data, start) { + return data[start] << 24 >> 24; +} +function readUint16(data, offset) { + return data[offset] << 8 | data[offset + 1]; +} +function readUint32(data, offset) { + return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0; +} +function isLittleEndian() { + var buffer8 = new Uint8Array(2); + buffer8[0] = 1; + var buffer16 = new Uint16Array(buffer8.buffer); + return buffer16[0] === 1; +} +function isEvalSupported() { + try { + new Function(''); + return true; + } catch (e) { + return false; + } +} +var Uint32ArrayView = function Uint32ArrayViewClosure() { + function Uint32ArrayView(buffer, length) { + this.buffer = buffer; + this.byteLength = buffer.length; + this.length = length === undefined ? this.byteLength >> 2 : length; + ensureUint32ArrayViewProps(this.length); + } + Uint32ArrayView.prototype = Object.create(null); + var uint32ArrayViewSetters = 0; + function createUint32ArrayProp(index) { + return { + get: function () { + var buffer = this.buffer, offset = index << 2; + return (buffer[offset] | buffer[offset + 1] << 8 | buffer[offset + 2] << 16 | buffer[offset + 3] << 24) >>> 0; + }, + set: function (value) { + var buffer = this.buffer, offset = index << 2; + buffer[offset] = value & 255; + buffer[offset + 1] = value >> 8 & 255; + buffer[offset + 2] = value >> 16 & 255; + buffer[offset + 3] = value >>> 24 & 255; + } + }; + } + function ensureUint32ArrayViewProps(length) { + while (uint32ArrayViewSetters < length) { + Object.defineProperty(Uint32ArrayView.prototype, uint32ArrayViewSetters, createUint32ArrayProp(uint32ArrayViewSetters)); + uint32ArrayViewSetters++; + } + } + return Uint32ArrayView; +}(); +exports.Uint32ArrayView = Uint32ArrayView; +var IDENTITY_MATRIX = [ + 1, + 0, + 0, + 1, + 0, + 0 +]; +var Util = function UtilClosure() { + function Util() { + } + var rgbBuf = [ + 'rgb(', + 0, + ',', + 0, + ',', + 0, + ')' + ]; + Util.makeCssRgb = function Util_makeCssRgb(r, g, b) { + rgbBuf[1] = r; + rgbBuf[3] = g; + rgbBuf[5] = b; + return rgbBuf.join(''); + }; + Util.transform = function Util_transform(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; + }; + Util.applyTransform = function Util_applyTransform(p, m) { + var xt = p[0] * m[0] + p[1] * m[2] + m[4]; + var yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [ + xt, + yt + ]; + }; + Util.applyInverseTransform = function Util_applyInverseTransform(p, m) { + var d = m[0] * m[3] - m[1] * m[2]; + var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + return [ + xt, + yt + ]; + }; + Util.getAxialAlignedBoundingBox = function Util_getAxialAlignedBoundingBox(r, m) { + var p1 = Util.applyTransform(r, m); + var p2 = Util.applyTransform(r.slice(2, 4), m); + var p3 = Util.applyTransform([ + r[0], + r[3] + ], m); + var p4 = Util.applyTransform([ + r[2], + r[1] + ], m); + return [ + Math.min(p1[0], p2[0], p3[0], p4[0]), + Math.min(p1[1], p2[1], p3[1], p4[1]), + Math.max(p1[0], p2[0], p3[0], p4[0]), + Math.max(p1[1], p2[1], p3[1], p4[1]) + ]; + }; + Util.inverseTransform = function Util_inverseTransform(m) { + var d = m[0] * m[3] - m[1] * m[2]; + return [ + m[3] / d, + -m[1] / d, + -m[2] / d, + m[0] / d, + (m[2] * m[5] - m[4] * m[3]) / d, + (m[4] * m[1] - m[5] * m[0]) / d + ]; + }; + Util.apply3dTransform = function Util_apply3dTransform(m, v) { + return [ + m[0] * v[0] + m[1] * v[1] + m[2] * v[2], + m[3] * v[0] + m[4] * v[1] + m[5] * v[2], + m[6] * v[0] + m[7] * v[1] + m[8] * v[2] + ]; + }; + Util.singularValueDecompose2dScale = function Util_singularValueDecompose2dScale(m) { + var transpose = [ + m[0], + m[2], + m[1], + m[3] + ]; + var a = m[0] * transpose[0] + m[1] * transpose[2]; + var b = m[0] * transpose[1] + m[1] * transpose[3]; + var c = m[2] * transpose[0] + m[3] * transpose[2]; + var d = m[2] * transpose[1] + m[3] * transpose[3]; + var first = (a + d) / 2; + var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2; + var sx = first + second || 1; + var sy = first - second || 1; + return [ + Math.sqrt(sx), + Math.sqrt(sy) + ]; + }; + Util.normalizeRect = function Util_normalizeRect(rect) { + var r = rect.slice(0); + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + }; + Util.intersect = function Util_intersect(rect1, rect2) { + function compare(a, b) { + return a - b; + } + var orderedX = [ + rect1[0], + rect1[2], + rect2[0], + rect2[2] + ].sort(compare), orderedY = [ + rect1[1], + rect1[3], + rect2[1], + rect2[3] + ].sort(compare), result = []; + rect1 = Util.normalizeRect(rect1); + rect2 = Util.normalizeRect(rect2); + if (orderedX[0] === rect1[0] && orderedX[1] === rect2[0] || orderedX[0] === rect2[0] && orderedX[1] === rect1[0]) { + result[0] = orderedX[1]; + result[2] = orderedX[2]; + } else { + return false; + } + if (orderedY[0] === rect1[1] && orderedY[1] === rect2[1] || orderedY[0] === rect2[1] && orderedY[1] === rect1[1]) { + result[1] = orderedY[1]; + result[3] = orderedY[2]; + } else { + return false; + } + return result; + }; + Util.sign = function Util_sign(num) { + return num < 0 ? -1 : 1; + }; + var ROMAN_NUMBER_MAP = [ + '', + 'C', + 'CC', + 'CCC', + 'CD', + 'D', + 'DC', + 'DCC', + 'DCCC', + 'CM', + '', + 'X', + 'XX', + 'XXX', + 'XL', + 'L', + 'LX', + 'LXX', + 'LXXX', + 'XC', + '', + 'I', + 'II', + 'III', + 'IV', + 'V', + 'VI', + 'VII', + 'VIII', + 'IX' + ]; + Util.toRoman = function Util_toRoman(number, lowerCase) { + assert(isInt(number) && number > 0, 'The number should be a positive integer.'); + var pos, romanBuf = []; + while (number >= 1000) { + number -= 1000; + romanBuf.push('M'); + } + pos = number / 100 | 0; + number %= 100; + romanBuf.push(ROMAN_NUMBER_MAP[pos]); + pos = number / 10 | 0; + number %= 10; + romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]); + romanBuf.push(ROMAN_NUMBER_MAP[20 + number]); + var romanStr = romanBuf.join(''); + return lowerCase ? romanStr.toLowerCase() : romanStr; + }; + Util.appendToArray = function Util_appendToArray(arr1, arr2) { + Array.prototype.push.apply(arr1, arr2); + }; + Util.prependToArray = function Util_prependToArray(arr1, arr2) { + Array.prototype.unshift.apply(arr1, arr2); + }; + Util.extendObj = function extendObj(obj1, obj2) { + for (var key in obj2) { + obj1[key] = obj2[key]; + } + }; + Util.getInheritableProperty = function Util_getInheritableProperty(dict, name, getArray) { + while (dict && !dict.has(name)) { + dict = dict.get('Parent'); + } + if (!dict) { + return null; + } + return getArray ? dict.getArray(name) : dict.get(name); + }; + Util.inherit = function Util_inherit(sub, base, prototype) { + sub.prototype = Object.create(base.prototype); + sub.prototype.constructor = sub; + for (var prop in prototype) { + sub.prototype[prop] = prototype[prop]; + } + }; + Util.loadScript = function Util_loadScript(src, callback) { + var script = document.createElement('script'); + var loaded = false; + script.setAttribute('src', src); + if (callback) { + script.onload = function () { + if (!loaded) { + callback(); + } + loaded = true; + }; + } + document.getElementsByTagName('head')[0].appendChild(script); + }; + return Util; +}(); +var PageViewport = function PageViewportClosure() { + function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) { + this.viewBox = viewBox; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + var centerX = (viewBox[2] + viewBox[0]) / 2; + var centerY = (viewBox[3] + viewBox[1]) / 2; + var rotateA, rotateB, rotateC, rotateD; + rotation = rotation % 360; + rotation = rotation < 0 ? rotation + 360 : rotation; + switch (rotation) { + case 180: + rotateA = -1; + rotateB = 0; + rotateC = 0; + rotateD = 1; + break; + case 90: + rotateA = 0; + rotateB = 1; + rotateC = 1; + rotateD = 0; + break; + case 270: + rotateA = 0; + rotateB = -1; + rotateC = -1; + rotateD = 0; + break; + default: + rotateA = 1; + rotateB = 0; + rotateC = 0; + rotateD = -1; + break; + } + if (dontFlip) { + rotateC = -rotateC; + rotateD = -rotateD; + } + var offsetCanvasX, offsetCanvasY; + var width, height; + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = Math.abs(viewBox[3] - viewBox[1]) * scale; + height = Math.abs(viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = Math.abs(viewBox[2] - viewBox[0]) * scale; + height = Math.abs(viewBox[3] - viewBox[1]) * scale; + } + this.transform = [ + rotateA * scale, + rotateB * scale, + rotateC * scale, + rotateD * scale, + offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, + offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY + ]; + this.width = width; + this.height = height; + this.fontScale = scale; + } + PageViewport.prototype = { + clone: function PageViewPort_clone(args) { + args = args || {}; + var scale = 'scale' in args ? args.scale : this.scale; + var rotation = 'rotation' in args ? args.rotation : this.rotation; + return new PageViewport(this.viewBox.slice(), scale, rotation, this.offsetX, this.offsetY, args.dontFlip); + }, + convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) { + return Util.applyTransform([ + x, + y + ], this.transform); + }, + convertToViewportRectangle: function PageViewport_convertToViewportRectangle(rect) { + var tl = Util.applyTransform([ + rect[0], + rect[1] + ], this.transform); + var br = Util.applyTransform([ + rect[2], + rect[3] + ], this.transform); + return [ + tl[0], + tl[1], + br[0], + br[1] + ]; + }, + convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) { + return Util.applyInverseTransform([ + x, + y + ], this.transform); + } + }; + return PageViewport; +}(); +var PDFStringTranslateTable = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0x2D8, + 0x2C7, + 0x2C6, + 0x2D9, + 0x2DD, + 0x2DB, + 0x2DA, + 0x2DC, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0x2022, + 0x2020, + 0x2021, + 0x2026, + 0x2014, + 0x2013, + 0x192, + 0x2044, + 0x2039, + 0x203A, + 0x2212, + 0x2030, + 0x201E, + 0x201C, + 0x201D, + 0x2018, + 0x2019, + 0x201A, + 0x2122, + 0xFB01, + 0xFB02, + 0x141, + 0x152, + 0x160, + 0x178, + 0x17D, + 0x131, + 0x142, + 0x153, + 0x161, + 0x17E, + 0, + 0x20AC +]; +function stringToPDFString(str) { + var i, n = str.length, strBuf = []; + if (str[0] === '\xFE' && str[1] === '\xFF') { + for (i = 2; i < n; i += 2) { + strBuf.push(String.fromCharCode(str.charCodeAt(i) << 8 | str.charCodeAt(i + 1))); + } + } else { + for (i = 0; i < n; ++i) { + var code = PDFStringTranslateTable[str.charCodeAt(i)]; + strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); + } + } + return strBuf.join(''); +} +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} +function utf8StringToString(str) { + return unescape(encodeURIComponent(str)); +} +function isEmptyObj(obj) { + for (var key in obj) { + return false; + } + return true; +} +function isBool(v) { + return typeof v === 'boolean'; +} +function isInt(v) { + return typeof v === 'number' && (v | 0) === v; +} +function isNum(v) { + return typeof v === 'number'; +} +function isString(v) { + return typeof v === 'string'; +} +function isArray(v) { + return v instanceof Array; +} +function isArrayBuffer(v) { + return typeof v === 'object' && v !== null && v.byteLength !== undefined; +} +function isSpace(ch) { + return ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A; +} +function isNodeJS() { + if (typeof __pdfjsdev_webpack__ === 'undefined') { + return typeof process === 'object' && process + '' === '[object process]'; + } + return false; +} +function createPromiseCapability() { + var capability = {}; + capability.promise = new Promise(function (resolve, reject) { + capability.resolve = resolve; + capability.reject = reject; + }); + return capability; +} +var StatTimer = function StatTimerClosure() { + function rpad(str, pad, length) { + while (str.length < length) { + str += pad; + } + return str; + } + function StatTimer() { + this.started = Object.create(null); + this.times = []; + this.enabled = true; + } + StatTimer.prototype = { + time: function StatTimer_time(name) { + if (!this.enabled) { + return; + } + if (name in this.started) { + warn('Timer is already running for ' + name); + } + this.started[name] = Date.now(); + }, + timeEnd: function StatTimer_timeEnd(name) { + if (!this.enabled) { + return; + } + if (!(name in this.started)) { + warn('Timer has not been started for ' + name); + } + this.times.push({ + 'name': name, + 'start': this.started[name], + 'end': Date.now() + }); + delete this.started[name]; + }, + toString: function StatTimer_toString() { + var i, ii; + var times = this.times; + var out = ''; + var longest = 0; + for (i = 0, ii = times.length; i < ii; ++i) { + var name = times[i]['name']; + if (name.length > longest) { + longest = name.length; + } + } + for (i = 0, ii = times.length; i < ii; ++i) { + var span = times[i]; + var duration = span.end - span.start; + out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n'; + } + return out; + } + }; + return StatTimer; +}(); +var createBlob = function createBlob(data, contentType) { + if (typeof Blob !== 'undefined') { + return new Blob([data], { type: contentType }); + } + warn('The "Blob" constructor is not supported.'); +}; +var createObjectURL = function createObjectURLClosure() { + var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + return function createObjectURL(data, contentType, forceDataSchema) { + if (!forceDataSchema && typeof URL !== 'undefined' && URL.createObjectURL) { + var blob = createBlob(data, contentType); + return URL.createObjectURL(blob); + } + var buffer = 'data:' + contentType + ';base64,'; + for (var i = 0, ii = data.length; i < ii; i += 3) { + var b1 = data[i] & 0xFF; + var b2 = data[i + 1] & 0xFF; + var b3 = data[i + 2] & 0xFF; + var d1 = b1 >> 2, d2 = (b1 & 3) << 4 | b2 >> 4; + var d3 = i + 1 < ii ? (b2 & 0xF) << 2 | b3 >> 6 : 64; + var d4 = i + 2 < ii ? b3 & 0x3F : 64; + buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; + } + return buffer; + }; +}(); +function MessageHandler(sourceName, targetName, comObj) { + this.sourceName = sourceName; + this.targetName = targetName; + this.comObj = comObj; + this.callbackIndex = 1; + this.postMessageTransfers = true; + var callbacksCapabilities = this.callbacksCapabilities = Object.create(null); + var ah = this.actionHandler = Object.create(null); + this._onComObjOnMessage = function messageHandlerComObjOnMessage(event) { + var data = event.data; + if (data.targetName !== this.sourceName) { + return; + } + if (data.isReply) { + var callbackId = data.callbackId; + if (data.callbackId in callbacksCapabilities) { + var callback = callbacksCapabilities[callbackId]; + delete callbacksCapabilities[callbackId]; + if ('error' in data) { + callback.reject(data.error); + } else { + callback.resolve(data.data); + } + } else { + error('Cannot resolve callback ' + callbackId); + } + } else if (data.action in ah) { + var action = ah[data.action]; + if (data.callbackId) { + var sourceName = this.sourceName; + var targetName = data.sourceName; + Promise.resolve().then(function () { + return action[0].call(action[1], data.data); + }).then(function (result) { + comObj.postMessage({ + sourceName: sourceName, + targetName: targetName, + isReply: true, + callbackId: data.callbackId, + data: result + }); + }, function (reason) { + if (reason instanceof Error) { + reason = reason + ''; + } + comObj.postMessage({ + sourceName: sourceName, + targetName: targetName, + isReply: true, + callbackId: data.callbackId, + error: reason + }); + }); + } else { + action[0].call(action[1], data.data); + } + } else { + error('Unknown action from worker: ' + data.action); + } + }.bind(this); + comObj.addEventListener('message', this._onComObjOnMessage); +} +MessageHandler.prototype = { + on: function messageHandlerOn(actionName, handler, scope) { + var ah = this.actionHandler; + if (ah[actionName]) { + error('There is already an actionName called "' + actionName + '"'); + } + ah[actionName] = [ + handler, + scope + ]; + }, + send: function messageHandlerSend(actionName, data, transfers) { + var message = { + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + data: data + }; + this.postMessage(message, transfers); + }, + sendWithPromise: function messageHandlerSendWithPromise(actionName, data, transfers) { + var callbackId = this.callbackIndex++; + var message = { + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + data: data, + callbackId: callbackId + }; + var capability = createPromiseCapability(); + this.callbacksCapabilities[callbackId] = capability; + try { + this.postMessage(message, transfers); + } catch (e) { + capability.reject(e); + } + return capability.promise; + }, + postMessage: function (message, transfers) { + if (transfers && this.postMessageTransfers) { + this.comObj.postMessage(message, transfers); + } else { + this.comObj.postMessage(message); + } + }, + destroy: function () { + this.comObj.removeEventListener('message', this._onComObjOnMessage); + } +}; +function loadJpegStream(id, imageUrl, objs) { + var img = new Image(); + img.onload = function loadJpegStream_onloadClosure() { + objs.resolve(id, img); + }; + img.onerror = function loadJpegStream_onerrorClosure() { + objs.resolve(id, null); + warn('Error during JPEG image loading'); + }; + img.src = imageUrl; +} +exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX; +exports.IDENTITY_MATRIX = IDENTITY_MATRIX; +exports.OPS = OPS; +exports.VERBOSITY_LEVELS = VERBOSITY_LEVELS; +exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; +exports.AnnotationBorderStyleType = AnnotationBorderStyleType; +exports.AnnotationFieldFlag = AnnotationFieldFlag; +exports.AnnotationFlag = AnnotationFlag; +exports.AnnotationType = AnnotationType; +exports.FontType = FontType; +exports.ImageKind = ImageKind; +exports.CMapCompressionType = CMapCompressionType; +exports.InvalidPDFException = InvalidPDFException; +exports.MessageHandler = MessageHandler; +exports.MissingDataException = MissingDataException; +exports.MissingPDFException = MissingPDFException; +exports.NotImplementedException = NotImplementedException; +exports.PageViewport = PageViewport; +exports.PasswordException = PasswordException; +exports.PasswordResponses = PasswordResponses; +exports.StatTimer = StatTimer; +exports.StreamType = StreamType; +exports.TextRenderingMode = TextRenderingMode; +exports.UnexpectedResponseException = UnexpectedResponseException; +exports.UnknownErrorException = UnknownErrorException; +exports.Util = Util; +exports.XRefParseException = XRefParseException; +exports.arrayByteLength = arrayByteLength; +exports.arraysToBytes = arraysToBytes; +exports.assert = assert; +exports.bytesToString = bytesToString; +exports.createBlob = createBlob; +exports.createPromiseCapability = createPromiseCapability; +exports.createObjectURL = createObjectURL; +exports.deprecated = deprecated; +exports.error = error; +exports.getLookupTableFactory = getLookupTableFactory; +exports.getVerbosityLevel = getVerbosityLevel; +exports.globalScope = globalScope; +exports.info = info; +exports.isArray = isArray; +exports.isArrayBuffer = isArrayBuffer; +exports.isBool = isBool; +exports.isEmptyObj = isEmptyObj; +exports.isInt = isInt; +exports.isNum = isNum; +exports.isString = isString; +exports.isSpace = isSpace; +exports.isNodeJS = isNodeJS; +exports.isSameOrigin = isSameOrigin; +exports.createValidAbsoluteUrl = createValidAbsoluteUrl; +exports.isLittleEndian = isLittleEndian; +exports.isEvalSupported = isEvalSupported; +exports.loadJpegStream = loadJpegStream; +exports.log2 = log2; +exports.readInt8 = readInt8; +exports.readUint16 = readUint16; +exports.readUint32 = readUint32; +exports.removeNullCharacters = removeNullCharacters; +exports.setVerbosityLevel = setVerbosityLevel; +exports.shadow = shadow; +exports.string32 = string32; +exports.stringToBytes = stringToBytes; +exports.stringToPDFString = stringToPDFString; +exports.stringToUTF8String = stringToUTF8String; +exports.utf8StringToString = utf8StringToString; +exports.warn = warn; +/* WEBPACK VAR INJECTION */}.call(exports, __w_pdfjs_require__(9))) + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var isArray = sharedUtil.isArray; +var EOF = {}; +var Name = function NameClosure() { + function Name(name) { + this.name = name; + } + Name.prototype = {}; + var nameCache = Object.create(null); + Name.get = function Name_get(name) { + var nameValue = nameCache[name]; + return nameValue ? nameValue : nameCache[name] = new Name(name); + }; + return Name; +}(); +var Cmd = function CmdClosure() { + function Cmd(cmd) { + this.cmd = cmd; + } + Cmd.prototype = {}; + var cmdCache = Object.create(null); + Cmd.get = function Cmd_get(cmd) { + var cmdValue = cmdCache[cmd]; + return cmdValue ? cmdValue : cmdCache[cmd] = new Cmd(cmd); + }; + return Cmd; +}(); +var Dict = function DictClosure() { + var nonSerializable = function nonSerializableClosure() { + return nonSerializable; + }; + function Dict(xref) { + this.map = Object.create(null); + this.xref = xref; + this.objId = null; + this.suppressEncryption = false; + this.__nonSerializable__ = nonSerializable; + } + Dict.prototype = { + assignXref: function Dict_assignXref(newXref) { + this.xref = newXref; + }, + get: function Dict_get(key1, key2, key3) { + var value; + var xref = this.xref, suppressEncryption = this.suppressEncryption; + if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || typeof key2 === 'undefined') { + return xref ? xref.fetchIfRef(value, suppressEncryption) : value; + } + if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || typeof key3 === 'undefined') { + return xref ? xref.fetchIfRef(value, suppressEncryption) : value; + } + value = this.map[key3] || null; + return xref ? xref.fetchIfRef(value, suppressEncryption) : value; + }, + getAsync: function Dict_getAsync(key1, key2, key3) { + var value; + var xref = this.xref, suppressEncryption = this.suppressEncryption; + if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || typeof key2 === 'undefined') { + if (xref) { + return xref.fetchIfRefAsync(value, suppressEncryption); + } + return Promise.resolve(value); + } + if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || typeof key3 === 'undefined') { + if (xref) { + return xref.fetchIfRefAsync(value, suppressEncryption); + } + return Promise.resolve(value); + } + value = this.map[key3] || null; + if (xref) { + return xref.fetchIfRefAsync(value, suppressEncryption); + } + return Promise.resolve(value); + }, + getArray: function Dict_getArray(key1, key2, key3) { + var value = this.get(key1, key2, key3); + var xref = this.xref, suppressEncryption = this.suppressEncryption; + if (!isArray(value) || !xref) { + return value; + } + value = value.slice(); + for (var i = 0, ii = value.length; i < ii; i++) { + if (!isRef(value[i])) { + continue; + } + value[i] = xref.fetch(value[i], suppressEncryption); + } + return value; + }, + getRaw: function Dict_getRaw(key) { + return this.map[key]; + }, + getKeys: function Dict_getKeys() { + return Object.keys(this.map); + }, + set: function Dict_set(key, value) { + this.map[key] = value; + }, + has: function Dict_has(key) { + return key in this.map; + }, + forEach: function Dict_forEach(callback) { + for (var key in this.map) { + callback(key, this.get(key)); + } + } + }; + Dict.empty = new Dict(null); + Dict.merge = function Dict_merge(xref, dictArray) { + var mergedDict = new Dict(xref); + for (var i = 0, ii = dictArray.length; i < ii; i++) { + var dict = dictArray[i]; + if (!isDict(dict)) { + continue; + } + for (var keyName in dict.map) { + if (mergedDict.map[keyName]) { + continue; + } + mergedDict.map[keyName] = dict.map[keyName]; + } + } + return mergedDict; + }; + return Dict; +}(); +var Ref = function RefClosure() { + function Ref(num, gen) { + this.num = num; + this.gen = gen; + } + Ref.prototype = { + toString: function Ref_toString() { + var str = this.num + 'R'; + if (this.gen !== 0) { + str += this.gen; + } + return str; + } + }; + return Ref; +}(); +var RefSet = function RefSetClosure() { + function RefSet() { + this.dict = Object.create(null); + } + RefSet.prototype = { + has: function RefSet_has(ref) { + return ref.toString() in this.dict; + }, + put: function RefSet_put(ref) { + this.dict[ref.toString()] = true; + }, + remove: function RefSet_remove(ref) { + delete this.dict[ref.toString()]; + } + }; + return RefSet; +}(); +var RefSetCache = function RefSetCacheClosure() { + function RefSetCache() { + this.dict = Object.create(null); + } + RefSetCache.prototype = { + get: function RefSetCache_get(ref) { + return this.dict[ref.toString()]; + }, + has: function RefSetCache_has(ref) { + return ref.toString() in this.dict; + }, + put: function RefSetCache_put(ref, obj) { + this.dict[ref.toString()] = obj; + }, + putAlias: function RefSetCache_putAlias(ref, aliasRef) { + this.dict[ref.toString()] = this.get(aliasRef); + }, + forEach: function RefSetCache_forEach(fn, thisArg) { + for (var i in this.dict) { + fn.call(thisArg, this.dict[i]); + } + }, + clear: function RefSetCache_clear() { + this.dict = Object.create(null); + } + }; + return RefSetCache; +}(); +function isEOF(v) { + return v === EOF; +} +function isName(v, name) { + return v instanceof Name && (name === undefined || v.name === name); +} +function isCmd(v, cmd) { + return v instanceof Cmd && (cmd === undefined || v.cmd === cmd); +} +function isDict(v, type) { + return v instanceof Dict && (type === undefined || isName(v.get('Type'), type)); +} +function isRef(v) { + return v instanceof Ref; +} +function isRefsEqual(v1, v2) { + return v1.num === v2.num && v1.gen === v2.gen; +} +function isStream(v) { + return typeof v === 'object' && v !== null && v.getBytes !== undefined; +} +exports.EOF = EOF; +exports.Cmd = Cmd; +exports.Dict = Dict; +exports.Name = Name; +exports.Ref = Ref; +exports.RefSet = RefSet; +exports.RefSetCache = RefSetCache; +exports.isEOF = isEOF; +exports.isCmd = isCmd; +exports.isDict = isDict; +exports.isName = isName; +exports.isRef = isRef; +exports.isRefsEqual = isRefsEqual; +exports.isStream = isStream; + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreJbig2 = __w_pdfjs_require__(28); +var coreJpg = __w_pdfjs_require__(29); +var coreJpx = __w_pdfjs_require__(15); +var Util = sharedUtil.Util; +var error = sharedUtil.error; +var info = sharedUtil.info; +var isInt = sharedUtil.isInt; +var isArray = sharedUtil.isArray; +var createObjectURL = sharedUtil.createObjectURL; +var shadow = sharedUtil.shadow; +var isSpace = sharedUtil.isSpace; +var Dict = corePrimitives.Dict; +var isDict = corePrimitives.isDict; +var isStream = corePrimitives.isStream; +var Jbig2Image = coreJbig2.Jbig2Image; +var JpegImage = coreJpg.JpegImage; +var JpxImage = coreJpx.JpxImage; +var Stream = function StreamClosure() { + function Stream(arrayBuffer, start, length, dict) { + this.bytes = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer); + this.start = start || 0; + this.pos = this.start; + this.end = start + length || this.bytes.length; + this.dict = dict; + } + Stream.prototype = { + get length() { + return this.end - this.start; + }, + get isEmpty() { + return this.length === 0; + }, + getByte: function Stream_getByte() { + if (this.pos >= this.end) { + return -1; + } + return this.bytes[this.pos++]; + }, + getUint16: function Stream_getUint16() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }, + getInt32: function Stream_getInt32() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }, + getBytes: function Stream_getBytes(length) { + var bytes = this.bytes; + var pos = this.pos; + var strEnd = this.end; + if (!length) { + return bytes.subarray(pos, strEnd); + } + var end = pos + length; + if (end > strEnd) { + end = strEnd; + } + this.pos = end; + return bytes.subarray(pos, end); + }, + peekByte: function Stream_peekByte() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }, + peekBytes: function Stream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + skip: function Stream_skip(n) { + if (!n) { + n = 1; + } + this.pos += n; + }, + reset: function Stream_reset() { + this.pos = this.start; + }, + moveStart: function Stream_moveStart() { + this.start = this.pos; + }, + makeSubStream: function Stream_makeSubStream(start, length, dict) { + return new Stream(this.bytes.buffer, start, length, dict); + } + }; + return Stream; +}(); +var StringStream = function StringStreamClosure() { + function StringStream(str) { + var length = str.length; + var bytes = new Uint8Array(length); + for (var n = 0; n < length; ++n) { + bytes[n] = str.charCodeAt(n); + } + Stream.call(this, bytes); + } + StringStream.prototype = Stream.prototype; + return StringStream; +}(); +var DecodeStream = function DecodeStreamClosure() { + var emptyBuffer = new Uint8Array(0); + function DecodeStream(maybeMinBufferLength) { + this.pos = 0; + this.bufferLength = 0; + this.eof = false; + this.buffer = emptyBuffer; + this.minBufferLength = 512; + if (maybeMinBufferLength) { + while (this.minBufferLength < maybeMinBufferLength) { + this.minBufferLength *= 2; + } + } + } + DecodeStream.prototype = { + get isEmpty() { + while (!this.eof && this.bufferLength === 0) { + this.readBlock(); + } + return this.bufferLength === 0; + }, + ensureBuffer: function DecodeStream_ensureBuffer(requested) { + var buffer = this.buffer; + if (requested <= buffer.byteLength) { + return buffer; + } + var size = this.minBufferLength; + while (size < requested) { + size *= 2; + } + var buffer2 = new Uint8Array(size); + buffer2.set(buffer); + return this.buffer = buffer2; + }, + getByte: function DecodeStream_getByte() { + var pos = this.pos; + while (this.bufferLength <= pos) { + if (this.eof) { + return -1; + } + this.readBlock(); + } + return this.buffer[this.pos++]; + }, + getUint16: function DecodeStream_getUint16() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }, + getInt32: function DecodeStream_getInt32() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }, + getBytes: function DecodeStream_getBytes(length) { + var end, pos = this.pos; + if (length) { + this.ensureBuffer(pos + length); + end = pos + length; + while (!this.eof && this.bufferLength < end) { + this.readBlock(); + } + var bufEnd = this.bufferLength; + if (end > bufEnd) { + end = bufEnd; + } + } else { + while (!this.eof) { + this.readBlock(); + } + end = this.bufferLength; + } + this.pos = end; + return this.buffer.subarray(pos, end); + }, + peekByte: function DecodeStream_peekByte() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }, + peekBytes: function DecodeStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + makeSubStream: function DecodeStream_makeSubStream(start, length, dict) { + var end = start + length; + while (this.bufferLength <= end && !this.eof) { + this.readBlock(); + } + return new Stream(this.buffer, start, length, dict); + }, + skip: function DecodeStream_skip(n) { + if (!n) { + n = 1; + } + this.pos += n; + }, + reset: function DecodeStream_reset() { + this.pos = 0; + }, + getBaseStreams: function DecodeStream_getBaseStreams() { + if (this.str && this.str.getBaseStreams) { + return this.str.getBaseStreams(); + } + return []; + } + }; + return DecodeStream; +}(); +var StreamsSequenceStream = function StreamsSequenceStreamClosure() { + function StreamsSequenceStream(streams) { + this.streams = streams; + DecodeStream.call(this, null); + } + StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype); + StreamsSequenceStream.prototype.readBlock = function streamSequenceStreamReadBlock() { + var streams = this.streams; + if (streams.length === 0) { + this.eof = true; + return; + } + var stream = streams.shift(); + var chunk = stream.getBytes(); + var bufferLength = this.bufferLength; + var newLength = bufferLength + chunk.length; + var buffer = this.ensureBuffer(newLength); + buffer.set(chunk, bufferLength); + this.bufferLength = newLength; + }; + StreamsSequenceStream.prototype.getBaseStreams = function StreamsSequenceStream_getBaseStreams() { + var baseStreams = []; + for (var i = 0, ii = this.streams.length; i < ii; i++) { + var stream = this.streams[i]; + if (stream.getBaseStreams) { + Util.appendToArray(baseStreams, stream.getBaseStreams()); + } + } + return baseStreams; + }; + return StreamsSequenceStream; +}(); +var FlateStream = function FlateStreamClosure() { + var codeLenCodeMap = new Int32Array([ + 16, + 17, + 18, + 0, + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15 + ]); + var lengthDecode = new Int32Array([ + 0x00003, + 0x00004, + 0x00005, + 0x00006, + 0x00007, + 0x00008, + 0x00009, + 0x0000a, + 0x1000b, + 0x1000d, + 0x1000f, + 0x10011, + 0x20013, + 0x20017, + 0x2001b, + 0x2001f, + 0x30023, + 0x3002b, + 0x30033, + 0x3003b, + 0x40043, + 0x40053, + 0x40063, + 0x40073, + 0x50083, + 0x500a3, + 0x500c3, + 0x500e3, + 0x00102, + 0x00102, + 0x00102 + ]); + var distDecode = new Int32Array([ + 0x00001, + 0x00002, + 0x00003, + 0x00004, + 0x10005, + 0x10007, + 0x20009, + 0x2000d, + 0x30011, + 0x30019, + 0x40021, + 0x40031, + 0x50041, + 0x50061, + 0x60081, + 0x600c1, + 0x70101, + 0x70181, + 0x80201, + 0x80301, + 0x90401, + 0x90601, + 0xa0801, + 0xa0c01, + 0xb1001, + 0xb1801, + 0xc2001, + 0xc3001, + 0xd4001, + 0xd6001 + ]); + var fixedLitCodeTab = [ + new Int32Array([ + 0x70100, + 0x80050, + 0x80010, + 0x80118, + 0x70110, + 0x80070, + 0x80030, + 0x900c0, + 0x70108, + 0x80060, + 0x80020, + 0x900a0, + 0x80000, + 0x80080, + 0x80040, + 0x900e0, + 0x70104, + 0x80058, + 0x80018, + 0x90090, + 0x70114, + 0x80078, + 0x80038, + 0x900d0, + 0x7010c, + 0x80068, + 0x80028, + 0x900b0, + 0x80008, + 0x80088, + 0x80048, + 0x900f0, + 0x70102, + 0x80054, + 0x80014, + 0x8011c, + 0x70112, + 0x80074, + 0x80034, + 0x900c8, + 0x7010a, + 0x80064, + 0x80024, + 0x900a8, + 0x80004, + 0x80084, + 0x80044, + 0x900e8, + 0x70106, + 0x8005c, + 0x8001c, + 0x90098, + 0x70116, + 0x8007c, + 0x8003c, + 0x900d8, + 0x7010e, + 0x8006c, + 0x8002c, + 0x900b8, + 0x8000c, + 0x8008c, + 0x8004c, + 0x900f8, + 0x70101, + 0x80052, + 0x80012, + 0x8011a, + 0x70111, + 0x80072, + 0x80032, + 0x900c4, + 0x70109, + 0x80062, + 0x80022, + 0x900a4, + 0x80002, + 0x80082, + 0x80042, + 0x900e4, + 0x70105, + 0x8005a, + 0x8001a, + 0x90094, + 0x70115, + 0x8007a, + 0x8003a, + 0x900d4, + 0x7010d, + 0x8006a, + 0x8002a, + 0x900b4, + 0x8000a, + 0x8008a, + 0x8004a, + 0x900f4, + 0x70103, + 0x80056, + 0x80016, + 0x8011e, + 0x70113, + 0x80076, + 0x80036, + 0x900cc, + 0x7010b, + 0x80066, + 0x80026, + 0x900ac, + 0x80006, + 0x80086, + 0x80046, + 0x900ec, + 0x70107, + 0x8005e, + 0x8001e, + 0x9009c, + 0x70117, + 0x8007e, + 0x8003e, + 0x900dc, + 0x7010f, + 0x8006e, + 0x8002e, + 0x900bc, + 0x8000e, + 0x8008e, + 0x8004e, + 0x900fc, + 0x70100, + 0x80051, + 0x80011, + 0x80119, + 0x70110, + 0x80071, + 0x80031, + 0x900c2, + 0x70108, + 0x80061, + 0x80021, + 0x900a2, + 0x80001, + 0x80081, + 0x80041, + 0x900e2, + 0x70104, + 0x80059, + 0x80019, + 0x90092, + 0x70114, + 0x80079, + 0x80039, + 0x900d2, + 0x7010c, + 0x80069, + 0x80029, + 0x900b2, + 0x80009, + 0x80089, + 0x80049, + 0x900f2, + 0x70102, + 0x80055, + 0x80015, + 0x8011d, + 0x70112, + 0x80075, + 0x80035, + 0x900ca, + 0x7010a, + 0x80065, + 0x80025, + 0x900aa, + 0x80005, + 0x80085, + 0x80045, + 0x900ea, + 0x70106, + 0x8005d, + 0x8001d, + 0x9009a, + 0x70116, + 0x8007d, + 0x8003d, + 0x900da, + 0x7010e, + 0x8006d, + 0x8002d, + 0x900ba, + 0x8000d, + 0x8008d, + 0x8004d, + 0x900fa, + 0x70101, + 0x80053, + 0x80013, + 0x8011b, + 0x70111, + 0x80073, + 0x80033, + 0x900c6, + 0x70109, + 0x80063, + 0x80023, + 0x900a6, + 0x80003, + 0x80083, + 0x80043, + 0x900e6, + 0x70105, + 0x8005b, + 0x8001b, + 0x90096, + 0x70115, + 0x8007b, + 0x8003b, + 0x900d6, + 0x7010d, + 0x8006b, + 0x8002b, + 0x900b6, + 0x8000b, + 0x8008b, + 0x8004b, + 0x900f6, + 0x70103, + 0x80057, + 0x80017, + 0x8011f, + 0x70113, + 0x80077, + 0x80037, + 0x900ce, + 0x7010b, + 0x80067, + 0x80027, + 0x900ae, + 0x80007, + 0x80087, + 0x80047, + 0x900ee, + 0x70107, + 0x8005f, + 0x8001f, + 0x9009e, + 0x70117, + 0x8007f, + 0x8003f, + 0x900de, + 0x7010f, + 0x8006f, + 0x8002f, + 0x900be, + 0x8000f, + 0x8008f, + 0x8004f, + 0x900fe, + 0x70100, + 0x80050, + 0x80010, + 0x80118, + 0x70110, + 0x80070, + 0x80030, + 0x900c1, + 0x70108, + 0x80060, + 0x80020, + 0x900a1, + 0x80000, + 0x80080, + 0x80040, + 0x900e1, + 0x70104, + 0x80058, + 0x80018, + 0x90091, + 0x70114, + 0x80078, + 0x80038, + 0x900d1, + 0x7010c, + 0x80068, + 0x80028, + 0x900b1, + 0x80008, + 0x80088, + 0x80048, + 0x900f1, + 0x70102, + 0x80054, + 0x80014, + 0x8011c, + 0x70112, + 0x80074, + 0x80034, + 0x900c9, + 0x7010a, + 0x80064, + 0x80024, + 0x900a9, + 0x80004, + 0x80084, + 0x80044, + 0x900e9, + 0x70106, + 0x8005c, + 0x8001c, + 0x90099, + 0x70116, + 0x8007c, + 0x8003c, + 0x900d9, + 0x7010e, + 0x8006c, + 0x8002c, + 0x900b9, + 0x8000c, + 0x8008c, + 0x8004c, + 0x900f9, + 0x70101, + 0x80052, + 0x80012, + 0x8011a, + 0x70111, + 0x80072, + 0x80032, + 0x900c5, + 0x70109, + 0x80062, + 0x80022, + 0x900a5, + 0x80002, + 0x80082, + 0x80042, + 0x900e5, + 0x70105, + 0x8005a, + 0x8001a, + 0x90095, + 0x70115, + 0x8007a, + 0x8003a, + 0x900d5, + 0x7010d, + 0x8006a, + 0x8002a, + 0x900b5, + 0x8000a, + 0x8008a, + 0x8004a, + 0x900f5, + 0x70103, + 0x80056, + 0x80016, + 0x8011e, + 0x70113, + 0x80076, + 0x80036, + 0x900cd, + 0x7010b, + 0x80066, + 0x80026, + 0x900ad, + 0x80006, + 0x80086, + 0x80046, + 0x900ed, + 0x70107, + 0x8005e, + 0x8001e, + 0x9009d, + 0x70117, + 0x8007e, + 0x8003e, + 0x900dd, + 0x7010f, + 0x8006e, + 0x8002e, + 0x900bd, + 0x8000e, + 0x8008e, + 0x8004e, + 0x900fd, + 0x70100, + 0x80051, + 0x80011, + 0x80119, + 0x70110, + 0x80071, + 0x80031, + 0x900c3, + 0x70108, + 0x80061, + 0x80021, + 0x900a3, + 0x80001, + 0x80081, + 0x80041, + 0x900e3, + 0x70104, + 0x80059, + 0x80019, + 0x90093, + 0x70114, + 0x80079, + 0x80039, + 0x900d3, + 0x7010c, + 0x80069, + 0x80029, + 0x900b3, + 0x80009, + 0x80089, + 0x80049, + 0x900f3, + 0x70102, + 0x80055, + 0x80015, + 0x8011d, + 0x70112, + 0x80075, + 0x80035, + 0x900cb, + 0x7010a, + 0x80065, + 0x80025, + 0x900ab, + 0x80005, + 0x80085, + 0x80045, + 0x900eb, + 0x70106, + 0x8005d, + 0x8001d, + 0x9009b, + 0x70116, + 0x8007d, + 0x8003d, + 0x900db, + 0x7010e, + 0x8006d, + 0x8002d, + 0x900bb, + 0x8000d, + 0x8008d, + 0x8004d, + 0x900fb, + 0x70101, + 0x80053, + 0x80013, + 0x8011b, + 0x70111, + 0x80073, + 0x80033, + 0x900c7, + 0x70109, + 0x80063, + 0x80023, + 0x900a7, + 0x80003, + 0x80083, + 0x80043, + 0x900e7, + 0x70105, + 0x8005b, + 0x8001b, + 0x90097, + 0x70115, + 0x8007b, + 0x8003b, + 0x900d7, + 0x7010d, + 0x8006b, + 0x8002b, + 0x900b7, + 0x8000b, + 0x8008b, + 0x8004b, + 0x900f7, + 0x70103, + 0x80057, + 0x80017, + 0x8011f, + 0x70113, + 0x80077, + 0x80037, + 0x900cf, + 0x7010b, + 0x80067, + 0x80027, + 0x900af, + 0x80007, + 0x80087, + 0x80047, + 0x900ef, + 0x70107, + 0x8005f, + 0x8001f, + 0x9009f, + 0x70117, + 0x8007f, + 0x8003f, + 0x900df, + 0x7010f, + 0x8006f, + 0x8002f, + 0x900bf, + 0x8000f, + 0x8008f, + 0x8004f, + 0x900ff + ]), + 9 + ]; + var fixedDistCodeTab = [ + new Int32Array([ + 0x50000, + 0x50010, + 0x50008, + 0x50018, + 0x50004, + 0x50014, + 0x5000c, + 0x5001c, + 0x50002, + 0x50012, + 0x5000a, + 0x5001a, + 0x50006, + 0x50016, + 0x5000e, + 0x00000, + 0x50001, + 0x50011, + 0x50009, + 0x50019, + 0x50005, + 0x50015, + 0x5000d, + 0x5001d, + 0x50003, + 0x50013, + 0x5000b, + 0x5001b, + 0x50007, + 0x50017, + 0x5000f, + 0x00000 + ]), + 5 + ]; + function FlateStream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + var cmf = str.getByte(); + var flg = str.getByte(); + if (cmf === -1 || flg === -1) { + error('Invalid header in flate stream: ' + cmf + ', ' + flg); + } + if ((cmf & 0x0f) !== 0x08) { + error('Unknown compression method in flate stream: ' + cmf + ', ' + flg); + } + if (((cmf << 8) + flg) % 31 !== 0) { + error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg); + } + if (flg & 0x20) { + error('FDICT bit set in flate stream: ' + cmf + ', ' + flg); + } + this.codeSize = 0; + this.codeBuf = 0; + DecodeStream.call(this, maybeLength); + } + FlateStream.prototype = Object.create(DecodeStream.prototype); + FlateStream.prototype.getBits = function FlateStream_getBits(bits) { + var str = this.str; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + var b; + while (codeSize < bits) { + if ((b = str.getByte()) === -1) { + error('Bad encoding in flate stream'); + } + codeBuf |= b << codeSize; + codeSize += 8; + } + b = codeBuf & (1 << bits) - 1; + this.codeBuf = codeBuf >> bits; + this.codeSize = codeSize -= bits; + return b; + }; + FlateStream.prototype.getCode = function FlateStream_getCode(table) { + var str = this.str; + var codes = table[0]; + var maxLen = table[1]; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + var b; + while (codeSize < maxLen) { + if ((b = str.getByte()) === -1) { + break; + } + codeBuf |= b << codeSize; + codeSize += 8; + } + var code = codes[codeBuf & (1 << maxLen) - 1]; + var codeLen = code >> 16; + var codeVal = code & 0xffff; + if (codeLen < 1 || codeSize < codeLen) { + error('Bad encoding in flate stream'); + } + this.codeBuf = codeBuf >> codeLen; + this.codeSize = codeSize - codeLen; + return codeVal; + }; + FlateStream.prototype.generateHuffmanTable = function flateStreamGenerateHuffmanTable(lengths) { + var n = lengths.length; + var maxLen = 0; + var i; + for (i = 0; i < n; ++i) { + if (lengths[i] > maxLen) { + maxLen = lengths[i]; + } + } + var size = 1 << maxLen; + var codes = new Int32Array(size); + for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) { + for (var val = 0; val < n; ++val) { + if (lengths[val] === len) { + var code2 = 0; + var t = code; + for (i = 0; i < len; ++i) { + code2 = code2 << 1 | t & 1; + t >>= 1; + } + for (i = code2; i < size; i += skip) { + codes[i] = len << 16 | val; + } + ++code; + } + } + } + return [ + codes, + maxLen + ]; + }; + FlateStream.prototype.readBlock = function FlateStream_readBlock() { + var buffer, len; + var str = this.str; + var hdr = this.getBits(3); + if (hdr & 1) { + this.eof = true; + } + hdr >>= 1; + if (hdr === 0) { + var b; + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + var blockLen = b; + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + blockLen |= b << 8; + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + var check = b; + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + check |= b << 8; + if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) { + error('Bad uncompressed block length in flate stream'); + } + this.codeBuf = 0; + this.codeSize = 0; + var bufferLength = this.bufferLength; + buffer = this.ensureBuffer(bufferLength + blockLen); + var end = bufferLength + blockLen; + this.bufferLength = end; + if (blockLen === 0) { + if (str.peekByte() === -1) { + this.eof = true; + } + } else { + for (var n = bufferLength; n < end; ++n) { + if ((b = str.getByte()) === -1) { + this.eof = true; + break; + } + buffer[n] = b; + } + } + return; + } + var litCodeTable; + var distCodeTable; + if (hdr === 1) { + litCodeTable = fixedLitCodeTab; + distCodeTable = fixedDistCodeTab; + } else if (hdr === 2) { + var numLitCodes = this.getBits(5) + 257; + var numDistCodes = this.getBits(5) + 1; + var numCodeLenCodes = this.getBits(4) + 4; + var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length); + var i; + for (i = 0; i < numCodeLenCodes; ++i) { + codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3); + } + var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); + len = 0; + i = 0; + var codes = numLitCodes + numDistCodes; + var codeLengths = new Uint8Array(codes); + var bitsLength, bitsOffset, what; + while (i < codes) { + var code = this.getCode(codeLenCodeTab); + if (code === 16) { + bitsLength = 2; + bitsOffset = 3; + what = len; + } else if (code === 17) { + bitsLength = 3; + bitsOffset = 3; + what = len = 0; + } else if (code === 18) { + bitsLength = 7; + bitsOffset = 11; + what = len = 0; + } else { + codeLengths[i++] = len = code; + continue; + } + var repeatLength = this.getBits(bitsLength) + bitsOffset; + while (repeatLength-- > 0) { + codeLengths[i++] = what; + } + } + litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes)); + distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes)); + } else { + error('Unknown block type in flate stream'); + } + buffer = this.buffer; + var limit = buffer ? buffer.length : 0; + var pos = this.bufferLength; + while (true) { + var code1 = this.getCode(litCodeTable); + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer = this.ensureBuffer(pos + 1); + limit = buffer.length; + } + buffer[pos++] = code1; + continue; + } + if (code1 === 256) { + this.bufferLength = pos; + return; + } + code1 -= 257; + code1 = lengthDecode[code1]; + var code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + len = (code1 & 0xffff) + code2; + code1 = this.getCode(distCodeTable); + code1 = distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + var dist = (code1 & 0xffff) + code2; + if (pos + len >= limit) { + buffer = this.ensureBuffer(pos + len); + limit = buffer.length; + } + for (var k = 0; k < len; ++k, ++pos) { + buffer[pos] = buffer[pos - dist]; + } + } + }; + return FlateStream; +}(); +var PredictorStream = function PredictorStreamClosure() { + function PredictorStream(str, maybeLength, params) { + if (!isDict(params)) { + return str; + } + var predictor = this.predictor = params.get('Predictor') || 1; + if (predictor <= 1) { + return str; + } + if (predictor !== 2 && (predictor < 10 || predictor > 15)) { + error('Unsupported predictor: ' + predictor); + } + if (predictor === 2) { + this.readBlock = this.readBlockTiff; + } else { + this.readBlock = this.readBlockPng; + } + this.str = str; + this.dict = str.dict; + var colors = this.colors = params.get('Colors') || 1; + var bits = this.bits = params.get('BitsPerComponent') || 8; + var columns = this.columns = params.get('Columns') || 1; + this.pixBytes = colors * bits + 7 >> 3; + this.rowBytes = columns * colors * bits + 7 >> 3; + DecodeStream.call(this, maybeLength); + return this; + } + PredictorStream.prototype = Object.create(DecodeStream.prototype); + PredictorStream.prototype.readBlockTiff = function predictorStreamReadBlockTiff() { + var rowBytes = this.rowBytes; + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + rowBytes); + var bits = this.bits; + var colors = this.colors; + var rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + var inbuf = 0, outbuf = 0; + var inbits = 0, outbits = 0; + var pos = bufferLength; + var i; + if (bits === 1 && colors === 1) { + for (i = 0; i < rowBytes; ++i) { + var c = rawBytes[i] ^ inbuf; + c ^= c >> 1; + c ^= c >> 2; + c ^= c >> 4; + inbuf = (c & 1) << 7; + buffer[pos++] = c; + } + } else if (bits === 8) { + for (i = 0; i < colors; ++i) { + buffer[pos++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[pos] = buffer[pos - colors] + rawBytes[i]; + pos++; + } + } else { + var compArray = new Uint8Array(colors + 1); + var bitMask = (1 << bits) - 1; + var j = 0, k = bufferLength; + var columns = this.columns; + for (i = 0; i < columns; ++i) { + for (var kk = 0; kk < colors; ++kk) { + if (inbits < bits) { + inbuf = inbuf << 8 | rawBytes[j++] & 0xFF; + inbits += 8; + } + compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask; + inbits -= bits; + outbuf = outbuf << bits | compArray[kk]; + outbits += bits; + if (outbits >= 8) { + buffer[k++] = outbuf >> outbits - 8 & 0xFF; + outbits -= 8; + } + } + } + if (outbits > 0) { + buffer[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1); + } + } + this.bufferLength += rowBytes; + }; + PredictorStream.prototype.readBlockPng = function predictorStreamReadBlockPng() { + var rowBytes = this.rowBytes; + var pixBytes = this.pixBytes; + var predictor = this.str.getByte(); + var rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + rowBytes); + var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength); + if (prevRow.length === 0) { + prevRow = new Uint8Array(rowBytes); + } + var i, j = bufferLength, up, c; + switch (predictor) { + case 0: + for (i = 0; i < rowBytes; ++i) { + buffer[j++] = rawBytes[i]; + } + break; + case 1: + for (i = 0; i < pixBytes; ++i) { + buffer[j++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xFF; + j++; + } + break; + case 2: + for (i = 0; i < rowBytes; ++i) { + buffer[j++] = prevRow[i] + rawBytes[i] & 0xFF; + } + break; + case 3: + for (i = 0; i < pixBytes; ++i) { + buffer[j++] = (prevRow[i] >> 1) + rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xFF; + j++; + } + break; + case 4: + for (i = 0; i < pixBytes; ++i) { + up = prevRow[i]; + c = rawBytes[i]; + buffer[j++] = up + c; + } + for (; i < rowBytes; ++i) { + up = prevRow[i]; + var upLeft = prevRow[i - pixBytes]; + var left = buffer[j - pixBytes]; + var p = left + up - upLeft; + var pa = p - left; + if (pa < 0) { + pa = -pa; + } + var pb = p - up; + if (pb < 0) { + pb = -pb; + } + var pc = p - upLeft; + if (pc < 0) { + pc = -pc; + } + c = rawBytes[i]; + if (pa <= pb && pa <= pc) { + buffer[j++] = left + c; + } else if (pb <= pc) { + buffer[j++] = up + c; + } else { + buffer[j++] = upLeft + c; + } + } + break; + default: + error('Unsupported predictor: ' + predictor); + } + this.bufferLength += rowBytes; + }; + return PredictorStream; +}(); +var JpegStream = function JpegStreamClosure() { + function JpegStream(stream, maybeLength, dict, params) { + var ch; + while ((ch = stream.getByte()) !== -1) { + if (ch === 0xFF) { + stream.skip(-1); + break; + } + } + this.stream = stream; + this.maybeLength = maybeLength; + this.dict = dict; + this.params = params; + DecodeStream.call(this, maybeLength); + } + JpegStream.prototype = Object.create(DecodeStream.prototype); + Object.defineProperty(JpegStream.prototype, 'bytes', { + get: function JpegStream_bytes() { + return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); + }, + configurable: true + }); + JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) { + if (this.bufferLength) { + return; + } + var jpegImage = new JpegImage(); + var decodeArr = this.dict.getArray('Decode', 'D'); + if (this.forceRGB && isArray(decodeArr)) { + var bitsPerComponent = this.dict.get('BitsPerComponent') || 8; + var decodeArrLength = decodeArr.length; + var transform = new Int32Array(decodeArrLength); + var transformNeeded = false; + var maxValue = (1 << bitsPerComponent) - 1; + for (var i = 0; i < decodeArrLength; i += 2) { + transform[i] = (decodeArr[i + 1] - decodeArr[i]) * 256 | 0; + transform[i + 1] = decodeArr[i] * maxValue | 0; + if (transform[i] !== 256 || transform[i + 1] !== 0) { + transformNeeded = true; + } + } + if (transformNeeded) { + jpegImage.decodeTransform = transform; + } + } + if (isDict(this.params)) { + var colorTransform = this.params.get('ColorTransform'); + if (isInt(colorTransform)) { + jpegImage.colorTransform = colorTransform; + } + } + jpegImage.parse(this.bytes); + var data = jpegImage.getData(this.drawWidth, this.drawHeight, this.forceRGB); + this.buffer = data; + this.bufferLength = data.length; + this.eof = true; + }; + JpegStream.prototype.getBytes = function JpegStream_getBytes(length) { + this.ensureBuffer(); + return this.buffer; + }; + JpegStream.prototype.getIR = function JpegStream_getIR(forceDataSchema) { + return createObjectURL(this.bytes, 'image/jpeg', forceDataSchema); + }; + return JpegStream; +}(); +var JpxStream = function JpxStreamClosure() { + function JpxStream(stream, maybeLength, dict, params) { + this.stream = stream; + this.maybeLength = maybeLength; + this.dict = dict; + this.params = params; + DecodeStream.call(this, maybeLength); + } + JpxStream.prototype = Object.create(DecodeStream.prototype); + Object.defineProperty(JpxStream.prototype, 'bytes', { + get: function JpxStream_bytes() { + return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); + }, + configurable: true + }); + JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) { + if (this.bufferLength) { + return; + } + var jpxImage = new JpxImage(); + jpxImage.parse(this.bytes); + var width = jpxImage.width; + var height = jpxImage.height; + var componentsCount = jpxImage.componentsCount; + var tileCount = jpxImage.tiles.length; + if (tileCount === 1) { + this.buffer = jpxImage.tiles[0].items; + } else { + var data = new Uint8Array(width * height * componentsCount); + for (var k = 0; k < tileCount; k++) { + var tileComponents = jpxImage.tiles[k]; + var tileWidth = tileComponents.width; + var tileHeight = tileComponents.height; + var tileLeft = tileComponents.left; + var tileTop = tileComponents.top; + var src = tileComponents.items; + var srcPosition = 0; + var dataPosition = (width * tileTop + tileLeft) * componentsCount; + var imgRowSize = width * componentsCount; + var tileRowSize = tileWidth * componentsCount; + for (var j = 0; j < tileHeight; j++) { + var rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize); + data.set(rowBytes, dataPosition); + srcPosition += tileRowSize; + dataPosition += imgRowSize; + } + } + this.buffer = data; + } + this.bufferLength = this.buffer.length; + this.eof = true; + }; + return JpxStream; +}(); +var Jbig2Stream = function Jbig2StreamClosure() { + function Jbig2Stream(stream, maybeLength, dict, params) { + this.stream = stream; + this.maybeLength = maybeLength; + this.dict = dict; + this.params = params; + DecodeStream.call(this, maybeLength); + } + Jbig2Stream.prototype = Object.create(DecodeStream.prototype); + Object.defineProperty(Jbig2Stream.prototype, 'bytes', { + get: function Jbig2Stream_bytes() { + return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); + }, + configurable: true + }); + Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) { + if (this.bufferLength) { + return; + } + var jbig2Image = new Jbig2Image(); + var chunks = []; + if (isDict(this.params)) { + var globalsStream = this.params.get('JBIG2Globals'); + if (isStream(globalsStream)) { + var globals = globalsStream.getBytes(); + chunks.push({ + data: globals, + start: 0, + end: globals.length + }); + } + } + chunks.push({ + data: this.bytes, + start: 0, + end: this.bytes.length + }); + var data = jbig2Image.parseChunks(chunks); + var dataLength = data.length; + for (var i = 0; i < dataLength; i++) { + data[i] ^= 0xFF; + } + this.buffer = data; + this.bufferLength = dataLength; + this.eof = true; + }; + return Jbig2Stream; +}(); +var DecryptStream = function DecryptStreamClosure() { + function DecryptStream(str, maybeLength, decrypt) { + this.str = str; + this.dict = str.dict; + this.decrypt = decrypt; + this.nextChunk = null; + this.initialized = false; + DecodeStream.call(this, maybeLength); + } + var chunkSize = 512; + DecryptStream.prototype = Object.create(DecodeStream.prototype); + DecryptStream.prototype.readBlock = function DecryptStream_readBlock() { + var chunk; + if (this.initialized) { + chunk = this.nextChunk; + } else { + chunk = this.str.getBytes(chunkSize); + this.initialized = true; + } + if (!chunk || chunk.length === 0) { + this.eof = true; + return; + } + this.nextChunk = this.str.getBytes(chunkSize); + var hasMoreData = this.nextChunk && this.nextChunk.length > 0; + var decrypt = this.decrypt; + chunk = decrypt(chunk, !hasMoreData); + var bufferLength = this.bufferLength; + var i, n = chunk.length; + var buffer = this.ensureBuffer(bufferLength + n); + for (i = 0; i < n; i++) { + buffer[bufferLength++] = chunk[i]; + } + this.bufferLength = bufferLength; + }; + return DecryptStream; +}(); +var Ascii85Stream = function Ascii85StreamClosure() { + function Ascii85Stream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + this.input = new Uint8Array(5); + if (maybeLength) { + maybeLength = 0.8 * maybeLength; + } + DecodeStream.call(this, maybeLength); + } + Ascii85Stream.prototype = Object.create(DecodeStream.prototype); + Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() { + var TILDA_CHAR = 0x7E; + var Z_LOWER_CHAR = 0x7A; + var EOF = -1; + var str = this.str; + var c = str.getByte(); + while (isSpace(c)) { + c = str.getByte(); + } + if (c === EOF || c === TILDA_CHAR) { + this.eof = true; + return; + } + var bufferLength = this.bufferLength, buffer; + var i; + if (c === Z_LOWER_CHAR) { + buffer = this.ensureBuffer(bufferLength + 4); + for (i = 0; i < 4; ++i) { + buffer[bufferLength + i] = 0; + } + this.bufferLength += 4; + } else { + var input = this.input; + input[0] = c; + for (i = 1; i < 5; ++i) { + c = str.getByte(); + while (isSpace(c)) { + c = str.getByte(); + } + input[i] = c; + if (c === EOF || c === TILDA_CHAR) { + break; + } + } + buffer = this.ensureBuffer(bufferLength + i - 1); + this.bufferLength += i - 1; + if (i < 5) { + for (; i < 5; ++i) { + input[i] = 0x21 + 84; + } + this.eof = true; + } + var t = 0; + for (i = 0; i < 5; ++i) { + t = t * 85 + (input[i] - 0x21); + } + for (i = 3; i >= 0; --i) { + buffer[bufferLength + i] = t & 0xFF; + t >>= 8; + } + } + }; + return Ascii85Stream; +}(); +var AsciiHexStream = function AsciiHexStreamClosure() { + function AsciiHexStream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + this.firstDigit = -1; + if (maybeLength) { + maybeLength = 0.5 * maybeLength; + } + DecodeStream.call(this, maybeLength); + } + AsciiHexStream.prototype = Object.create(DecodeStream.prototype); + AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() { + var UPSTREAM_BLOCK_SIZE = 8000; + var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE); + if (!bytes.length) { + this.eof = true; + return; + } + var maxDecodeLength = bytes.length + 1 >> 1; + var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength); + var bufferLength = this.bufferLength; + var firstDigit = this.firstDigit; + for (var i = 0, ii = bytes.length; i < ii; i++) { + var ch = bytes[i], digit; + if (ch >= 0x30 && ch <= 0x39) { + digit = ch & 0x0F; + } else if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) { + digit = (ch & 0x0F) + 9; + } else if (ch === 0x3E) { + this.eof = true; + break; + } else { + continue; + } + if (firstDigit < 0) { + firstDigit = digit; + } else { + buffer[bufferLength++] = firstDigit << 4 | digit; + firstDigit = -1; + } + } + if (firstDigit >= 0 && this.eof) { + buffer[bufferLength++] = firstDigit << 4; + firstDigit = -1; + } + this.firstDigit = firstDigit; + this.bufferLength = bufferLength; + }; + return AsciiHexStream; +}(); +var RunLengthStream = function RunLengthStreamClosure() { + function RunLengthStream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + DecodeStream.call(this, maybeLength); + } + RunLengthStream.prototype = Object.create(DecodeStream.prototype); + RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() { + var repeatHeader = this.str.getBytes(2); + if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) { + this.eof = true; + return; + } + var buffer; + var bufferLength = this.bufferLength; + var n = repeatHeader[0]; + if (n < 128) { + buffer = this.ensureBuffer(bufferLength + n + 1); + buffer[bufferLength++] = repeatHeader[1]; + if (n > 0) { + var source = this.str.getBytes(n); + buffer.set(source, bufferLength); + bufferLength += n; + } + } else { + n = 257 - n; + var b = repeatHeader[1]; + buffer = this.ensureBuffer(bufferLength + n + 1); + for (var i = 0; i < n; i++) { + buffer[bufferLength++] = b; + } + } + this.bufferLength = bufferLength; + }; + return RunLengthStream; +}(); +var CCITTFaxStream = function CCITTFaxStreamClosure() { + var ccittEOL = -2; + var ccittEOF = -1; + var twoDimPass = 0; + var twoDimHoriz = 1; + var twoDimVert0 = 2; + var twoDimVertR1 = 3; + var twoDimVertL1 = 4; + var twoDimVertR2 = 5; + var twoDimVertL2 = 6; + var twoDimVertR3 = 7; + var twoDimVertL3 = 8; + var twoDimTable = [ + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + 7, + twoDimVertL3 + ], + [ + 7, + twoDimVertR3 + ], + [ + 6, + twoDimVertL2 + ], + [ + 6, + twoDimVertL2 + ], + [ + 6, + twoDimVertR2 + ], + [ + 6, + twoDimVertR2 + ], + [ + 4, + twoDimPass + ], + [ + 4, + twoDimPass + ], + [ + 4, + twoDimPass + ], + [ + 4, + twoDimPass + ], + [ + 4, + twoDimPass + ], + [ + 4, + twoDimPass + ], + [ + 4, + twoDimPass + ], + [ + 4, + twoDimPass + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimHoriz + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertL1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 3, + twoDimVertR1 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ], + [ + 1, + twoDimVert0 + ] + ]; + var whiteTable1 = [ + [ + -1, + -1 + ], + [ + 12, + ccittEOL + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + 11, + 1792 + ], + [ + 11, + 1792 + ], + [ + 12, + 1984 + ], + [ + 12, + 2048 + ], + [ + 12, + 2112 + ], + [ + 12, + 2176 + ], + [ + 12, + 2240 + ], + [ + 12, + 2304 + ], + [ + 11, + 1856 + ], + [ + 11, + 1856 + ], + [ + 11, + 1920 + ], + [ + 11, + 1920 + ], + [ + 12, + 2368 + ], + [ + 12, + 2432 + ], + [ + 12, + 2496 + ], + [ + 12, + 2560 + ] + ]; + var whiteTable2 = [ + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + 8, + 29 + ], + [ + 8, + 29 + ], + [ + 8, + 30 + ], + [ + 8, + 30 + ], + [ + 8, + 45 + ], + [ + 8, + 45 + ], + [ + 8, + 46 + ], + [ + 8, + 46 + ], + [ + 7, + 22 + ], + [ + 7, + 22 + ], + [ + 7, + 22 + ], + [ + 7, + 22 + ], + [ + 7, + 23 + ], + [ + 7, + 23 + ], + [ + 7, + 23 + ], + [ + 7, + 23 + ], + [ + 8, + 47 + ], + [ + 8, + 47 + ], + [ + 8, + 48 + ], + [ + 8, + 48 + ], + [ + 6, + 13 + ], + [ + 6, + 13 + ], + [ + 6, + 13 + ], + [ + 6, + 13 + ], + [ + 6, + 13 + ], + [ + 6, + 13 + ], + [ + 6, + 13 + ], + [ + 6, + 13 + ], + [ + 7, + 20 + ], + [ + 7, + 20 + ], + [ + 7, + 20 + ], + [ + 7, + 20 + ], + [ + 8, + 33 + ], + [ + 8, + 33 + ], + [ + 8, + 34 + ], + [ + 8, + 34 + ], + [ + 8, + 35 + ], + [ + 8, + 35 + ], + [ + 8, + 36 + ], + [ + 8, + 36 + ], + [ + 8, + 37 + ], + [ + 8, + 37 + ], + [ + 8, + 38 + ], + [ + 8, + 38 + ], + [ + 7, + 19 + ], + [ + 7, + 19 + ], + [ + 7, + 19 + ], + [ + 7, + 19 + ], + [ + 8, + 31 + ], + [ + 8, + 31 + ], + [ + 8, + 32 + ], + [ + 8, + 32 + ], + [ + 6, + 1 + ], + [ + 6, + 1 + ], + [ + 6, + 1 + ], + [ + 6, + 1 + ], + [ + 6, + 1 + ], + [ + 6, + 1 + ], + [ + 6, + 1 + ], + [ + 6, + 1 + ], + [ + 6, + 12 + ], + [ + 6, + 12 + ], + [ + 6, + 12 + ], + [ + 6, + 12 + ], + [ + 6, + 12 + ], + [ + 6, + 12 + ], + [ + 6, + 12 + ], + [ + 6, + 12 + ], + [ + 8, + 53 + ], + [ + 8, + 53 + ], + [ + 8, + 54 + ], + [ + 8, + 54 + ], + [ + 7, + 26 + ], + [ + 7, + 26 + ], + [ + 7, + 26 + ], + [ + 7, + 26 + ], + [ + 8, + 39 + ], + [ + 8, + 39 + ], + [ + 8, + 40 + ], + [ + 8, + 40 + ], + [ + 8, + 41 + ], + [ + 8, + 41 + ], + [ + 8, + 42 + ], + [ + 8, + 42 + ], + [ + 8, + 43 + ], + [ + 8, + 43 + ], + [ + 8, + 44 + ], + [ + 8, + 44 + ], + [ + 7, + 21 + ], + [ + 7, + 21 + ], + [ + 7, + 21 + ], + [ + 7, + 21 + ], + [ + 7, + 28 + ], + [ + 7, + 28 + ], + [ + 7, + 28 + ], + [ + 7, + 28 + ], + [ + 8, + 61 + ], + [ + 8, + 61 + ], + [ + 8, + 62 + ], + [ + 8, + 62 + ], + [ + 8, + 63 + ], + [ + 8, + 63 + ], + [ + 8, + 0 + ], + [ + 8, + 0 + ], + [ + 8, + 320 + ], + [ + 8, + 320 + ], + [ + 8, + 384 + ], + [ + 8, + 384 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 10 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 5, + 11 + ], + [ + 7, + 27 + ], + [ + 7, + 27 + ], + [ + 7, + 27 + ], + [ + 7, + 27 + ], + [ + 8, + 59 + ], + [ + 8, + 59 + ], + [ + 8, + 60 + ], + [ + 8, + 60 + ], + [ + 9, + 1472 + ], + [ + 9, + 1536 + ], + [ + 9, + 1600 + ], + [ + 9, + 1728 + ], + [ + 7, + 18 + ], + [ + 7, + 18 + ], + [ + 7, + 18 + ], + [ + 7, + 18 + ], + [ + 7, + 24 + ], + [ + 7, + 24 + ], + [ + 7, + 24 + ], + [ + 7, + 24 + ], + [ + 8, + 49 + ], + [ + 8, + 49 + ], + [ + 8, + 50 + ], + [ + 8, + 50 + ], + [ + 8, + 51 + ], + [ + 8, + 51 + ], + [ + 8, + 52 + ], + [ + 8, + 52 + ], + [ + 7, + 25 + ], + [ + 7, + 25 + ], + [ + 7, + 25 + ], + [ + 7, + 25 + ], + [ + 8, + 55 + ], + [ + 8, + 55 + ], + [ + 8, + 56 + ], + [ + 8, + 56 + ], + [ + 8, + 57 + ], + [ + 8, + 57 + ], + [ + 8, + 58 + ], + [ + 8, + 58 + ], + [ + 6, + 192 + ], + [ + 6, + 192 + ], + [ + 6, + 192 + ], + [ + 6, + 192 + ], + [ + 6, + 192 + ], + [ + 6, + 192 + ], + [ + 6, + 192 + ], + [ + 6, + 192 + ], + [ + 6, + 1664 + ], + [ + 6, + 1664 + ], + [ + 6, + 1664 + ], + [ + 6, + 1664 + ], + [ + 6, + 1664 + ], + [ + 6, + 1664 + ], + [ + 6, + 1664 + ], + [ + 6, + 1664 + ], + [ + 8, + 448 + ], + [ + 8, + 448 + ], + [ + 8, + 512 + ], + [ + 8, + 512 + ], + [ + 9, + 704 + ], + [ + 9, + 768 + ], + [ + 8, + 640 + ], + [ + 8, + 640 + ], + [ + 8, + 576 + ], + [ + 8, + 576 + ], + [ + 9, + 832 + ], + [ + 9, + 896 + ], + [ + 9, + 960 + ], + [ + 9, + 1024 + ], + [ + 9, + 1088 + ], + [ + 9, + 1152 + ], + [ + 9, + 1216 + ], + [ + 9, + 1280 + ], + [ + 9, + 1344 + ], + [ + 9, + 1408 + ], + [ + 7, + 256 + ], + [ + 7, + 256 + ], + [ + 7, + 256 + ], + [ + 7, + 256 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 2 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 4, + 3 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 128 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 8 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 5, + 9 + ], + [ + 6, + 16 + ], + [ + 6, + 16 + ], + [ + 6, + 16 + ], + [ + 6, + 16 + ], + [ + 6, + 16 + ], + [ + 6, + 16 + ], + [ + 6, + 16 + ], + [ + 6, + 16 + ], + [ + 6, + 17 + ], + [ + 6, + 17 + ], + [ + 6, + 17 + ], + [ + 6, + 17 + ], + [ + 6, + 17 + ], + [ + 6, + 17 + ], + [ + 6, + 17 + ], + [ + 6, + 17 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 4 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 6, + 14 + ], + [ + 6, + 14 + ], + [ + 6, + 14 + ], + [ + 6, + 14 + ], + [ + 6, + 14 + ], + [ + 6, + 14 + ], + [ + 6, + 14 + ], + [ + 6, + 14 + ], + [ + 6, + 15 + ], + [ + 6, + 15 + ], + [ + 6, + 15 + ], + [ + 6, + 15 + ], + [ + 6, + 15 + ], + [ + 6, + 15 + ], + [ + 6, + 15 + ], + [ + 6, + 15 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 5, + 64 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ], + [ + 4, + 7 + ] + ]; + var blackTable1 = [ + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + 12, + ccittEOL + ], + [ + 12, + ccittEOL + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + 11, + 1792 + ], + [ + 11, + 1792 + ], + [ + 11, + 1792 + ], + [ + 11, + 1792 + ], + [ + 12, + 1984 + ], + [ + 12, + 1984 + ], + [ + 12, + 2048 + ], + [ + 12, + 2048 + ], + [ + 12, + 2112 + ], + [ + 12, + 2112 + ], + [ + 12, + 2176 + ], + [ + 12, + 2176 + ], + [ + 12, + 2240 + ], + [ + 12, + 2240 + ], + [ + 12, + 2304 + ], + [ + 12, + 2304 + ], + [ + 11, + 1856 + ], + [ + 11, + 1856 + ], + [ + 11, + 1856 + ], + [ + 11, + 1856 + ], + [ + 11, + 1920 + ], + [ + 11, + 1920 + ], + [ + 11, + 1920 + ], + [ + 11, + 1920 + ], + [ + 12, + 2368 + ], + [ + 12, + 2368 + ], + [ + 12, + 2432 + ], + [ + 12, + 2432 + ], + [ + 12, + 2496 + ], + [ + 12, + 2496 + ], + [ + 12, + 2560 + ], + [ + 12, + 2560 + ], + [ + 10, + 18 + ], + [ + 10, + 18 + ], + [ + 10, + 18 + ], + [ + 10, + 18 + ], + [ + 10, + 18 + ], + [ + 10, + 18 + ], + [ + 10, + 18 + ], + [ + 10, + 18 + ], + [ + 12, + 52 + ], + [ + 12, + 52 + ], + [ + 13, + 640 + ], + [ + 13, + 704 + ], + [ + 13, + 768 + ], + [ + 13, + 832 + ], + [ + 12, + 55 + ], + [ + 12, + 55 + ], + [ + 12, + 56 + ], + [ + 12, + 56 + ], + [ + 13, + 1280 + ], + [ + 13, + 1344 + ], + [ + 13, + 1408 + ], + [ + 13, + 1472 + ], + [ + 12, + 59 + ], + [ + 12, + 59 + ], + [ + 12, + 60 + ], + [ + 12, + 60 + ], + [ + 13, + 1536 + ], + [ + 13, + 1600 + ], + [ + 11, + 24 + ], + [ + 11, + 24 + ], + [ + 11, + 24 + ], + [ + 11, + 24 + ], + [ + 11, + 25 + ], + [ + 11, + 25 + ], + [ + 11, + 25 + ], + [ + 11, + 25 + ], + [ + 13, + 1664 + ], + [ + 13, + 1728 + ], + [ + 12, + 320 + ], + [ + 12, + 320 + ], + [ + 12, + 384 + ], + [ + 12, + 384 + ], + [ + 12, + 448 + ], + [ + 12, + 448 + ], + [ + 13, + 512 + ], + [ + 13, + 576 + ], + [ + 12, + 53 + ], + [ + 12, + 53 + ], + [ + 12, + 54 + ], + [ + 12, + 54 + ], + [ + 13, + 896 + ], + [ + 13, + 960 + ], + [ + 13, + 1024 + ], + [ + 13, + 1088 + ], + [ + 13, + 1152 + ], + [ + 13, + 1216 + ], + [ + 10, + 64 + ], + [ + 10, + 64 + ], + [ + 10, + 64 + ], + [ + 10, + 64 + ], + [ + 10, + 64 + ], + [ + 10, + 64 + ], + [ + 10, + 64 + ], + [ + 10, + 64 + ] + ]; + var blackTable2 = [ + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 8, + 13 + ], + [ + 11, + 23 + ], + [ + 11, + 23 + ], + [ + 12, + 50 + ], + [ + 12, + 51 + ], + [ + 12, + 44 + ], + [ + 12, + 45 + ], + [ + 12, + 46 + ], + [ + 12, + 47 + ], + [ + 12, + 57 + ], + [ + 12, + 58 + ], + [ + 12, + 61 + ], + [ + 12, + 256 + ], + [ + 10, + 16 + ], + [ + 10, + 16 + ], + [ + 10, + 16 + ], + [ + 10, + 16 + ], + [ + 10, + 17 + ], + [ + 10, + 17 + ], + [ + 10, + 17 + ], + [ + 10, + 17 + ], + [ + 12, + 48 + ], + [ + 12, + 49 + ], + [ + 12, + 62 + ], + [ + 12, + 63 + ], + [ + 12, + 30 + ], + [ + 12, + 31 + ], + [ + 12, + 32 + ], + [ + 12, + 33 + ], + [ + 12, + 40 + ], + [ + 12, + 41 + ], + [ + 11, + 22 + ], + [ + 11, + 22 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 8, + 14 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 10 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 7, + 11 + ], + [ + 9, + 15 + ], + [ + 9, + 15 + ], + [ + 9, + 15 + ], + [ + 9, + 15 + ], + [ + 9, + 15 + ], + [ + 9, + 15 + ], + [ + 9, + 15 + ], + [ + 9, + 15 + ], + [ + 12, + 128 + ], + [ + 12, + 192 + ], + [ + 12, + 26 + ], + [ + 12, + 27 + ], + [ + 12, + 28 + ], + [ + 12, + 29 + ], + [ + 11, + 19 + ], + [ + 11, + 19 + ], + [ + 11, + 20 + ], + [ + 11, + 20 + ], + [ + 12, + 34 + ], + [ + 12, + 35 + ], + [ + 12, + 36 + ], + [ + 12, + 37 + ], + [ + 12, + 38 + ], + [ + 12, + 39 + ], + [ + 11, + 21 + ], + [ + 11, + 21 + ], + [ + 12, + 42 + ], + [ + 12, + 43 + ], + [ + 10, + 0 + ], + [ + 10, + 0 + ], + [ + 10, + 0 + ], + [ + 10, + 0 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ], + [ + 7, + 12 + ] + ]; + var blackTable3 = [ + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + -1, + -1 + ], + [ + 6, + 9 + ], + [ + 6, + 8 + ], + [ + 5, + 7 + ], + [ + 5, + 7 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 6 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 4, + 5 + ], + [ + 3, + 1 + ], + [ + 3, + 1 + ], + [ + 3, + 1 + ], + [ + 3, + 1 + ], + [ + 3, + 1 + ], + [ + 3, + 1 + ], + [ + 3, + 1 + ], + [ + 3, + 1 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 3 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ], + [ + 2, + 2 + ] + ]; + function CCITTFaxStream(str, maybeLength, params) { + this.str = str; + this.dict = str.dict; + params = params || Dict.empty; + this.encoding = params.get('K') || 0; + this.eoline = params.get('EndOfLine') || false; + this.byteAlign = params.get('EncodedByteAlign') || false; + this.columns = params.get('Columns') || 1728; + this.rows = params.get('Rows') || 0; + var eoblock = params.get('EndOfBlock'); + if (eoblock === null || eoblock === undefined) { + eoblock = true; + } + this.eoblock = eoblock; + this.black = params.get('BlackIs1') || false; + this.codingLine = new Uint32Array(this.columns + 1); + this.refLine = new Uint32Array(this.columns + 2); + this.codingLine[0] = this.columns; + this.codingPos = 0; + this.row = 0; + this.nextLine2D = this.encoding < 0; + this.inputBits = 0; + this.inputBuf = 0; + this.outputBits = 0; + var code1; + while ((code1 = this.lookBits(12)) === 0) { + this.eatBits(1); + } + if (code1 === 1) { + this.eatBits(12); + } + if (this.encoding > 0) { + this.nextLine2D = !this.lookBits(1); + this.eatBits(1); + } + DecodeStream.call(this, maybeLength); + } + CCITTFaxStream.prototype = Object.create(DecodeStream.prototype); + CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() { + while (!this.eof) { + var c = this.lookChar(); + this.ensureBuffer(this.bufferLength + 1); + this.buffer[this.bufferLength++] = c; + } + }; + CCITTFaxStream.prototype.addPixels = function ccittFaxStreamAddPixels(a1, blackPixels) { + var codingLine = this.codingLine; + var codingPos = this.codingPos; + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info('row is wrong length'); + this.err = true; + a1 = this.columns; + } + if (codingPos & 1 ^ blackPixels) { + ++codingPos; + } + codingLine[codingPos] = a1; + } + this.codingPos = codingPos; + }; + CCITTFaxStream.prototype.addPixelsNeg = function ccittFaxStreamAddPixelsNeg(a1, blackPixels) { + var codingLine = this.codingLine; + var codingPos = this.codingPos; + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info('row is wrong length'); + this.err = true; + a1 = this.columns; + } + if (codingPos & 1 ^ blackPixels) { + ++codingPos; + } + codingLine[codingPos] = a1; + } else if (a1 < codingLine[codingPos]) { + if (a1 < 0) { + info('invalid code'); + this.err = true; + a1 = 0; + } + while (codingPos > 0 && a1 < codingLine[codingPos - 1]) { + --codingPos; + } + codingLine[codingPos] = a1; + } + this.codingPos = codingPos; + }; + CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() { + var refLine = this.refLine; + var codingLine = this.codingLine; + var columns = this.columns; + var refPos, blackPixels, bits, i; + if (this.outputBits === 0) { + if (this.eof) { + return null; + } + this.err = false; + var code1, code2, code3; + if (this.nextLine2D) { + for (i = 0; codingLine[i] < columns; ++i) { + refLine[i] = codingLine[i]; + } + refLine[i++] = columns; + refLine[i] = columns; + codingLine[0] = 0; + this.codingPos = 0; + refPos = 0; + blackPixels = 0; + while (codingLine[this.codingPos] < columns) { + code1 = this.getTwoDimCode(); + switch (code1) { + case twoDimPass: + this.addPixels(refLine[refPos + 1], blackPixels); + if (refLine[refPos + 1] < columns) { + refPos += 2; + } + break; + case twoDimHoriz: + code1 = code2 = 0; + if (blackPixels) { + do { + code1 += code3 = this.getBlackCode(); + } while (code3 >= 64); + do { + code2 += code3 = this.getWhiteCode(); + } while (code3 >= 64); + } else { + do { + code1 += code3 = this.getWhiteCode(); + } while (code3 >= 64); + do { + code2 += code3 = this.getBlackCode(); + } while (code3 >= 64); + } + this.addPixels(codingLine[this.codingPos] + code1, blackPixels); + if (codingLine[this.codingPos] < columns) { + this.addPixels(codingLine[this.codingPos] + code2, blackPixels ^ 1); + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + break; + case twoDimVertR3: + this.addPixels(refLine[refPos] + 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR2: + this.addPixels(refLine[refPos] + 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR1: + this.addPixels(refLine[refPos] + 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVert0: + this.addPixels(refLine[refPos], blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL3: + this.addPixelsNeg(refLine[refPos] - 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL2: + this.addPixelsNeg(refLine[refPos] - 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL1: + this.addPixelsNeg(refLine[refPos] - 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case ccittEOF: + this.addPixels(columns, 0); + this.eof = true; + break; + default: + info('bad 2d code'); + this.addPixels(columns, 0); + this.err = true; + } + } + } else { + codingLine[0] = 0; + this.codingPos = 0; + blackPixels = 0; + while (codingLine[this.codingPos] < columns) { + code1 = 0; + if (blackPixels) { + do { + code1 += code3 = this.getBlackCode(); + } while (code3 >= 64); + } else { + do { + code1 += code3 = this.getWhiteCode(); + } while (code3 >= 64); + } + this.addPixels(codingLine[this.codingPos] + code1, blackPixels); + blackPixels ^= 1; + } + } + var gotEOL = false; + if (this.byteAlign) { + this.inputBits &= ~7; + } + if (!this.eoblock && this.row === this.rows - 1) { + this.eof = true; + } else { + code1 = this.lookBits(12); + if (this.eoline) { + while (code1 !== ccittEOF && code1 !== 1) { + this.eatBits(1); + code1 = this.lookBits(12); + } + } else { + while (code1 === 0) { + this.eatBits(1); + code1 = this.lookBits(12); + } + } + if (code1 === 1) { + this.eatBits(12); + gotEOL = true; + } else if (code1 === ccittEOF) { + this.eof = true; + } + } + if (!this.eof && this.encoding > 0) { + this.nextLine2D = !this.lookBits(1); + this.eatBits(1); + } + if (this.eoblock && gotEOL && this.byteAlign) { + code1 = this.lookBits(12); + if (code1 === 1) { + this.eatBits(12); + if (this.encoding > 0) { + this.lookBits(1); + this.eatBits(1); + } + if (this.encoding >= 0) { + for (i = 0; i < 4; ++i) { + code1 = this.lookBits(12); + if (code1 !== 1) { + info('bad rtc code: ' + code1); + } + this.eatBits(12); + if (this.encoding > 0) { + this.lookBits(1); + this.eatBits(1); + } + } + } + this.eof = true; + } + } else if (this.err && this.eoline) { + while (true) { + code1 = this.lookBits(13); + if (code1 === ccittEOF) { + this.eof = true; + return null; + } + if (code1 >> 1 === 1) { + break; + } + this.eatBits(1); + } + this.eatBits(12); + if (this.encoding > 0) { + this.eatBits(1); + this.nextLine2D = !(code1 & 1); + } + } + if (codingLine[0] > 0) { + this.outputBits = codingLine[this.codingPos = 0]; + } else { + this.outputBits = codingLine[this.codingPos = 1]; + } + this.row++; + } + var c; + if (this.outputBits >= 8) { + c = this.codingPos & 1 ? 0 : 0xFF; + this.outputBits -= 8; + if (this.outputBits === 0 && codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1]; + } + } else { + bits = 8; + c = 0; + do { + if (this.outputBits > bits) { + c <<= bits; + if (!(this.codingPos & 1)) { + c |= 0xFF >> 8 - bits; + } + this.outputBits -= bits; + bits = 0; + } else { + c <<= this.outputBits; + if (!(this.codingPos & 1)) { + c |= 0xFF >> 8 - this.outputBits; + } + bits -= this.outputBits; + this.outputBits = 0; + if (codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1]; + } else if (bits > 0) { + c <<= bits; + bits = 0; + } + } + } while (bits); + } + if (this.black) { + c ^= 0xFF; + } + return c; + }; + CCITTFaxStream.prototype.findTableCode = function ccittFaxStreamFindTableCode(start, end, table, limit) { + var limitValue = limit || 0; + for (var i = start; i <= end; ++i) { + var code = this.lookBits(i); + if (code === ccittEOF) { + return [ + true, + 1, + false + ]; + } + if (i < end) { + code <<= end - i; + } + if (!limitValue || code >= limitValue) { + var p = table[code - limitValue]; + if (p[0] === i) { + this.eatBits(i); + return [ + true, + p[1], + true + ]; + } + } + } + return [ + false, + 0, + false + ]; + }; + CCITTFaxStream.prototype.getTwoDimCode = function ccittFaxStreamGetTwoDimCode() { + var code = 0; + var p; + if (this.eoblock) { + code = this.lookBits(7); + p = twoDimTable[code]; + if (p && p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(1, 7, twoDimTable); + if (result[0] && result[2]) { + return result[1]; + } + } + info('Bad two dim code'); + return ccittEOF; + }; + CCITTFaxStream.prototype.getWhiteCode = function ccittFaxStreamGetWhiteCode() { + var code = 0; + var p; + if (this.eoblock) { + code = this.lookBits(12); + if (code === ccittEOF) { + return 1; + } + if (code >> 5 === 0) { + p = whiteTable1[code]; + } else { + p = whiteTable2[code >> 3]; + } + if (p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(1, 9, whiteTable2); + if (result[0]) { + return result[1]; + } + result = this.findTableCode(11, 12, whiteTable1); + if (result[0]) { + return result[1]; + } + } + info('bad white code'); + this.eatBits(1); + return 1; + }; + CCITTFaxStream.prototype.getBlackCode = function ccittFaxStreamGetBlackCode() { + var code, p; + if (this.eoblock) { + code = this.lookBits(13); + if (code === ccittEOF) { + return 1; + } + if (code >> 7 === 0) { + p = blackTable1[code]; + } else if (code >> 9 === 0 && code >> 7 !== 0) { + p = blackTable2[(code >> 1) - 64]; + } else { + p = blackTable3[code >> 7]; + } + if (p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(2, 6, blackTable3); + if (result[0]) { + return result[1]; + } + result = this.findTableCode(7, 12, blackTable2, 64); + if (result[0]) { + return result[1]; + } + result = this.findTableCode(10, 13, blackTable1); + if (result[0]) { + return result[1]; + } + } + info('bad black code'); + this.eatBits(1); + return 1; + }; + CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) { + var c; + while (this.inputBits < n) { + if ((c = this.str.getByte()) === -1) { + if (this.inputBits === 0) { + return ccittEOF; + } + return this.inputBuf << n - this.inputBits & 0xFFFF >> 16 - n; + } + this.inputBuf = this.inputBuf << 8 | c; + this.inputBits += 8; + } + return this.inputBuf >> this.inputBits - n & 0xFFFF >> 16 - n; + }; + CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) { + if ((this.inputBits -= n) < 0) { + this.inputBits = 0; + } + }; + return CCITTFaxStream; +}(); +var LZWStream = function LZWStreamClosure() { + function LZWStream(str, maybeLength, earlyChange) { + this.str = str; + this.dict = str.dict; + this.cachedData = 0; + this.bitsCached = 0; + var maxLzwDictionarySize = 4096; + var lzwState = { + earlyChange: earlyChange, + codeLength: 9, + nextCode: 258, + dictionaryValues: new Uint8Array(maxLzwDictionarySize), + dictionaryLengths: new Uint16Array(maxLzwDictionarySize), + dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), + currentSequence: new Uint8Array(maxLzwDictionarySize), + currentSequenceLength: 0 + }; + for (var i = 0; i < 256; ++i) { + lzwState.dictionaryValues[i] = i; + lzwState.dictionaryLengths[i] = 1; + } + this.lzwState = lzwState; + DecodeStream.call(this, maybeLength); + } + LZWStream.prototype = Object.create(DecodeStream.prototype); + LZWStream.prototype.readBits = function LZWStream_readBits(n) { + var bitsCached = this.bitsCached; + var cachedData = this.cachedData; + while (bitsCached < n) { + var c = this.str.getByte(); + if (c === -1) { + this.eof = true; + return null; + } + cachedData = cachedData << 8 | c; + bitsCached += 8; + } + this.bitsCached = bitsCached -= n; + this.cachedData = cachedData; + this.lastCode = null; + return cachedData >>> bitsCached & (1 << n) - 1; + }; + LZWStream.prototype.readBlock = function LZWStream_readBlock() { + var blockSize = 512; + var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize; + var i, j, q; + var lzwState = this.lzwState; + if (!lzwState) { + return; + } + var earlyChange = lzwState.earlyChange; + var nextCode = lzwState.nextCode; + var dictionaryValues = lzwState.dictionaryValues; + var dictionaryLengths = lzwState.dictionaryLengths; + var dictionaryPrevCodes = lzwState.dictionaryPrevCodes; + var codeLength = lzwState.codeLength; + var prevCode = lzwState.prevCode; + var currentSequence = lzwState.currentSequence; + var currentSequenceLength = lzwState.currentSequenceLength; + var decodedLength = 0; + var currentBufferLength = this.bufferLength; + var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + for (i = 0; i < blockSize; i++) { + var code = this.readBits(codeLength); + var hasPrev = currentSequenceLength > 0; + if (code < 256) { + currentSequence[0] = code; + currentSequenceLength = 1; + } else if (code >= 258) { + if (code < nextCode) { + currentSequenceLength = dictionaryLengths[code]; + for (j = currentSequenceLength - 1, q = code; j >= 0; j--) { + currentSequence[j] = dictionaryValues[q]; + q = dictionaryPrevCodes[q]; + } + } else { + currentSequence[currentSequenceLength++] = currentSequence[0]; + } + } else if (code === 256) { + codeLength = 9; + nextCode = 258; + currentSequenceLength = 0; + continue; + } else { + this.eof = true; + delete this.lzwState; + break; + } + if (hasPrev) { + dictionaryPrevCodes[nextCode] = prevCode; + dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; + dictionaryValues[nextCode] = currentSequence[0]; + nextCode++; + codeLength = nextCode + earlyChange & nextCode + earlyChange - 1 ? codeLength : Math.min(Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1, 12) | 0; + } + prevCode = code; + decodedLength += currentSequenceLength; + if (estimatedDecodedSize < decodedLength) { + do { + estimatedDecodedSize += decodedSizeDelta; + } while (estimatedDecodedSize < decodedLength); + buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + } + for (j = 0; j < currentSequenceLength; j++) { + buffer[currentBufferLength++] = currentSequence[j]; + } + } + lzwState.nextCode = nextCode; + lzwState.codeLength = codeLength; + lzwState.prevCode = prevCode; + lzwState.currentSequenceLength = currentSequenceLength; + this.bufferLength = currentBufferLength; + }; + return LZWStream; +}(); +var NullStream = function NullStreamClosure() { + function NullStream() { + Stream.call(this, new Uint8Array(0)); + } + NullStream.prototype = Stream.prototype; + return NullStream; +}(); +exports.Ascii85Stream = Ascii85Stream; +exports.AsciiHexStream = AsciiHexStream; +exports.CCITTFaxStream = CCITTFaxStream; +exports.DecryptStream = DecryptStream; +exports.DecodeStream = DecodeStream; +exports.FlateStream = FlateStream; +exports.Jbig2Stream = Jbig2Stream; +exports.JpegStream = JpegStream; +exports.JpxStream = JpxStream; +exports.NullStream = NullStream; +exports.PredictorStream = PredictorStream; +exports.RunLengthStream = RunLengthStream; +exports.Stream = Stream; +exports.StreamsSequenceStream = StreamsSequenceStream; +exports.StringStream = StringStream; +exports.LZWStream = LZWStream; + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreFunction = __w_pdfjs_require__(6); +var error = sharedUtil.error; +var info = sharedUtil.info; +var isArray = sharedUtil.isArray; +var isString = sharedUtil.isString; +var shadow = sharedUtil.shadow; +var warn = sharedUtil.warn; +var isDict = corePrimitives.isDict; +var isName = corePrimitives.isName; +var isStream = corePrimitives.isStream; +var PDFFunction = coreFunction.PDFFunction; +var ColorSpace = function ColorSpaceClosure() { + function resizeRgbImage(src, bpc, w1, h1, w2, h2, alpha01, dest) { + var COMPONENTS = 3; + alpha01 = alpha01 !== 1 ? 0 : alpha01; + var xRatio = w1 / w2; + var yRatio = h1 / h2; + var i, j, py, newIndex = 0, oldIndex; + var xScaled = new Uint16Array(w2); + var w1Scanline = w1 * COMPONENTS; + for (i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio) * COMPONENTS; + } + for (i = 0; i < h2; i++) { + py = Math.floor(i * yRatio) * w1Scanline; + for (j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + dest[newIndex++] = src[oldIndex++]; + dest[newIndex++] = src[oldIndex++]; + dest[newIndex++] = src[oldIndex++]; + newIndex += alpha01; + } + } + } + function ColorSpace() { + error('should not call ColorSpace constructor'); + } + ColorSpace.prototype = { + getRgb: function ColorSpace_getRgb(src, srcOffset) { + var rgb = new Uint8Array(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; + }, + getRgbItem: function ColorSpace_getRgbItem(src, srcOffset, dest, destOffset) { + error('Should not call ColorSpace.getRgbItem'); + }, + getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + error('Should not call ColorSpace.getRgbBuffer'); + }, + getOutputLength: function ColorSpace_getOutputLength(inputLength, alpha01) { + error('Should not call ColorSpace.getOutputLength'); + }, + isPassthrough: function ColorSpace_isPassthrough(bits) { + return false; + }, + fillRgb: function ColorSpace_fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) { + var count = originalWidth * originalHeight; + var rgbBuf = null; + var numComponentColors = 1 << bpc; + var needsResizing = originalHeight !== height || originalWidth !== width; + var i, ii; + if (this.isPassthrough(bpc)) { + rgbBuf = comps; + } else if (this.numComps === 1 && count > numComponentColors && this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') { + var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors); + var key; + for (i = 0; i < numComponentColors; i++) { + allColors[i] = i; + } + var colorMap = new Uint8Array(numComponentColors * 3); + this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, 0); + var destPos, rgbPos; + if (!needsResizing) { + destPos = 0; + for (i = 0; i < count; ++i) { + key = comps[i] * 3; + dest[destPos++] = colorMap[key]; + dest[destPos++] = colorMap[key + 1]; + dest[destPos++] = colorMap[key + 2]; + destPos += alpha01; + } + } else { + rgbBuf = new Uint8Array(count * 3); + rgbPos = 0; + for (i = 0; i < count; ++i) { + key = comps[i] * 3; + rgbBuf[rgbPos++] = colorMap[key]; + rgbBuf[rgbPos++] = colorMap[key + 1]; + rgbBuf[rgbPos++] = colorMap[key + 2]; + } + } + } else { + if (!needsResizing) { + this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01); + } else { + rgbBuf = new Uint8Array(count * 3); + this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, 0); + } + } + if (rgbBuf) { + if (needsResizing) { + resizeRgbImage(rgbBuf, bpc, originalWidth, originalHeight, width, height, alpha01, dest); + } else { + rgbPos = 0; + destPos = 0; + for (i = 0, ii = width * actualHeight; i < ii; i++) { + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + destPos += alpha01; + } + } + } + }, + usesZeroToOneRange: true + }; + ColorSpace.parse = function ColorSpace_parse(cs, xref, res) { + var IR = ColorSpace.parseToIR(cs, xref, res); + if (IR instanceof AlternateCS) { + return IR; + } + return ColorSpace.fromIR(IR); + }; + ColorSpace.fromIR = function ColorSpace_fromIR(IR) { + var name = isArray(IR) ? IR[0] : IR; + var whitePoint, blackPoint, gamma; + switch (name) { + case 'DeviceGrayCS': + return this.singletons.gray; + case 'DeviceRgbCS': + return this.singletons.rgb; + case 'DeviceCmykCS': + return this.singletons.cmyk; + case 'CalGrayCS': + whitePoint = IR[1]; + blackPoint = IR[2]; + gamma = IR[3]; + return new CalGrayCS(whitePoint, blackPoint, gamma); + case 'CalRGBCS': + whitePoint = IR[1]; + blackPoint = IR[2]; + gamma = IR[3]; + var matrix = IR[4]; + return new CalRGBCS(whitePoint, blackPoint, gamma, matrix); + case 'PatternCS': + var basePatternCS = IR[1]; + if (basePatternCS) { + basePatternCS = ColorSpace.fromIR(basePatternCS); + } + return new PatternCS(basePatternCS); + case 'IndexedCS': + var baseIndexedCS = IR[1]; + var hiVal = IR[2]; + var lookup = IR[3]; + return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup); + case 'AlternateCS': + var numComps = IR[1]; + var alt = IR[2]; + var tintFnIR = IR[3]; + return new AlternateCS(numComps, ColorSpace.fromIR(alt), PDFFunction.fromIR(tintFnIR)); + case 'LabCS': + whitePoint = IR[1]; + blackPoint = IR[2]; + var range = IR[3]; + return new LabCS(whitePoint, blackPoint, range); + default: + error('Unknown name ' + name); + } + return null; + }; + ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) { + if (isName(cs)) { + var colorSpaces = res.get('ColorSpace'); + if (isDict(colorSpaces)) { + var refcs = colorSpaces.get(cs.name); + if (refcs) { + cs = refcs; + } + } + } + cs = xref.fetchIfRef(cs); + if (isName(cs)) { + switch (cs.name) { + case 'DeviceGray': + case 'G': + return 'DeviceGrayCS'; + case 'DeviceRGB': + case 'RGB': + return 'DeviceRgbCS'; + case 'DeviceCMYK': + case 'CMYK': + return 'DeviceCmykCS'; + case 'Pattern': + return [ + 'PatternCS', + null + ]; + default: + error('unrecognized colorspace ' + cs.name); + } + } else if (isArray(cs)) { + var mode = xref.fetchIfRef(cs[0]).name; + var numComps, params, alt, whitePoint, blackPoint, gamma; + switch (mode) { + case 'DeviceGray': + case 'G': + return 'DeviceGrayCS'; + case 'DeviceRGB': + case 'RGB': + return 'DeviceRgbCS'; + case 'DeviceCMYK': + case 'CMYK': + return 'DeviceCmykCS'; + case 'CalGray': + params = xref.fetchIfRef(cs[1]); + whitePoint = params.getArray('WhitePoint'); + blackPoint = params.getArray('BlackPoint'); + gamma = params.get('Gamma'); + return [ + 'CalGrayCS', + whitePoint, + blackPoint, + gamma + ]; + case 'CalRGB': + params = xref.fetchIfRef(cs[1]); + whitePoint = params.getArray('WhitePoint'); + blackPoint = params.getArray('BlackPoint'); + gamma = params.getArray('Gamma'); + var matrix = params.getArray('Matrix'); + return [ + 'CalRGBCS', + whitePoint, + blackPoint, + gamma, + matrix + ]; + case 'ICCBased': + var stream = xref.fetchIfRef(cs[1]); + var dict = stream.dict; + numComps = dict.get('N'); + alt = dict.get('Alternate'); + if (alt) { + var altIR = ColorSpace.parseToIR(alt, xref, res); + var altCS = ColorSpace.fromIR(altIR); + if (altCS.numComps === numComps) { + return altIR; + } + warn('ICCBased color space: Ignoring incorrect /Alternate entry.'); + } + if (numComps === 1) { + return 'DeviceGrayCS'; + } else if (numComps === 3) { + return 'DeviceRgbCS'; + } else if (numComps === 4) { + return 'DeviceCmykCS'; + } + break; + case 'Pattern': + var basePatternCS = cs[1] || null; + if (basePatternCS) { + basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res); + } + return [ + 'PatternCS', + basePatternCS + ]; + case 'Indexed': + case 'I': + var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res); + var hiVal = xref.fetchIfRef(cs[2]) + 1; + var lookup = xref.fetchIfRef(cs[3]); + if (isStream(lookup)) { + lookup = lookup.getBytes(); + } + return [ + 'IndexedCS', + baseIndexedCS, + hiVal, + lookup + ]; + case 'Separation': + case 'DeviceN': + var name = xref.fetchIfRef(cs[1]); + numComps = isArray(name) ? name.length : 1; + alt = ColorSpace.parseToIR(cs[2], xref, res); + var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3])); + return [ + 'AlternateCS', + numComps, + alt, + tintFnIR + ]; + case 'Lab': + params = xref.fetchIfRef(cs[1]); + whitePoint = params.getArray('WhitePoint'); + blackPoint = params.getArray('BlackPoint'); + var range = params.getArray('Range'); + return [ + 'LabCS', + whitePoint, + blackPoint, + range + ]; + default: + error('unimplemented color space object "' + mode + '"'); + } + } else { + error('unrecognized color space object: "' + cs + '"'); + } + return null; + }; + ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) { + if (!isArray(decode)) { + return true; + } + if (n * 2 !== decode.length) { + warn('The decode map is not the correct length'); + return true; + } + for (var i = 0, ii = decode.length; i < ii; i += 2) { + if (decode[i] !== 0 || decode[i + 1] !== 1) { + return false; + } + } + return true; + }; + ColorSpace.singletons = { + get gray() { + return shadow(this, 'gray', new DeviceGrayCS()); + }, + get rgb() { + return shadow(this, 'rgb', new DeviceRgbCS()); + }, + get cmyk() { + return shadow(this, 'cmyk', new DeviceCmykCS()); + } + }; + return ColorSpace; +}(); +var AlternateCS = function AlternateCSClosure() { + function AlternateCS(numComps, base, tintFn) { + this.name = 'Alternate'; + this.numComps = numComps; + this.defaultColor = new Float32Array(numComps); + for (var i = 0; i < numComps; ++i) { + this.defaultColor[i] = 1; + } + this.base = base; + this.tintFn = tintFn; + this.tmpBuf = new Float32Array(base.numComps); + } + AlternateCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function AlternateCS_getRgbItem(src, srcOffset, dest, destOffset) { + var tmpBuf = this.tmpBuf; + this.tintFn(src, srcOffset, tmpBuf, 0); + this.base.getRgbItem(tmpBuf, 0, dest, destOffset); + }, + getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + var tintFn = this.tintFn; + var base = this.base; + var scale = 1 / ((1 << bits) - 1); + var baseNumComps = base.numComps; + var usesZeroToOneRange = base.usesZeroToOneRange; + var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && alpha01 === 0; + var pos = isPassthrough ? destOffset : 0; + var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count); + var numComps = this.numComps; + var scaled = new Float32Array(numComps); + var tinted = new Float32Array(baseNumComps); + var i, j; + for (i = 0; i < count; i++) { + for (j = 0; j < numComps; j++) { + scaled[j] = src[srcOffset++] * scale; + } + tintFn(scaled, 0, tinted, 0); + if (usesZeroToOneRange) { + for (j = 0; j < baseNumComps; j++) { + baseBuf[pos++] = tinted[j] * 255; + } + } else { + base.getRgbItem(tinted, 0, baseBuf, pos); + pos += baseNumComps; + } + } + if (!isPassthrough) { + base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); + } + }, + getOutputLength: function AlternateCS_getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * this.base.numComps / this.numComps, alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return AlternateCS; +}(); +var PatternCS = function PatternCSClosure() { + function PatternCS(baseCS) { + this.name = 'Pattern'; + this.base = baseCS; + } + PatternCS.prototype = {}; + return PatternCS; +}(); +var IndexedCS = function IndexedCSClosure() { + function IndexedCS(base, highVal, lookup) { + this.name = 'Indexed'; + this.numComps = 1; + this.defaultColor = new Uint8Array(this.numComps); + this.base = base; + this.highVal = highVal; + var baseNumComps = base.numComps; + var length = baseNumComps * highVal; + if (isStream(lookup)) { + this.lookup = new Uint8Array(length); + var bytes = lookup.getBytes(length); + this.lookup.set(bytes); + } else if (isString(lookup)) { + this.lookup = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + this.lookup[i] = lookup.charCodeAt(i); + } + } else if (lookup instanceof Uint8Array || lookup instanceof Array) { + this.lookup = lookup; + } else { + error('Unrecognized lookup table: ' + lookup); + } + } + IndexedCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function IndexedCS_getRgbItem(src, srcOffset, dest, destOffset) { + var numComps = this.base.numComps; + var start = src[srcOffset] * numComps; + this.base.getRgbItem(this.lookup, start, dest, destOffset); + }, + getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + var base = this.base; + var numComps = base.numComps; + var outputDelta = base.getOutputLength(numComps, alpha01); + var lookup = this.lookup; + for (var i = 0; i < count; ++i) { + var lookupPos = src[srcOffset++] * numComps; + base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01); + destOffset += outputDelta; + } + }, + getOutputLength: function IndexedCS_getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * this.base.numComps, alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) { + return true; + }, + usesZeroToOneRange: true + }; + return IndexedCS; +}(); +var DeviceGrayCS = function DeviceGrayCSClosure() { + function DeviceGrayCS() { + this.name = 'DeviceGray'; + this.numComps = 1; + this.defaultColor = new Float32Array(this.numComps); + } + DeviceGrayCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset, dest, destOffset) { + var c = src[srcOffset] * 255 | 0; + c = c < 0 ? 0 : c > 255 ? 255 : c; + dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c; + }, + getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < count; ++i) { + var c = scale * src[j++] | 0; + dest[q++] = c; + dest[q++] = c; + dest[q++] = c; + q += alpha01; + } + }, + getOutputLength: function DeviceGrayCS_getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return DeviceGrayCS; +}(); +var DeviceRgbCS = function DeviceRgbCSClosure() { + function DeviceRgbCS() { + this.name = 'DeviceRGB'; + this.numComps = 3; + this.defaultColor = new Float32Array(this.numComps); + } + DeviceRgbCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset, dest, destOffset) { + var r = src[srcOffset] * 255 | 0; + var g = src[srcOffset + 1] * 255 | 0; + var b = src[srcOffset + 2] * 255 | 0; + dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r; + dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g; + dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b; + }, + getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + if (bits === 8 && alpha01 === 0) { + dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset); + return; + } + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < count; ++i) { + dest[q++] = scale * src[j++] | 0; + dest[q++] = scale * src[j++] | 0; + dest[q++] = scale * src[j++] | 0; + q += alpha01; + } + }, + getOutputLength: function DeviceRgbCS_getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01) / 3 | 0; + }, + isPassthrough: function DeviceRgbCS_isPassthrough(bits) { + return bits === 8; + }, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return DeviceRgbCS; +}(); +var DeviceCmykCS = function DeviceCmykCSClosure() { + function convertToRgb(src, srcOffset, srcScale, dest, destOffset) { + var c = src[srcOffset + 0] * srcScale; + var m = src[srcOffset + 1] * srcScale; + var y = src[srcOffset + 2] * srcScale; + var k = src[srcOffset + 3] * srcScale; + var r = c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k + -285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y + -17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) + k * (-21.86122147463605 * k - 189.48180835922747) + 255 | 0; + var g = c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k + -79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + k * (-20.737325471181034 * k - 187.80453709719578) + 255 | 0; + var b = c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k + -14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k + -193.58209356861505) + k * (-22.33816807309886 * k - 180.12613974708367) + 255 | 0; + dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r; + dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g; + dest[destOffset + 2] = b > 255 ? 255 : b < 0 ? 0 : b; + } + function DeviceCmykCS() { + this.name = 'DeviceCMYK'; + this.numComps = 4; + this.defaultColor = new Float32Array(this.numComps); + this.defaultColor[3] = 1; + } + DeviceCmykCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset, dest, destOffset) { + convertToRgb(src, srcOffset, 1, dest, destOffset); + }, + getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + var scale = 1 / ((1 << bits) - 1); + for (var i = 0; i < count; i++) { + convertToRgb(src, srcOffset, scale, dest, destOffset); + srcOffset += 4; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function DeviceCmykCS_getOutputLength(inputLength, alpha01) { + return inputLength / 4 * (3 + alpha01) | 0; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return DeviceCmykCS; +}(); +var CalGrayCS = function CalGrayCSClosure() { + function CalGrayCS(whitePoint, blackPoint, gamma) { + this.name = 'CalGray'; + this.numComps = 1; + this.defaultColor = new Float32Array(this.numComps); + if (!whitePoint) { + error('WhitePoint missing - required for color space CalGray'); + } + blackPoint = blackPoint || [ + 0, + 0, + 0 + ]; + gamma = gamma || 1; + this.XW = whitePoint[0]; + this.YW = whitePoint[1]; + this.ZW = whitePoint[2]; + this.XB = blackPoint[0]; + this.YB = blackPoint[1]; + this.ZB = blackPoint[2]; + this.G = gamma; + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + error('Invalid WhitePoint components for ' + this.name + ', no fallback available'); + } + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info('Invalid BlackPoint for ' + this.name + ', falling back to default'); + this.XB = this.YB = this.ZB = 0; + } + if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { + warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB + ', ZB: ' + this.ZB + ', only default values are supported.'); + } + if (this.G < 1) { + info('Invalid Gamma: ' + this.G + ' for ' + this.name + ', falling back to default'); + this.G = 1; + } + } + function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { + var A = src[srcOffset] * scale; + var AG = Math.pow(A, cs.G); + var L = cs.YW * AG; + var val = Math.max(295.8 * Math.pow(L, 0.333333333333333333) - 40.8, 0) | 0; + dest[destOffset] = val; + dest[destOffset + 1] = val; + dest[destOffset + 2] = val; + } + CalGrayCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function CalGrayCS_getRgbItem(src, srcOffset, dest, destOffset) { + convertToRgb(this, src, srcOffset, dest, destOffset, 1); + }, + getRgbBuffer: function CalGrayCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + var scale = 1 / ((1 << bits) - 1); + for (var i = 0; i < count; ++i) { + convertToRgb(this, src, srcOffset, dest, destOffset, scale); + srcOffset += 1; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function CalGrayCS_getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return CalGrayCS; +}(); +var CalRGBCS = function CalRGBCSClosure() { + var BRADFORD_SCALE_MATRIX = new Float32Array([ + 0.8951, + 0.2664, + -0.1614, + -0.7502, + 1.7135, + 0.0367, + 0.0389, + -0.0685, + 1.0296 + ]); + var BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([ + 0.9869929, + -0.1470543, + 0.1599627, + 0.4323053, + 0.5183603, + 0.0492912, + -0.0085287, + 0.0400428, + 0.9684867 + ]); + var SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([ + 3.2404542, + -1.5371385, + -0.4985314, + -0.9692660, + 1.8760108, + 0.0415560, + 0.0556434, + -0.2040259, + 1.0572252 + ]); + var FLAT_WHITEPOINT_MATRIX = new Float32Array([ + 1, + 1, + 1 + ]); + var tempNormalizeMatrix = new Float32Array(3); + var tempConvertMatrix1 = new Float32Array(3); + var tempConvertMatrix2 = new Float32Array(3); + var DECODE_L_CONSTANT = Math.pow((8 + 16) / 116, 3) / 8.0; + function CalRGBCS(whitePoint, blackPoint, gamma, matrix) { + this.name = 'CalRGB'; + this.numComps = 3; + this.defaultColor = new Float32Array(this.numComps); + if (!whitePoint) { + error('WhitePoint missing - required for color space CalRGB'); + } + blackPoint = blackPoint || new Float32Array(3); + gamma = gamma || new Float32Array([ + 1, + 1, + 1 + ]); + matrix = matrix || new Float32Array([ + 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 + ]); + var XW = whitePoint[0]; + var YW = whitePoint[1]; + var ZW = whitePoint[2]; + this.whitePoint = whitePoint; + var XB = blackPoint[0]; + var YB = blackPoint[1]; + var ZB = blackPoint[2]; + this.blackPoint = blackPoint; + this.GR = gamma[0]; + this.GG = gamma[1]; + this.GB = gamma[2]; + this.MXA = matrix[0]; + this.MYA = matrix[1]; + this.MZA = matrix[2]; + this.MXB = matrix[3]; + this.MYB = matrix[4]; + this.MZB = matrix[5]; + this.MXC = matrix[6]; + this.MYC = matrix[7]; + this.MZC = matrix[8]; + if (XW < 0 || ZW < 0 || YW !== 1) { + error('Invalid WhitePoint components for ' + this.name + ', no fallback available'); + } + if (XB < 0 || YB < 0 || ZB < 0) { + info('Invalid BlackPoint for ' + this.name + ' [' + XB + ', ' + YB + ', ' + ZB + '], falling back to default'); + this.blackPoint = new Float32Array(3); + } + if (this.GR < 0 || this.GG < 0 || this.GB < 0) { + info('Invalid Gamma [' + this.GR + ', ' + this.GG + ', ' + this.GB + '] for ' + this.name + ', falling back to default'); + this.GR = this.GG = this.GB = 1; + } + if (this.MXA < 0 || this.MYA < 0 || this.MZA < 0 || this.MXB < 0 || this.MYB < 0 || this.MZB < 0 || this.MXC < 0 || this.MYC < 0 || this.MZC < 0) { + info('Invalid Matrix for ' + this.name + ' [' + this.MXA + ', ' + this.MYA + ', ' + this.MZA + this.MXB + ', ' + this.MYB + ', ' + this.MZB + this.MXC + ', ' + this.MYC + ', ' + this.MZC + '], falling back to default'); + this.MXA = this.MYB = this.MZC = 1; + this.MXB = this.MYA = this.MZA = this.MXC = this.MYC = this.MZB = 0; + } + } + function matrixProduct(a, b, result) { + result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2]; + result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2]; + } + function convertToFlat(sourceWhitePoint, LMS, result) { + result[0] = LMS[0] * 1 / sourceWhitePoint[0]; + result[1] = LMS[1] * 1 / sourceWhitePoint[1]; + result[2] = LMS[2] * 1 / sourceWhitePoint[2]; + } + function convertToD65(sourceWhitePoint, LMS, result) { + var D65X = 0.95047; + var D65Y = 1; + var D65Z = 1.08883; + result[0] = LMS[0] * D65X / sourceWhitePoint[0]; + result[1] = LMS[1] * D65Y / sourceWhitePoint[1]; + result[2] = LMS[2] * D65Z / sourceWhitePoint[2]; + } + function sRGBTransferFunction(color) { + if (color <= 0.0031308) { + return adjustToRange(0, 1, 12.92 * color); + } + return adjustToRange(0, 1, (1 + 0.055) * Math.pow(color, 1 / 2.4) - 0.055); + } + function adjustToRange(min, max, value) { + return Math.max(min, Math.min(max, value)); + } + function decodeL(L) { + if (L < 0) { + return -decodeL(-L); + } + if (L > 8.0) { + return Math.pow((L + 16) / 116, 3); + } + return L * DECODE_L_CONSTANT; + } + function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) { + if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) { + result[0] = XYZ_Flat[0]; + result[1] = XYZ_Flat[1]; + result[2] = XYZ_Flat[2]; + return; + } + var zeroDecodeL = decodeL(0); + var X_DST = zeroDecodeL; + var X_SRC = decodeL(sourceBlackPoint[0]); + var Y_DST = zeroDecodeL; + var Y_SRC = decodeL(sourceBlackPoint[1]); + var Z_DST = zeroDecodeL; + var Z_SRC = decodeL(sourceBlackPoint[2]); + var X_Scale = (1 - X_DST) / (1 - X_SRC); + var X_Offset = 1 - X_Scale; + var Y_Scale = (1 - Y_DST) / (1 - Y_SRC); + var Y_Offset = 1 - Y_Scale; + var Z_Scale = (1 - Z_DST) / (1 - Z_SRC); + var Z_Offset = 1 - Z_Scale; + result[0] = XYZ_Flat[0] * X_Scale + X_Offset; + result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset; + result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset; + } + function normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) { + if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) { + result[0] = XYZ_In[0]; + result[1] = XYZ_In[1]; + result[2] = XYZ_In[2]; + return; + } + var LMS = result; + matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + var LMS_Flat = tempNormalizeMatrix; + convertToFlat(sourceWhitePoint, LMS, LMS_Flat); + matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result); + } + function normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) { + var LMS = result; + matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + var LMS_D65 = tempNormalizeMatrix; + convertToD65(sourceWhitePoint, LMS, LMS_D65); + matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result); + } + function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { + var A = adjustToRange(0, 1, src[srcOffset] * scale); + var B = adjustToRange(0, 1, src[srcOffset + 1] * scale); + var C = adjustToRange(0, 1, src[srcOffset + 2] * scale); + var AGR = Math.pow(A, cs.GR); + var BGG = Math.pow(B, cs.GG); + var CGB = Math.pow(C, cs.GB); + var X = cs.MXA * AGR + cs.MXB * BGG + cs.MXC * CGB; + var Y = cs.MYA * AGR + cs.MYB * BGG + cs.MYC * CGB; + var Z = cs.MZA * AGR + cs.MZB * BGG + cs.MZC * CGB; + var XYZ = tempConvertMatrix1; + XYZ[0] = X; + XYZ[1] = Y; + XYZ[2] = Z; + var XYZ_Flat = tempConvertMatrix2; + normalizeWhitePointToFlat(cs.whitePoint, XYZ, XYZ_Flat); + var XYZ_Black = tempConvertMatrix1; + compensateBlackPoint(cs.blackPoint, XYZ_Flat, XYZ_Black); + var XYZ_D65 = tempConvertMatrix2; + normalizeWhitePointToD65(FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65); + var SRGB = tempConvertMatrix1; + matrixProduct(SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB); + var sR = sRGBTransferFunction(SRGB[0]); + var sG = sRGBTransferFunction(SRGB[1]); + var sB = sRGBTransferFunction(SRGB[2]); + dest[destOffset] = Math.round(sR * 255); + dest[destOffset + 1] = Math.round(sG * 255); + dest[destOffset + 2] = Math.round(sB * 255); + } + CalRGBCS.prototype = { + getRgb: function CalRGBCS_getRgb(src, srcOffset) { + var rgb = new Uint8Array(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; + }, + getRgbItem: function CalRGBCS_getRgbItem(src, srcOffset, dest, destOffset) { + convertToRgb(this, src, srcOffset, dest, destOffset, 1); + }, + getRgbBuffer: function CalRGBCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + var scale = 1 / ((1 << bits) - 1); + for (var i = 0; i < count; ++i) { + convertToRgb(this, src, srcOffset, dest, destOffset, scale); + srcOffset += 3; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function CalRGBCS_getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01) / 3 | 0; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function CalRGBCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return CalRGBCS; +}(); +var LabCS = function LabCSClosure() { + function LabCS(whitePoint, blackPoint, range) { + this.name = 'Lab'; + this.numComps = 3; + this.defaultColor = new Float32Array(this.numComps); + if (!whitePoint) { + error('WhitePoint missing - required for color space Lab'); + } + blackPoint = blackPoint || [ + 0, + 0, + 0 + ]; + range = range || [ + -100, + 100, + -100, + 100 + ]; + this.XW = whitePoint[0]; + this.YW = whitePoint[1]; + this.ZW = whitePoint[2]; + this.amin = range[0]; + this.amax = range[1]; + this.bmin = range[2]; + this.bmax = range[3]; + this.XB = blackPoint[0]; + this.YB = blackPoint[1]; + this.ZB = blackPoint[2]; + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + error('Invalid WhitePoint components, no fallback available'); + } + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info('Invalid BlackPoint, falling back to default'); + this.XB = this.YB = this.ZB = 0; + } + if (this.amin > this.amax || this.bmin > this.bmax) { + info('Invalid Range, falling back to defaults'); + this.amin = -100; + this.amax = 100; + this.bmin = -100; + this.bmax = 100; + } + } + function fn_g(x) { + var result; + if (x >= 6 / 29) { + result = x * x * x; + } else { + result = 108 / 841 * (x - 4 / 29); + } + return result; + } + function decode(value, high1, low2, high2) { + return low2 + value * (high2 - low2) / high1; + } + function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) { + var Ls = src[srcOffset]; + var as = src[srcOffset + 1]; + var bs = src[srcOffset + 2]; + if (maxVal !== false) { + Ls = decode(Ls, maxVal, 0, 100); + as = decode(as, maxVal, cs.amin, cs.amax); + bs = decode(bs, maxVal, cs.bmin, cs.bmax); + } + as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as; + bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs; + var M = (Ls + 16) / 116; + var L = M + as / 500; + var N = M - bs / 200; + var X = cs.XW * fn_g(L); + var Y = cs.YW * fn_g(M); + var Z = cs.ZW * fn_g(N); + var r, g, b; + if (cs.ZW < 1) { + r = X * 3.1339 + Y * -1.6170 + Z * -0.4906; + g = X * -0.9785 + Y * 1.9160 + Z * 0.0333; + b = X * 0.0720 + Y * -0.2290 + Z * 1.4057; + } else { + r = X * 3.2406 + Y * -1.5372 + Z * -0.4986; + g = X * -0.9689 + Y * 1.8758 + Z * 0.0415; + b = X * 0.0557 + Y * -0.2040 + Z * 1.0570; + } + dest[destOffset] = r <= 0 ? 0 : r >= 1 ? 255 : Math.sqrt(r) * 255 | 0; + dest[destOffset + 1] = g <= 0 ? 0 : g >= 1 ? 255 : Math.sqrt(g) * 255 | 0; + dest[destOffset + 2] = b <= 0 ? 0 : b >= 1 ? 255 : Math.sqrt(b) * 255 | 0; + } + LabCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) { + convertToRgb(this, src, srcOffset, false, dest, destOffset); + }, + getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + var maxVal = (1 << bits) - 1; + for (var i = 0; i < count; i++) { + convertToRgb(this, src, srcOffset, maxVal, dest, destOffset); + srcOffset += 3; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function LabCS_getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01) / 3 | 0; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) { + return true; + }, + usesZeroToOneRange: false + }; + return LabCS; +}(); +exports.ColorSpace = ColorSpace; + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var ExpertEncoding = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'space', + 'exclamsmall', + 'Hungarumlautsmall', + '', + 'dollaroldstyle', + 'dollarsuperior', + 'ampersandsmall', + 'Acutesmall', + 'parenleftsuperior', + 'parenrightsuperior', + 'twodotenleader', + 'onedotenleader', + 'comma', + 'hyphen', + 'period', + 'fraction', + 'zerooldstyle', + 'oneoldstyle', + 'twooldstyle', + 'threeoldstyle', + 'fouroldstyle', + 'fiveoldstyle', + 'sixoldstyle', + 'sevenoldstyle', + 'eightoldstyle', + 'nineoldstyle', + 'colon', + 'semicolon', + 'commasuperior', + 'threequartersemdash', + 'periodsuperior', + 'questionsmall', + '', + 'asuperior', + 'bsuperior', + 'centsuperior', + 'dsuperior', + 'esuperior', + '', + '', + 'isuperior', + '', + '', + 'lsuperior', + 'msuperior', + 'nsuperior', + 'osuperior', + '', + '', + 'rsuperior', + 'ssuperior', + 'tsuperior', + '', + 'ff', + 'fi', + 'fl', + 'ffi', + 'ffl', + 'parenleftinferior', + '', + 'parenrightinferior', + 'Circumflexsmall', + 'hyphensuperior', + 'Gravesmall', + 'Asmall', + 'Bsmall', + 'Csmall', + 'Dsmall', + 'Esmall', + 'Fsmall', + 'Gsmall', + 'Hsmall', + 'Ismall', + 'Jsmall', + 'Ksmall', + 'Lsmall', + 'Msmall', + 'Nsmall', + 'Osmall', + 'Psmall', + 'Qsmall', + 'Rsmall', + 'Ssmall', + 'Tsmall', + 'Usmall', + 'Vsmall', + 'Wsmall', + 'Xsmall', + 'Ysmall', + 'Zsmall', + 'colonmonetary', + 'onefitted', + 'rupiah', + 'Tildesmall', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'exclamdownsmall', + 'centoldstyle', + 'Lslashsmall', + '', + '', + 'Scaronsmall', + 'Zcaronsmall', + 'Dieresissmall', + 'Brevesmall', + 'Caronsmall', + '', + 'Dotaccentsmall', + '', + '', + 'Macronsmall', + '', + '', + 'figuredash', + 'hypheninferior', + '', + '', + 'Ogoneksmall', + 'Ringsmall', + 'Cedillasmall', + '', + '', + '', + 'onequarter', + 'onehalf', + 'threequarters', + 'questiondownsmall', + 'oneeighth', + 'threeeighths', + 'fiveeighths', + 'seveneighths', + 'onethird', + 'twothirds', + '', + '', + 'zerosuperior', + 'onesuperior', + 'twosuperior', + 'threesuperior', + 'foursuperior', + 'fivesuperior', + 'sixsuperior', + 'sevensuperior', + 'eightsuperior', + 'ninesuperior', + 'zeroinferior', + 'oneinferior', + 'twoinferior', + 'threeinferior', + 'fourinferior', + 'fiveinferior', + 'sixinferior', + 'seveninferior', + 'eightinferior', + 'nineinferior', + 'centinferior', + 'dollarinferior', + 'periodinferior', + 'commainferior', + 'Agravesmall', + 'Aacutesmall', + 'Acircumflexsmall', + 'Atildesmall', + 'Adieresissmall', + 'Aringsmall', + 'AEsmall', + 'Ccedillasmall', + 'Egravesmall', + 'Eacutesmall', + 'Ecircumflexsmall', + 'Edieresissmall', + 'Igravesmall', + 'Iacutesmall', + 'Icircumflexsmall', + 'Idieresissmall', + 'Ethsmall', + 'Ntildesmall', + 'Ogravesmall', + 'Oacutesmall', + 'Ocircumflexsmall', + 'Otildesmall', + 'Odieresissmall', + 'OEsmall', + 'Oslashsmall', + 'Ugravesmall', + 'Uacutesmall', + 'Ucircumflexsmall', + 'Udieresissmall', + 'Yacutesmall', + 'Thornsmall', + 'Ydieresissmall' +]; +var MacExpertEncoding = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'space', + 'exclamsmall', + 'Hungarumlautsmall', + 'centoldstyle', + 'dollaroldstyle', + 'dollarsuperior', + 'ampersandsmall', + 'Acutesmall', + 'parenleftsuperior', + 'parenrightsuperior', + 'twodotenleader', + 'onedotenleader', + 'comma', + 'hyphen', + 'period', + 'fraction', + 'zerooldstyle', + 'oneoldstyle', + 'twooldstyle', + 'threeoldstyle', + 'fouroldstyle', + 'fiveoldstyle', + 'sixoldstyle', + 'sevenoldstyle', + 'eightoldstyle', + 'nineoldstyle', + 'colon', + 'semicolon', + '', + 'threequartersemdash', + '', + 'questionsmall', + '', + '', + '', + '', + 'Ethsmall', + '', + '', + 'onequarter', + 'onehalf', + 'threequarters', + 'oneeighth', + 'threeeighths', + 'fiveeighths', + 'seveneighths', + 'onethird', + 'twothirds', + '', + '', + '', + '', + '', + '', + 'ff', + 'fi', + 'fl', + 'ffi', + 'ffl', + 'parenleftinferior', + '', + 'parenrightinferior', + 'Circumflexsmall', + 'hypheninferior', + 'Gravesmall', + 'Asmall', + 'Bsmall', + 'Csmall', + 'Dsmall', + 'Esmall', + 'Fsmall', + 'Gsmall', + 'Hsmall', + 'Ismall', + 'Jsmall', + 'Ksmall', + 'Lsmall', + 'Msmall', + 'Nsmall', + 'Osmall', + 'Psmall', + 'Qsmall', + 'Rsmall', + 'Ssmall', + 'Tsmall', + 'Usmall', + 'Vsmall', + 'Wsmall', + 'Xsmall', + 'Ysmall', + 'Zsmall', + 'colonmonetary', + 'onefitted', + 'rupiah', + 'Tildesmall', + '', + '', + 'asuperior', + 'centsuperior', + '', + '', + '', + '', + 'Aacutesmall', + 'Agravesmall', + 'Acircumflexsmall', + 'Adieresissmall', + 'Atildesmall', + 'Aringsmall', + 'Ccedillasmall', + 'Eacutesmall', + 'Egravesmall', + 'Ecircumflexsmall', + 'Edieresissmall', + 'Iacutesmall', + 'Igravesmall', + 'Icircumflexsmall', + 'Idieresissmall', + 'Ntildesmall', + 'Oacutesmall', + 'Ogravesmall', + 'Ocircumflexsmall', + 'Odieresissmall', + 'Otildesmall', + 'Uacutesmall', + 'Ugravesmall', + 'Ucircumflexsmall', + 'Udieresissmall', + '', + 'eightsuperior', + 'fourinferior', + 'threeinferior', + 'sixinferior', + 'eightinferior', + 'seveninferior', + 'Scaronsmall', + '', + 'centinferior', + 'twoinferior', + '', + 'Dieresissmall', + '', + 'Caronsmall', + 'osuperior', + 'fiveinferior', + '', + 'commainferior', + 'periodinferior', + 'Yacutesmall', + '', + 'dollarinferior', + '', + 'Thornsmall', + '', + 'nineinferior', + 'zeroinferior', + 'Zcaronsmall', + 'AEsmall', + 'Oslashsmall', + 'questiondownsmall', + 'oneinferior', + 'Lslashsmall', + '', + '', + '', + '', + '', + '', + 'Cedillasmall', + '', + '', + '', + '', + '', + 'OEsmall', + 'figuredash', + 'hyphensuperior', + '', + '', + '', + '', + 'exclamdownsmall', + '', + 'Ydieresissmall', + '', + 'onesuperior', + 'twosuperior', + 'threesuperior', + 'foursuperior', + 'fivesuperior', + 'sixsuperior', + 'sevensuperior', + 'ninesuperior', + 'zerosuperior', + '', + 'esuperior', + 'rsuperior', + 'tsuperior', + '', + '', + 'isuperior', + 'ssuperior', + 'dsuperior', + '', + '', + '', + '', + '', + 'lsuperior', + 'Ogoneksmall', + 'Brevesmall', + 'Macronsmall', + 'bsuperior', + 'nsuperior', + 'msuperior', + 'commasuperior', + 'periodsuperior', + 'Dotaccentsmall', + 'Ringsmall' +]; +var MacRomanEncoding = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'space', + 'exclam', + 'quotedbl', + 'numbersign', + 'dollar', + 'percent', + 'ampersand', + 'quotesingle', + 'parenleft', + 'parenright', + 'asterisk', + 'plus', + 'comma', + 'hyphen', + 'period', + 'slash', + 'zero', + 'one', + 'two', + 'three', + 'four', + 'five', + 'six', + 'seven', + 'eight', + 'nine', + 'colon', + 'semicolon', + 'less', + 'equal', + 'greater', + 'question', + 'at', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + 'bracketleft', + 'backslash', + 'bracketright', + 'asciicircum', + 'underscore', + 'grave', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'braceleft', + 'bar', + 'braceright', + 'asciitilde', + '', + 'Adieresis', + 'Aring', + 'Ccedilla', + 'Eacute', + 'Ntilde', + 'Odieresis', + 'Udieresis', + 'aacute', + 'agrave', + 'acircumflex', + 'adieresis', + 'atilde', + 'aring', + 'ccedilla', + 'eacute', + 'egrave', + 'ecircumflex', + 'edieresis', + 'iacute', + 'igrave', + 'icircumflex', + 'idieresis', + 'ntilde', + 'oacute', + 'ograve', + 'ocircumflex', + 'odieresis', + 'otilde', + 'uacute', + 'ugrave', + 'ucircumflex', + 'udieresis', + 'dagger', + 'degree', + 'cent', + 'sterling', + 'section', + 'bullet', + 'paragraph', + 'germandbls', + 'registered', + 'copyright', + 'trademark', + 'acute', + 'dieresis', + 'notequal', + 'AE', + 'Oslash', + 'infinity', + 'plusminus', + 'lessequal', + 'greaterequal', + 'yen', + 'mu', + 'partialdiff', + 'summation', + 'product', + 'pi', + 'integral', + 'ordfeminine', + 'ordmasculine', + 'Omega', + 'ae', + 'oslash', + 'questiondown', + 'exclamdown', + 'logicalnot', + 'radical', + 'florin', + 'approxequal', + 'Delta', + 'guillemotleft', + 'guillemotright', + 'ellipsis', + 'space', + 'Agrave', + 'Atilde', + 'Otilde', + 'OE', + 'oe', + 'endash', + 'emdash', + 'quotedblleft', + 'quotedblright', + 'quoteleft', + 'quoteright', + 'divide', + 'lozenge', + 'ydieresis', + 'Ydieresis', + 'fraction', + 'currency', + 'guilsinglleft', + 'guilsinglright', + 'fi', + 'fl', + 'daggerdbl', + 'periodcentered', + 'quotesinglbase', + 'quotedblbase', + 'perthousand', + 'Acircumflex', + 'Ecircumflex', + 'Aacute', + 'Edieresis', + 'Egrave', + 'Iacute', + 'Icircumflex', + 'Idieresis', + 'Igrave', + 'Oacute', + 'Ocircumflex', + 'apple', + 'Ograve', + 'Uacute', + 'Ucircumflex', + 'Ugrave', + 'dotlessi', + 'circumflex', + 'tilde', + 'macron', + 'breve', + 'dotaccent', + 'ring', + 'cedilla', + 'hungarumlaut', + 'ogonek', + 'caron' +]; +var StandardEncoding = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'space', + 'exclam', + 'quotedbl', + 'numbersign', + 'dollar', + 'percent', + 'ampersand', + 'quoteright', + 'parenleft', + 'parenright', + 'asterisk', + 'plus', + 'comma', + 'hyphen', + 'period', + 'slash', + 'zero', + 'one', + 'two', + 'three', + 'four', + 'five', + 'six', + 'seven', + 'eight', + 'nine', + 'colon', + 'semicolon', + 'less', + 'equal', + 'greater', + 'question', + 'at', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + 'bracketleft', + 'backslash', + 'bracketright', + 'asciicircum', + 'underscore', + 'quoteleft', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'braceleft', + 'bar', + 'braceright', + 'asciitilde', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'exclamdown', + 'cent', + 'sterling', + 'fraction', + 'yen', + 'florin', + 'section', + 'currency', + 'quotesingle', + 'quotedblleft', + 'guillemotleft', + 'guilsinglleft', + 'guilsinglright', + 'fi', + 'fl', + '', + 'endash', + 'dagger', + 'daggerdbl', + 'periodcentered', + '', + 'paragraph', + 'bullet', + 'quotesinglbase', + 'quotedblbase', + 'quotedblright', + 'guillemotright', + 'ellipsis', + 'perthousand', + '', + 'questiondown', + '', + 'grave', + 'acute', + 'circumflex', + 'tilde', + 'macron', + 'breve', + 'dotaccent', + 'dieresis', + '', + 'ring', + 'cedilla', + '', + 'hungarumlaut', + 'ogonek', + 'caron', + 'emdash', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'AE', + '', + 'ordfeminine', + '', + '', + '', + '', + 'Lslash', + 'Oslash', + 'OE', + 'ordmasculine', + '', + '', + '', + '', + '', + 'ae', + '', + '', + '', + 'dotlessi', + '', + '', + 'lslash', + 'oslash', + 'oe', + 'germandbls' +]; +var WinAnsiEncoding = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'space', + 'exclam', + 'quotedbl', + 'numbersign', + 'dollar', + 'percent', + 'ampersand', + 'quotesingle', + 'parenleft', + 'parenright', + 'asterisk', + 'plus', + 'comma', + 'hyphen', + 'period', + 'slash', + 'zero', + 'one', + 'two', + 'three', + 'four', + 'five', + 'six', + 'seven', + 'eight', + 'nine', + 'colon', + 'semicolon', + 'less', + 'equal', + 'greater', + 'question', + 'at', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + 'bracketleft', + 'backslash', + 'bracketright', + 'asciicircum', + 'underscore', + 'grave', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'braceleft', + 'bar', + 'braceright', + 'asciitilde', + 'bullet', + 'Euro', + 'bullet', + 'quotesinglbase', + 'florin', + 'quotedblbase', + 'ellipsis', + 'dagger', + 'daggerdbl', + 'circumflex', + 'perthousand', + 'Scaron', + 'guilsinglleft', + 'OE', + 'bullet', + 'Zcaron', + 'bullet', + 'bullet', + 'quoteleft', + 'quoteright', + 'quotedblleft', + 'quotedblright', + 'bullet', + 'endash', + 'emdash', + 'tilde', + 'trademark', + 'scaron', + 'guilsinglright', + 'oe', + 'bullet', + 'zcaron', + 'Ydieresis', + 'space', + 'exclamdown', + 'cent', + 'sterling', + 'currency', + 'yen', + 'brokenbar', + 'section', + 'dieresis', + 'copyright', + 'ordfeminine', + 'guillemotleft', + 'logicalnot', + 'hyphen', + 'registered', + 'macron', + 'degree', + 'plusminus', + 'twosuperior', + 'threesuperior', + 'acute', + 'mu', + 'paragraph', + 'periodcentered', + 'cedilla', + 'onesuperior', + 'ordmasculine', + 'guillemotright', + 'onequarter', + 'onehalf', + 'threequarters', + 'questiondown', + 'Agrave', + 'Aacute', + 'Acircumflex', + 'Atilde', + 'Adieresis', + 'Aring', + 'AE', + 'Ccedilla', + 'Egrave', + 'Eacute', + 'Ecircumflex', + 'Edieresis', + 'Igrave', + 'Iacute', + 'Icircumflex', + 'Idieresis', + 'Eth', + 'Ntilde', + 'Ograve', + 'Oacute', + 'Ocircumflex', + 'Otilde', + 'Odieresis', + 'multiply', + 'Oslash', + 'Ugrave', + 'Uacute', + 'Ucircumflex', + 'Udieresis', + 'Yacute', + 'Thorn', + 'germandbls', + 'agrave', + 'aacute', + 'acircumflex', + 'atilde', + 'adieresis', + 'aring', + 'ae', + 'ccedilla', + 'egrave', + 'eacute', + 'ecircumflex', + 'edieresis', + 'igrave', + 'iacute', + 'icircumflex', + 'idieresis', + 'eth', + 'ntilde', + 'ograve', + 'oacute', + 'ocircumflex', + 'otilde', + 'odieresis', + 'divide', + 'oslash', + 'ugrave', + 'uacute', + 'ucircumflex', + 'udieresis', + 'yacute', + 'thorn', + 'ydieresis' +]; +var SymbolSetEncoding = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'space', + 'exclam', + 'universal', + 'numbersign', + 'existential', + 'percent', + 'ampersand', + 'suchthat', + 'parenleft', + 'parenright', + 'asteriskmath', + 'plus', + 'comma', + 'minus', + 'period', + 'slash', + 'zero', + 'one', + 'two', + 'three', + 'four', + 'five', + 'six', + 'seven', + 'eight', + 'nine', + 'colon', + 'semicolon', + 'less', + 'equal', + 'greater', + 'question', + 'congruent', + 'Alpha', + 'Beta', + 'Chi', + 'Delta', + 'Epsilon', + 'Phi', + 'Gamma', + 'Eta', + 'Iota', + 'theta1', + 'Kappa', + 'Lambda', + 'Mu', + 'Nu', + 'Omicron', + 'Pi', + 'Theta', + 'Rho', + 'Sigma', + 'Tau', + 'Upsilon', + 'sigma1', + 'Omega', + 'Xi', + 'Psi', + 'Zeta', + 'bracketleft', + 'therefore', + 'bracketright', + 'perpendicular', + 'underscore', + 'radicalex', + 'alpha', + 'beta', + 'chi', + 'delta', + 'epsilon', + 'phi', + 'gamma', + 'eta', + 'iota', + 'phi1', + 'kappa', + 'lambda', + 'mu', + 'nu', + 'omicron', + 'pi', + 'theta', + 'rho', + 'sigma', + 'tau', + 'upsilon', + 'omega1', + 'omega', + 'xi', + 'psi', + 'zeta', + 'braceleft', + 'bar', + 'braceright', + 'similar', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'Euro', + 'Upsilon1', + 'minute', + 'lessequal', + 'fraction', + 'infinity', + 'florin', + 'club', + 'diamond', + 'heart', + 'spade', + 'arrowboth', + 'arrowleft', + 'arrowup', + 'arrowright', + 'arrowdown', + 'degree', + 'plusminus', + 'second', + 'greaterequal', + 'multiply', + 'proportional', + 'partialdiff', + 'bullet', + 'divide', + 'notequal', + 'equivalence', + 'approxequal', + 'ellipsis', + 'arrowvertex', + 'arrowhorizex', + 'carriagereturn', + 'aleph', + 'Ifraktur', + 'Rfraktur', + 'weierstrass', + 'circlemultiply', + 'circleplus', + 'emptyset', + 'intersection', + 'union', + 'propersuperset', + 'reflexsuperset', + 'notsubset', + 'propersubset', + 'reflexsubset', + 'element', + 'notelement', + 'angle', + 'gradient', + 'registerserif', + 'copyrightserif', + 'trademarkserif', + 'product', + 'radical', + 'dotmath', + 'logicalnot', + 'logicaland', + 'logicalor', + 'arrowdblboth', + 'arrowdblleft', + 'arrowdblup', + 'arrowdblright', + 'arrowdbldown', + 'lozenge', + 'angleleft', + 'registersans', + 'copyrightsans', + 'trademarksans', + 'summation', + 'parenlefttp', + 'parenleftex', + 'parenleftbt', + 'bracketlefttp', + 'bracketleftex', + 'bracketleftbt', + 'bracelefttp', + 'braceleftmid', + 'braceleftbt', + 'braceex', + '', + 'angleright', + 'integral', + 'integraltp', + 'integralex', + 'integralbt', + 'parenrighttp', + 'parenrightex', + 'parenrightbt', + 'bracketrighttp', + 'bracketrightex', + 'bracketrightbt', + 'bracerighttp', + 'bracerightmid', + 'bracerightbt' +]; +var ZapfDingbatsEncoding = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'space', + 'a1', + 'a2', + 'a202', + 'a3', + 'a4', + 'a5', + 'a119', + 'a118', + 'a117', + 'a11', + 'a12', + 'a13', + 'a14', + 'a15', + 'a16', + 'a105', + 'a17', + 'a18', + 'a19', + 'a20', + 'a21', + 'a22', + 'a23', + 'a24', + 'a25', + 'a26', + 'a27', + 'a28', + 'a6', + 'a7', + 'a8', + 'a9', + 'a10', + 'a29', + 'a30', + 'a31', + 'a32', + 'a33', + 'a34', + 'a35', + 'a36', + 'a37', + 'a38', + 'a39', + 'a40', + 'a41', + 'a42', + 'a43', + 'a44', + 'a45', + 'a46', + 'a47', + 'a48', + 'a49', + 'a50', + 'a51', + 'a52', + 'a53', + 'a54', + 'a55', + 'a56', + 'a57', + 'a58', + 'a59', + 'a60', + 'a61', + 'a62', + 'a63', + 'a64', + 'a65', + 'a66', + 'a67', + 'a68', + 'a69', + 'a70', + 'a71', + 'a72', + 'a73', + 'a74', + 'a203', + 'a75', + 'a204', + 'a76', + 'a77', + 'a78', + 'a79', + 'a81', + 'a82', + 'a83', + 'a84', + 'a97', + 'a98', + 'a99', + 'a100', + '', + 'a89', + 'a90', + 'a93', + 'a94', + 'a91', + 'a92', + 'a205', + 'a85', + 'a206', + 'a86', + 'a87', + 'a88', + 'a95', + 'a96', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'a101', + 'a102', + 'a103', + 'a104', + 'a106', + 'a107', + 'a108', + 'a112', + 'a111', + 'a110', + 'a109', + 'a120', + 'a121', + 'a122', + 'a123', + 'a124', + 'a125', + 'a126', + 'a127', + 'a128', + 'a129', + 'a130', + 'a131', + 'a132', + 'a133', + 'a134', + 'a135', + 'a136', + 'a137', + 'a138', + 'a139', + 'a140', + 'a141', + 'a142', + 'a143', + 'a144', + 'a145', + 'a146', + 'a147', + 'a148', + 'a149', + 'a150', + 'a151', + 'a152', + 'a153', + 'a154', + 'a155', + 'a156', + 'a157', + 'a158', + 'a159', + 'a160', + 'a161', + 'a163', + 'a164', + 'a196', + 'a165', + 'a192', + 'a166', + 'a167', + 'a168', + 'a169', + 'a170', + 'a171', + 'a172', + 'a173', + 'a162', + 'a174', + 'a175', + 'a176', + 'a177', + 'a178', + 'a179', + 'a193', + 'a180', + 'a199', + 'a181', + 'a200', + 'a182', + '', + 'a201', + 'a183', + 'a184', + 'a197', + 'a185', + 'a194', + 'a198', + 'a186', + 'a195', + 'a187', + 'a188', + 'a189', + 'a190', + 'a191' +]; +function getEncoding(encodingName) { + switch (encodingName) { + case 'WinAnsiEncoding': + return WinAnsiEncoding; + case 'StandardEncoding': + return StandardEncoding; + case 'MacRomanEncoding': + return MacRomanEncoding; + case 'SymbolSetEncoding': + return SymbolSetEncoding; + case 'ZapfDingbatsEncoding': + return ZapfDingbatsEncoding; + case 'ExpertEncoding': + return ExpertEncoding; + case 'MacExpertEncoding': + return MacExpertEncoding; + default: + return null; + } +} +exports.WinAnsiEncoding = WinAnsiEncoding; +exports.StandardEncoding = StandardEncoding; +exports.MacRomanEncoding = MacRomanEncoding; +exports.SymbolSetEncoding = SymbolSetEncoding; +exports.ZapfDingbatsEncoding = ZapfDingbatsEncoding; +exports.ExpertEncoding = ExpertEncoding; +exports.getEncoding = getEncoding; + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreStream = __w_pdfjs_require__(2); +var MissingDataException = sharedUtil.MissingDataException; +var StreamType = sharedUtil.StreamType; +var assert = sharedUtil.assert; +var error = sharedUtil.error; +var info = sharedUtil.info; +var isArray = sharedUtil.isArray; +var isInt = sharedUtil.isInt; +var isNum = sharedUtil.isNum; +var isString = sharedUtil.isString; +var warn = sharedUtil.warn; +var EOF = corePrimitives.EOF; +var Cmd = corePrimitives.Cmd; +var Dict = corePrimitives.Dict; +var Name = corePrimitives.Name; +var Ref = corePrimitives.Ref; +var isEOF = corePrimitives.isEOF; +var isCmd = corePrimitives.isCmd; +var isDict = corePrimitives.isDict; +var isName = corePrimitives.isName; +var Ascii85Stream = coreStream.Ascii85Stream; +var AsciiHexStream = coreStream.AsciiHexStream; +var CCITTFaxStream = coreStream.CCITTFaxStream; +var FlateStream = coreStream.FlateStream; +var Jbig2Stream = coreStream.Jbig2Stream; +var JpegStream = coreStream.JpegStream; +var JpxStream = coreStream.JpxStream; +var LZWStream = coreStream.LZWStream; +var NullStream = coreStream.NullStream; +var PredictorStream = coreStream.PredictorStream; +var RunLengthStream = coreStream.RunLengthStream; +var MAX_LENGTH_TO_CACHE = 1000; +var Parser = function ParserClosure() { + function Parser(lexer, allowStreams, xref, recoveryMode) { + this.lexer = lexer; + this.allowStreams = allowStreams; + this.xref = xref; + this.recoveryMode = recoveryMode || false; + this.imageCache = Object.create(null); + this.refill(); + } + Parser.prototype = { + refill: function Parser_refill() { + this.buf1 = this.lexer.getObj(); + this.buf2 = this.lexer.getObj(); + }, + shift: function Parser_shift() { + if (isCmd(this.buf2, 'ID')) { + this.buf1 = this.buf2; + this.buf2 = null; + } else { + this.buf1 = this.buf2; + this.buf2 = this.lexer.getObj(); + } + }, + tryShift: function Parser_tryShift() { + try { + this.shift(); + return true; + } catch (e) { + if (e instanceof MissingDataException) { + throw e; + } + return false; + } + }, + getObj: function Parser_getObj(cipherTransform) { + var buf1 = this.buf1; + this.shift(); + if (buf1 instanceof Cmd) { + switch (buf1.cmd) { + case 'BI': + return this.makeInlineImage(cipherTransform); + case '[': + var array = []; + while (!isCmd(this.buf1, ']') && !isEOF(this.buf1)) { + array.push(this.getObj(cipherTransform)); + } + if (isEOF(this.buf1)) { + if (!this.recoveryMode) { + error('End of file inside array'); + } + return array; + } + this.shift(); + return array; + case '<<': + var dict = new Dict(this.xref); + while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) { + if (!isName(this.buf1)) { + info('Malformed dictionary: key must be a name object'); + this.shift(); + continue; + } + var key = this.buf1.name; + this.shift(); + if (isEOF(this.buf1)) { + break; + } + dict.set(key, this.getObj(cipherTransform)); + } + if (isEOF(this.buf1)) { + if (!this.recoveryMode) { + error('End of file inside dictionary'); + } + return dict; + } + if (isCmd(this.buf2, 'stream')) { + return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict; + } + this.shift(); + return dict; + default: + return buf1; + } + } + if (isInt(buf1)) { + var num = buf1; + if (isInt(this.buf1) && isCmd(this.buf2, 'R')) { + var ref = new Ref(num, this.buf1); + this.shift(); + this.shift(); + return ref; + } + return num; + } + if (isString(buf1)) { + var str = buf1; + if (cipherTransform) { + str = cipherTransform.decryptString(str); + } + return str; + } + return buf1; + }, + findDefaultInlineStreamEnd: function Parser_findDefaultInlineStreamEnd(stream) { + var E = 0x45, I = 0x49, SPACE = 0x20, LF = 0xA, CR = 0xD; + var startPos = stream.pos, state = 0, ch, i, n, followingBytes; + while ((ch = stream.getByte()) !== -1) { + if (state === 0) { + state = ch === E ? 1 : 0; + } else if (state === 1) { + state = ch === I ? 2 : 0; + } else { + assert(state === 2); + if (ch === SPACE || ch === LF || ch === CR) { + n = 5; + followingBytes = stream.peekBytes(n); + for (i = 0; i < n; i++) { + ch = followingBytes[i]; + if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7F)) { + state = 0; + break; + } + } + if (state === 2) { + break; + } + } else { + state = 0; + } + } + } + return stream.pos - 4 - startPos; + }, + findDCTDecodeInlineStreamEnd: function Parser_findDCTDecodeInlineStreamEnd(stream) { + var startPos = stream.pos, foundEOI = false, b, markerLength, length; + while ((b = stream.getByte()) !== -1) { + if (b !== 0xFF) { + continue; + } + switch (stream.getByte()) { + case 0x00: + break; + case 0xFF: + stream.skip(-1); + break; + case 0xD9: + foundEOI = true; + break; + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xC4: + case 0xCC: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xFE: + markerLength = stream.getUint16(); + if (markerLength > 2) { + stream.skip(markerLength - 2); + } else { + stream.skip(-2); + } + break; + } + if (foundEOI) { + break; + } + } + length = stream.pos - startPos; + if (b === -1) { + warn('Inline DCTDecode image stream: ' + 'EOI marker not found, searching for /EI/ instead.'); + stream.skip(-length); + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + }, + findASCII85DecodeInlineStreamEnd: function Parser_findASCII85DecodeInlineStreamEnd(stream) { + var TILDE = 0x7E, GT = 0x3E; + var startPos = stream.pos, ch, length; + while ((ch = stream.getByte()) !== -1) { + if (ch === TILDE && stream.peekByte() === GT) { + stream.skip(); + break; + } + } + length = stream.pos - startPos; + if (ch === -1) { + warn('Inline ASCII85Decode image stream: ' + 'EOD marker not found, searching for /EI/ instead.'); + stream.skip(-length); + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + }, + findASCIIHexDecodeInlineStreamEnd: function Parser_findASCIIHexDecodeInlineStreamEnd(stream) { + var GT = 0x3E; + var startPos = stream.pos, ch, length; + while ((ch = stream.getByte()) !== -1) { + if (ch === GT) { + break; + } + } + length = stream.pos - startPos; + if (ch === -1) { + warn('Inline ASCIIHexDecode image stream: ' + 'EOD marker not found, searching for /EI/ instead.'); + stream.skip(-length); + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + }, + inlineStreamSkipEI: function Parser_inlineStreamSkipEI(stream) { + var E = 0x45, I = 0x49; + var state = 0, ch; + while ((ch = stream.getByte()) !== -1) { + if (state === 0) { + state = ch === E ? 1 : 0; + } else if (state === 1) { + state = ch === I ? 2 : 0; + } else if (state === 2) { + break; + } + } + }, + makeInlineImage: function Parser_makeInlineImage(cipherTransform) { + var lexer = this.lexer; + var stream = lexer.stream; + var dict = new Dict(this.xref); + while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) { + if (!isName(this.buf1)) { + error('Dictionary key must be a name object'); + } + var key = this.buf1.name; + this.shift(); + if (isEOF(this.buf1)) { + break; + } + dict.set(key, this.getObj(cipherTransform)); + } + var filter = dict.get('Filter', 'F'), filterName; + if (isName(filter)) { + filterName = filter.name; + } else if (isArray(filter)) { + var filterZero = this.xref.fetchIfRef(filter[0]); + if (isName(filterZero)) { + filterName = filterZero.name; + } + } + var startPos = stream.pos, length, i, ii; + if (filterName === 'DCTDecode' || filterName === 'DCT') { + length = this.findDCTDecodeInlineStreamEnd(stream); + } else if (filterName === 'ASCII85Decide' || filterName === 'A85') { + length = this.findASCII85DecodeInlineStreamEnd(stream); + } else if (filterName === 'ASCIIHexDecode' || filterName === 'AHx') { + length = this.findASCIIHexDecodeInlineStreamEnd(stream); + } else { + length = this.findDefaultInlineStreamEnd(stream); + } + var imageStream = stream.makeSubStream(startPos, length, dict); + var adler32; + if (length < MAX_LENGTH_TO_CACHE) { + var imageBytes = imageStream.getBytes(); + imageStream.reset(); + var a = 1; + var b = 0; + for (i = 0, ii = imageBytes.length; i < ii; ++i) { + a += imageBytes[i] & 0xff; + b += a; + } + adler32 = b % 65521 << 16 | a % 65521; + if (this.imageCache.adler32 === adler32) { + this.buf2 = Cmd.get('EI'); + this.shift(); + this.imageCache[adler32].reset(); + return this.imageCache[adler32]; + } + } + if (cipherTransform) { + imageStream = cipherTransform.createStream(imageStream, length); + } + imageStream = this.filter(imageStream, dict, length); + imageStream.dict = dict; + if (adler32 !== undefined) { + imageStream.cacheKey = 'inline_' + length + '_' + adler32; + this.imageCache[adler32] = imageStream; + } + this.buf2 = Cmd.get('EI'); + this.shift(); + return imageStream; + }, + makeStream: function Parser_makeStream(dict, cipherTransform) { + var lexer = this.lexer; + var stream = lexer.stream; + lexer.skipToNextLine(); + var pos = stream.pos - 1; + var length = dict.get('Length'); + if (!isInt(length)) { + info('Bad ' + length + ' attribute in stream'); + length = 0; + } + stream.pos = pos + length; + lexer.nextChar(); + if (this.tryShift() && isCmd(this.buf2, 'endstream')) { + this.shift(); + } else { + stream.pos = pos; + var SCAN_BLOCK_SIZE = 2048; + var ENDSTREAM_SIGNATURE_LENGTH = 9; + var ENDSTREAM_SIGNATURE = [ + 0x65, + 0x6E, + 0x64, + 0x73, + 0x74, + 0x72, + 0x65, + 0x61, + 0x6D + ]; + var skipped = 0, found = false, i, j; + while (stream.pos < stream.end) { + var scanBytes = stream.peekBytes(SCAN_BLOCK_SIZE); + var scanLength = scanBytes.length - ENDSTREAM_SIGNATURE_LENGTH; + if (scanLength <= 0) { + break; + } + found = false; + i = 0; + while (i < scanLength) { + j = 0; + while (j < ENDSTREAM_SIGNATURE_LENGTH && scanBytes[i + j] === ENDSTREAM_SIGNATURE[j]) { + j++; + } + if (j >= ENDSTREAM_SIGNATURE_LENGTH) { + found = true; + break; + } + i++; + } + if (found) { + skipped += i; + stream.pos += i; + break; + } + skipped += scanLength; + stream.pos += scanLength; + } + if (!found) { + error('Missing endstream'); + } + length = skipped; + lexer.nextChar(); + this.shift(); + this.shift(); + } + this.shift(); + stream = stream.makeSubStream(pos, length, dict); + if (cipherTransform) { + stream = cipherTransform.createStream(stream, length); + } + stream = this.filter(stream, dict, length); + stream.dict = dict; + return stream; + }, + filter: function Parser_filter(stream, dict, length) { + var filter = dict.get('Filter', 'F'); + var params = dict.get('DecodeParms', 'DP'); + if (isName(filter)) { + if (isArray(params)) { + params = this.xref.fetchIfRef(params[0]); + } + return this.makeFilter(stream, filter.name, length, params); + } + var maybeLength = length; + if (isArray(filter)) { + var filterArray = filter; + var paramsArray = params; + for (var i = 0, ii = filterArray.length; i < ii; ++i) { + filter = this.xref.fetchIfRef(filterArray[i]); + if (!isName(filter)) { + error('Bad filter name: ' + filter); + } + params = null; + if (isArray(paramsArray) && i in paramsArray) { + params = this.xref.fetchIfRef(paramsArray[i]); + } + stream = this.makeFilter(stream, filter.name, maybeLength, params); + maybeLength = null; + } + } + return stream; + }, + makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) { + if (maybeLength === 0) { + warn('Empty "' + name + '" stream.'); + return new NullStream(stream); + } + try { + var xrefStreamStats = this.xref.stats.streamTypes; + if (name === 'FlateDecode' || name === 'Fl') { + xrefStreamStats[StreamType.FLATE] = true; + if (params) { + return new PredictorStream(new FlateStream(stream, maybeLength), maybeLength, params); + } + return new FlateStream(stream, maybeLength); + } + if (name === 'LZWDecode' || name === 'LZW') { + xrefStreamStats[StreamType.LZW] = true; + var earlyChange = 1; + if (params) { + if (params.has('EarlyChange')) { + earlyChange = params.get('EarlyChange'); + } + return new PredictorStream(new LZWStream(stream, maybeLength, earlyChange), maybeLength, params); + } + return new LZWStream(stream, maybeLength, earlyChange); + } + if (name === 'DCTDecode' || name === 'DCT') { + xrefStreamStats[StreamType.DCT] = true; + return new JpegStream(stream, maybeLength, stream.dict, params); + } + if (name === 'JPXDecode' || name === 'JPX') { + xrefStreamStats[StreamType.JPX] = true; + return new JpxStream(stream, maybeLength, stream.dict, params); + } + if (name === 'ASCII85Decode' || name === 'A85') { + xrefStreamStats[StreamType.A85] = true; + return new Ascii85Stream(stream, maybeLength); + } + if (name === 'ASCIIHexDecode' || name === 'AHx') { + xrefStreamStats[StreamType.AHX] = true; + return new AsciiHexStream(stream, maybeLength); + } + if (name === 'CCITTFaxDecode' || name === 'CCF') { + xrefStreamStats[StreamType.CCF] = true; + return new CCITTFaxStream(stream, maybeLength, params); + } + if (name === 'RunLengthDecode' || name === 'RL') { + xrefStreamStats[StreamType.RL] = true; + return new RunLengthStream(stream, maybeLength); + } + if (name === 'JBIG2Decode') { + xrefStreamStats[StreamType.JBIG] = true; + return new Jbig2Stream(stream, maybeLength, stream.dict, params); + } + warn('filter "' + name + '" not supported yet'); + return stream; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Invalid stream: \"' + ex + '\"'); + return new NullStream(stream); + } + } + }; + return Parser; +}(); +var Lexer = function LexerClosure() { + function Lexer(stream, knownCommands) { + this.stream = stream; + this.nextChar(); + this.strBuf = []; + this.knownCommands = knownCommands; + } + var specialChars = [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 2, + 0, + 0, + 2, + 2, + 0, + 0, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ]; + function toHexDigit(ch) { + if (ch >= 0x30 && ch <= 0x39) { + return ch & 0x0F; + } + if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) { + return (ch & 0x0F) + 9; + } + return -1; + } + Lexer.prototype = { + nextChar: function Lexer_nextChar() { + return this.currentChar = this.stream.getByte(); + }, + peekChar: function Lexer_peekChar() { + return this.stream.peekByte(); + }, + getNumber: function Lexer_getNumber() { + var ch = this.currentChar; + var eNotation = false; + var divideBy = 0; + var sign = 1; + if (ch === 0x2D) { + sign = -1; + ch = this.nextChar(); + if (ch === 0x2D) { + ch = this.nextChar(); + } + } else if (ch === 0x2B) { + ch = this.nextChar(); + } + if (ch === 0x2E) { + divideBy = 10; + ch = this.nextChar(); + } + if (ch < 0x30 || ch > 0x39) { + error('Invalid number: ' + String.fromCharCode(ch)); + return 0; + } + var baseValue = ch - 0x30; + var powerValue = 0; + var powerValueSign = 1; + while ((ch = this.nextChar()) >= 0) { + if (0x30 <= ch && ch <= 0x39) { + var currentDigit = ch - 0x30; + if (eNotation) { + powerValue = powerValue * 10 + currentDigit; + } else { + if (divideBy !== 0) { + divideBy *= 10; + } + baseValue = baseValue * 10 + currentDigit; + } + } else if (ch === 0x2E) { + if (divideBy === 0) { + divideBy = 1; + } else { + break; + } + } else if (ch === 0x2D) { + warn('Badly formatted number'); + } else if (ch === 0x45 || ch === 0x65) { + ch = this.peekChar(); + if (ch === 0x2B || ch === 0x2D) { + powerValueSign = ch === 0x2D ? -1 : 1; + this.nextChar(); + } else if (ch < 0x30 || ch > 0x39) { + break; + } + eNotation = true; + } else { + break; + } + } + if (divideBy !== 0) { + baseValue /= divideBy; + } + if (eNotation) { + baseValue *= Math.pow(10, powerValueSign * powerValue); + } + return sign * baseValue; + }, + getString: function Lexer_getString() { + var numParen = 1; + var done = false; + var strBuf = this.strBuf; + strBuf.length = 0; + var ch = this.nextChar(); + while (true) { + var charBuffered = false; + switch (ch | 0) { + case -1: + warn('Unterminated string'); + done = true; + break; + case 0x28: + ++numParen; + strBuf.push('('); + break; + case 0x29: + if (--numParen === 0) { + this.nextChar(); + done = true; + } else { + strBuf.push(')'); + } + break; + case 0x5C: + ch = this.nextChar(); + switch (ch) { + case -1: + warn('Unterminated string'); + done = true; + break; + case 0x6E: + strBuf.push('\n'); + break; + case 0x72: + strBuf.push('\r'); + break; + case 0x74: + strBuf.push('\t'); + break; + case 0x62: + strBuf.push('\b'); + break; + case 0x66: + strBuf.push('\f'); + break; + case 0x5C: + case 0x28: + case 0x29: + strBuf.push(String.fromCharCode(ch)); + break; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + var x = ch & 0x0F; + ch = this.nextChar(); + charBuffered = true; + if (ch >= 0x30 && ch <= 0x37) { + x = (x << 3) + (ch & 0x0F); + ch = this.nextChar(); + if (ch >= 0x30 && ch <= 0x37) { + charBuffered = false; + x = (x << 3) + (ch & 0x0F); + } + } + strBuf.push(String.fromCharCode(x)); + break; + case 0x0D: + if (this.peekChar() === 0x0A) { + this.nextChar(); + } + break; + case 0x0A: + break; + default: + strBuf.push(String.fromCharCode(ch)); + break; + } + break; + default: + strBuf.push(String.fromCharCode(ch)); + break; + } + if (done) { + break; + } + if (!charBuffered) { + ch = this.nextChar(); + } + } + return strBuf.join(''); + }, + getName: function Lexer_getName() { + var ch, previousCh; + var strBuf = this.strBuf; + strBuf.length = 0; + while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { + if (ch === 0x23) { + ch = this.nextChar(); + if (specialChars[ch]) { + warn('Lexer_getName: ' + 'NUMBER SIGN (#) should be followed by a hexadecimal number.'); + strBuf.push('#'); + break; + } + var x = toHexDigit(ch); + if (x !== -1) { + previousCh = ch; + ch = this.nextChar(); + var x2 = toHexDigit(ch); + if (x2 === -1) { + warn('Lexer_getName: Illegal digit (' + String.fromCharCode(ch) + ') in hexadecimal number.'); + strBuf.push('#', String.fromCharCode(previousCh)); + if (specialChars[ch]) { + break; + } + strBuf.push(String.fromCharCode(ch)); + continue; + } + strBuf.push(String.fromCharCode(x << 4 | x2)); + } else { + strBuf.push('#', String.fromCharCode(ch)); + } + } else { + strBuf.push(String.fromCharCode(ch)); + } + } + if (strBuf.length > 127) { + warn('name token is longer than allowed by the spec: ' + strBuf.length); + } + return Name.get(strBuf.join('')); + }, + getHexString: function Lexer_getHexString() { + var strBuf = this.strBuf; + strBuf.length = 0; + var ch = this.currentChar; + var isFirstHex = true; + var firstDigit; + var secondDigit; + while (true) { + if (ch < 0) { + warn('Unterminated hex string'); + break; + } else if (ch === 0x3E) { + this.nextChar(); + break; + } else if (specialChars[ch] === 1) { + ch = this.nextChar(); + continue; + } else { + if (isFirstHex) { + firstDigit = toHexDigit(ch); + if (firstDigit === -1) { + warn('Ignoring invalid character "' + ch + '" in hex string'); + ch = this.nextChar(); + continue; + } + } else { + secondDigit = toHexDigit(ch); + if (secondDigit === -1) { + warn('Ignoring invalid character "' + ch + '" in hex string'); + ch = this.nextChar(); + continue; + } + strBuf.push(String.fromCharCode(firstDigit << 4 | secondDigit)); + } + isFirstHex = !isFirstHex; + ch = this.nextChar(); + } + } + return strBuf.join(''); + }, + getObj: function Lexer_getObj() { + var comment = false; + var ch = this.currentChar; + while (true) { + if (ch < 0) { + return EOF; + } + if (comment) { + if (ch === 0x0A || ch === 0x0D) { + comment = false; + } + } else if (ch === 0x25) { + comment = true; + } else if (specialChars[ch] !== 1) { + break; + } + ch = this.nextChar(); + } + switch (ch | 0) { + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x2B: + case 0x2D: + case 0x2E: + return this.getNumber(); + case 0x28: + return this.getString(); + case 0x2F: + return this.getName(); + case 0x5B: + this.nextChar(); + return Cmd.get('['); + case 0x5D: + this.nextChar(); + return Cmd.get(']'); + case 0x3C: + ch = this.nextChar(); + if (ch === 0x3C) { + this.nextChar(); + return Cmd.get('<<'); + } + return this.getHexString(); + case 0x3E: + ch = this.nextChar(); + if (ch === 0x3E) { + this.nextChar(); + return Cmd.get('>>'); + } + return Cmd.get('>'); + case 0x7B: + this.nextChar(); + return Cmd.get('{'); + case 0x7D: + this.nextChar(); + return Cmd.get('}'); + case 0x29: + this.nextChar(); + error('Illegal character: ' + ch); + break; + } + var str = String.fromCharCode(ch); + var knownCommands = this.knownCommands; + var knownCommandFound = knownCommands && knownCommands[str] !== undefined; + while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { + var possibleCommand = str + String.fromCharCode(ch); + if (knownCommandFound && knownCommands[possibleCommand] === undefined) { + break; + } + if (str.length === 128) { + error('Command token too long: ' + str.length); + } + str = possibleCommand; + knownCommandFound = knownCommands && knownCommands[str] !== undefined; + } + if (str === 'true') { + return true; + } + if (str === 'false') { + return false; + } + if (str === 'null') { + return null; + } + return Cmd.get(str); + }, + skipToNextLine: function Lexer_skipToNextLine() { + var ch = this.currentChar; + while (ch >= 0) { + if (ch === 0x0D) { + ch = this.nextChar(); + if (ch === 0x0A) { + this.nextChar(); + } + break; + } else if (ch === 0x0A) { + this.nextChar(); + break; + } + ch = this.nextChar(); + } + } + }; + return Lexer; +}(); +var Linearization = { + create: function LinearizationCreate(stream) { + function getInt(name, allowZeroValue) { + var obj = linDict.get(name); + if (isInt(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) { + return obj; + } + throw new Error('The "' + name + '" parameter in the linearization ' + 'dictionary is invalid.'); + } + function getHints() { + var hints = linDict.get('H'), hintsLength, item; + if (isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) { + for (var index = 0; index < hintsLength; index++) { + if (!(isInt(item = hints[index]) && item > 0)) { + throw new Error('Hint (' + index + ') in the linearization dictionary is invalid.'); + } + } + return hints; + } + throw new Error('Hint array in the linearization dictionary is invalid.'); + } + var parser = new Parser(new Lexer(stream), false, null); + var obj1 = parser.getObj(); + var obj2 = parser.getObj(); + var obj3 = parser.getObj(); + var linDict = parser.getObj(); + var obj, length; + if (!(isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') && isDict(linDict) && isNum(obj = linDict.get('Linearized')) && obj > 0)) { + return null; + } else if ((length = getInt('L')) !== stream.length) { + throw new Error('The "L" parameter in the linearization dictionary ' + 'does not equal the stream length.'); + } + return { + length: length, + hints: getHints(), + objectNumberFirst: getInt('O'), + endFirst: getInt('E'), + numPages: getInt('N'), + mainXRefEntriesOffset: getInt('T'), + pageFirst: linDict.has('P') ? getInt('P', true) : 0 + }; + } +}; +exports.Lexer = Lexer; +exports.Linearization = Linearization; +exports.Parser = Parser; + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var corePsParser = __w_pdfjs_require__(34); +var error = sharedUtil.error; +var info = sharedUtil.info; +var isArray = sharedUtil.isArray; +var isBool = sharedUtil.isBool; +var isDict = corePrimitives.isDict; +var isStream = corePrimitives.isStream; +var PostScriptLexer = corePsParser.PostScriptLexer; +var PostScriptParser = corePsParser.PostScriptParser; +var PDFFunction = function PDFFunctionClosure() { + var CONSTRUCT_SAMPLED = 0; + var CONSTRUCT_INTERPOLATED = 2; + var CONSTRUCT_STICHED = 3; + var CONSTRUCT_POSTSCRIPT = 4; + return { + getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps, str) { + var i, ii; + var length = 1; + for (i = 0, ii = size.length; i < ii; i++) { + length *= size[i]; + } + length *= outputSize; + var array = new Array(length); + var codeSize = 0; + var codeBuf = 0; + var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1); + var strBytes = str.getBytes((length * bps + 7) / 8); + var strIdx = 0; + for (i = 0; i < length; i++) { + while (codeSize < bps) { + codeBuf <<= 8; + codeBuf |= strBytes[strIdx++]; + codeSize += 8; + } + codeSize -= bps; + array[i] = (codeBuf >> codeSize) * sampleMul; + codeBuf &= (1 << codeSize) - 1; + } + return array; + }, + getIR: function PDFFunction_getIR(xref, fn) { + var dict = fn.dict; + if (!dict) { + dict = fn; + } + var types = [ + this.constructSampled, + null, + this.constructInterpolated, + this.constructStiched, + this.constructPostScript + ]; + var typeNum = dict.get('FunctionType'); + var typeFn = types[typeNum]; + if (!typeFn) { + error('Unknown type of function'); + } + return typeFn.call(this, fn, dict, xref); + }, + fromIR: function PDFFunction_fromIR(IR) { + var type = IR[0]; + switch (type) { + case CONSTRUCT_SAMPLED: + return this.constructSampledFromIR(IR); + case CONSTRUCT_INTERPOLATED: + return this.constructInterpolatedFromIR(IR); + case CONSTRUCT_STICHED: + return this.constructStichedFromIR(IR); + default: + return this.constructPostScriptFromIR(IR); + } + }, + parse: function PDFFunction_parse(xref, fn) { + var IR = this.getIR(xref, fn); + return this.fromIR(IR); + }, + parseArray: function PDFFunction_parseArray(xref, fnObj) { + if (!isArray(fnObj)) { + return this.parse(xref, fnObj); + } + var fnArray = []; + for (var j = 0, jj = fnObj.length; j < jj; j++) { + var obj = xref.fetchIfRef(fnObj[j]); + fnArray.push(PDFFunction.parse(xref, obj)); + } + return function (src, srcOffset, dest, destOffset) { + for (var i = 0, ii = fnArray.length; i < ii; i++) { + fnArray[i](src, srcOffset, dest, destOffset + i); + } + }; + }, + constructSampled: function PDFFunction_constructSampled(str, dict) { + function toMultiArray(arr) { + var inputLength = arr.length; + var out = []; + var index = 0; + for (var i = 0; i < inputLength; i += 2) { + out[index] = [ + arr[i], + arr[i + 1] + ]; + ++index; + } + return out; + } + var domain = dict.getArray('Domain'); + var range = dict.getArray('Range'); + if (!domain || !range) { + error('No domain or range'); + } + var inputSize = domain.length / 2; + var outputSize = range.length / 2; + domain = toMultiArray(domain); + range = toMultiArray(range); + var size = dict.get('Size'); + var bps = dict.get('BitsPerSample'); + var order = dict.get('Order') || 1; + if (order !== 1) { + info('No support for cubic spline interpolation: ' + order); + } + var encode = dict.getArray('Encode'); + if (!encode) { + encode = []; + for (var i = 0; i < inputSize; ++i) { + encode.push(0); + encode.push(size[i] - 1); + } + } + encode = toMultiArray(encode); + var decode = dict.getArray('Decode'); + if (!decode) { + decode = range; + } else { + decode = toMultiArray(decode); + } + var samples = this.getSampleArray(size, outputSize, bps, str); + return [ + CONSTRUCT_SAMPLED, + inputSize, + domain, + encode, + decode, + samples, + size, + outputSize, + Math.pow(2, bps) - 1, + range + ]; + }, + constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) { + function interpolate(x, xmin, xmax, ymin, ymax) { + return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin)); + } + return function constructSampledFromIRResult(src, srcOffset, dest, destOffset) { + var m = IR[1]; + var domain = IR[2]; + var encode = IR[3]; + var decode = IR[4]; + var samples = IR[5]; + var size = IR[6]; + var n = IR[7]; + var range = IR[9]; + var cubeVertices = 1 << m; + var cubeN = new Float64Array(cubeVertices); + var cubeVertex = new Uint32Array(cubeVertices); + var i, j; + for (j = 0; j < cubeVertices; j++) { + cubeN[j] = 1; + } + var k = n, pos = 1; + for (i = 0; i < m; ++i) { + var domain_2i = domain[i][0]; + var domain_2i_1 = domain[i][1]; + var xi = Math.min(Math.max(src[srcOffset + i], domain_2i), domain_2i_1); + var e = interpolate(xi, domain_2i, domain_2i_1, encode[i][0], encode[i][1]); + var size_i = size[i]; + e = Math.min(Math.max(e, 0), size_i - 1); + var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; + var n0 = e0 + 1 - e; + var n1 = e - e0; + var offset0 = e0 * k; + var offset1 = offset0 + k; + for (j = 0; j < cubeVertices; j++) { + if (j & pos) { + cubeN[j] *= n1; + cubeVertex[j] += offset1; + } else { + cubeN[j] *= n0; + cubeVertex[j] += offset0; + } + } + k *= size_i; + pos <<= 1; + } + for (j = 0; j < n; ++j) { + var rj = 0; + for (i = 0; i < cubeVertices; i++) { + rj += samples[cubeVertex[i] + j] * cubeN[i]; + } + rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]); + dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), range[j][1]); + } + }; + }, + constructInterpolated: function PDFFunction_constructInterpolated(str, dict) { + var c0 = dict.getArray('C0') || [0]; + var c1 = dict.getArray('C1') || [1]; + var n = dict.get('N'); + if (!isArray(c0) || !isArray(c1)) { + error('Illegal dictionary for interpolated function'); + } + var length = c0.length; + var diff = []; + for (var i = 0; i < length; ++i) { + diff.push(c1[i] - c0[i]); + } + return [ + CONSTRUCT_INTERPOLATED, + c0, + diff, + n + ]; + }, + constructInterpolatedFromIR: function PDFFunction_constructInterpolatedFromIR(IR) { + var c0 = IR[1]; + var diff = IR[2]; + var n = IR[3]; + var length = diff.length; + return function constructInterpolatedFromIRResult(src, srcOffset, dest, destOffset) { + var x = n === 1 ? src[srcOffset] : Math.pow(src[srcOffset], n); + for (var j = 0; j < length; ++j) { + dest[destOffset + j] = c0[j] + x * diff[j]; + } + }; + }, + constructStiched: function PDFFunction_constructStiched(fn, dict, xref) { + var domain = dict.getArray('Domain'); + if (!domain) { + error('No domain'); + } + var inputSize = domain.length / 2; + if (inputSize !== 1) { + error('Bad domain for stiched function'); + } + var fnRefs = dict.get('Functions'); + var fns = []; + for (var i = 0, ii = fnRefs.length; i < ii; ++i) { + fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i]))); + } + var bounds = dict.getArray('Bounds'); + var encode = dict.getArray('Encode'); + return [ + CONSTRUCT_STICHED, + domain, + bounds, + encode, + fns + ]; + }, + constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) { + var domain = IR[1]; + var bounds = IR[2]; + var encode = IR[3]; + var fnsIR = IR[4]; + var fns = []; + var tmpBuf = new Float32Array(1); + for (var i = 0, ii = fnsIR.length; i < ii; i++) { + fns.push(PDFFunction.fromIR(fnsIR[i])); + } + return function constructStichedFromIRResult(src, srcOffset, dest, destOffset) { + var clip = function constructStichedFromIRClip(v, min, max) { + if (v > max) { + v = max; + } else if (v < min) { + v = min; + } + return v; + }; + var v = clip(src[srcOffset], domain[0], domain[1]); + for (var i = 0, ii = bounds.length; i < ii; ++i) { + if (v < bounds[i]) { + break; + } + } + var dmin = domain[0]; + if (i > 0) { + dmin = bounds[i - 1]; + } + var dmax = domain[1]; + if (i < bounds.length) { + dmax = bounds[i]; + } + var rmin = encode[2 * i]; + var rmax = encode[2 * i + 1]; + tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); + fns[i](tmpBuf, 0, dest, destOffset); + }; + }, + constructPostScript: function PDFFunction_constructPostScript(fn, dict, xref) { + var domain = dict.getArray('Domain'); + var range = dict.getArray('Range'); + if (!domain) { + error('No domain.'); + } + if (!range) { + error('No range.'); + } + var lexer = new PostScriptLexer(fn); + var parser = new PostScriptParser(lexer); + var code = parser.parse(); + return [ + CONSTRUCT_POSTSCRIPT, + domain, + range, + code + ]; + }, + constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR(IR) { + var domain = IR[1]; + var range = IR[2]; + var code = IR[3]; + var compiled = new PostScriptCompiler().compile(code, domain, range); + if (compiled) { + return new Function('src', 'srcOffset', 'dest', 'destOffset', compiled); + } + info('Unable to compile PS function'); + var numOutputs = range.length >> 1; + var numInputs = domain.length >> 1; + var evaluator = new PostScriptEvaluator(code); + var cache = Object.create(null); + var MAX_CACHE_SIZE = 2048 * 4; + var cache_available = MAX_CACHE_SIZE; + var tmpBuf = new Float32Array(numInputs); + return function constructPostScriptFromIRResult(src, srcOffset, dest, destOffset) { + var i, value; + var key = ''; + var input = tmpBuf; + for (i = 0; i < numInputs; i++) { + value = src[srcOffset + i]; + input[i] = value; + key += value + '_'; + } + var cachedValue = cache[key]; + if (cachedValue !== undefined) { + dest.set(cachedValue, destOffset); + return; + } + var output = new Float32Array(numOutputs); + var stack = evaluator.execute(input); + var stackIndex = stack.length - numOutputs; + for (i = 0; i < numOutputs; i++) { + value = stack[stackIndex + i]; + var bound = range[i * 2]; + if (value < bound) { + value = bound; + } else { + bound = range[i * 2 + 1]; + if (value > bound) { + value = bound; + } + } + output[i] = value; + } + if (cache_available > 0) { + cache_available--; + cache[key] = output; + } + dest.set(output, destOffset); + }; + } + }; +}(); +function isPDFFunction(v) { + var fnDict; + if (typeof v !== 'object') { + return false; + } else if (isDict(v)) { + fnDict = v; + } else if (isStream(v)) { + fnDict = v.dict; + } else { + return false; + } + return fnDict.has('FunctionType'); +} +var PostScriptStack = function PostScriptStackClosure() { + var MAX_STACK_SIZE = 100; + function PostScriptStack(initialStack) { + this.stack = !initialStack ? [] : Array.prototype.slice.call(initialStack, 0); + } + PostScriptStack.prototype = { + push: function PostScriptStack_push(value) { + if (this.stack.length >= MAX_STACK_SIZE) { + error('PostScript function stack overflow.'); + } + this.stack.push(value); + }, + pop: function PostScriptStack_pop() { + if (this.stack.length <= 0) { + error('PostScript function stack underflow.'); + } + return this.stack.pop(); + }, + copy: function PostScriptStack_copy(n) { + if (this.stack.length + n >= MAX_STACK_SIZE) { + error('PostScript function stack overflow.'); + } + var stack = this.stack; + for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) { + stack.push(stack[i]); + } + }, + index: function PostScriptStack_index(n) { + this.push(this.stack[this.stack.length - n - 1]); + }, + roll: function PostScriptStack_roll(n, p) { + var stack = this.stack; + var l = stack.length - n; + var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t; + for (i = l, j = r; i < j; i++, j--) { + t = stack[i]; + stack[i] = stack[j]; + stack[j] = t; + } + for (i = l, j = c - 1; i < j; i++, j--) { + t = stack[i]; + stack[i] = stack[j]; + stack[j] = t; + } + for (i = c, j = r; i < j; i++, j--) { + t = stack[i]; + stack[i] = stack[j]; + stack[j] = t; + } + } + }; + return PostScriptStack; +}(); +var PostScriptEvaluator = function PostScriptEvaluatorClosure() { + function PostScriptEvaluator(operators) { + this.operators = operators; + } + PostScriptEvaluator.prototype = { + execute: function PostScriptEvaluator_execute(initialStack) { + var stack = new PostScriptStack(initialStack); + var counter = 0; + var operators = this.operators; + var length = operators.length; + var operator, a, b; + while (counter < length) { + operator = operators[counter++]; + if (typeof operator === 'number') { + stack.push(operator); + continue; + } + switch (operator) { + case 'jz': + b = stack.pop(); + a = stack.pop(); + if (!a) { + counter = b; + } + break; + case 'j': + a = stack.pop(); + counter = a; + break; + case 'abs': + a = stack.pop(); + stack.push(Math.abs(a)); + break; + case 'add': + b = stack.pop(); + a = stack.pop(); + stack.push(a + b); + break; + case 'and': + b = stack.pop(); + a = stack.pop(); + if (isBool(a) && isBool(b)) { + stack.push(a && b); + } else { + stack.push(a & b); + } + break; + case 'atan': + a = stack.pop(); + stack.push(Math.atan(a)); + break; + case 'bitshift': + b = stack.pop(); + a = stack.pop(); + if (a > 0) { + stack.push(a << b); + } else { + stack.push(a >> b); + } + break; + case 'ceiling': + a = stack.pop(); + stack.push(Math.ceil(a)); + break; + case 'copy': + a = stack.pop(); + stack.copy(a); + break; + case 'cos': + a = stack.pop(); + stack.push(Math.cos(a)); + break; + case 'cvi': + a = stack.pop() | 0; + stack.push(a); + break; + case 'cvr': + break; + case 'div': + b = stack.pop(); + a = stack.pop(); + stack.push(a / b); + break; + case 'dup': + stack.copy(1); + break; + case 'eq': + b = stack.pop(); + a = stack.pop(); + stack.push(a === b); + break; + case 'exch': + stack.roll(2, 1); + break; + case 'exp': + b = stack.pop(); + a = stack.pop(); + stack.push(Math.pow(a, b)); + break; + case 'false': + stack.push(false); + break; + case 'floor': + a = stack.pop(); + stack.push(Math.floor(a)); + break; + case 'ge': + b = stack.pop(); + a = stack.pop(); + stack.push(a >= b); + break; + case 'gt': + b = stack.pop(); + a = stack.pop(); + stack.push(a > b); + break; + case 'idiv': + b = stack.pop(); + a = stack.pop(); + stack.push(a / b | 0); + break; + case 'index': + a = stack.pop(); + stack.index(a); + break; + case 'le': + b = stack.pop(); + a = stack.pop(); + stack.push(a <= b); + break; + case 'ln': + a = stack.pop(); + stack.push(Math.log(a)); + break; + case 'log': + a = stack.pop(); + stack.push(Math.log(a) / Math.LN10); + break; + case 'lt': + b = stack.pop(); + a = stack.pop(); + stack.push(a < b); + break; + case 'mod': + b = stack.pop(); + a = stack.pop(); + stack.push(a % b); + break; + case 'mul': + b = stack.pop(); + a = stack.pop(); + stack.push(a * b); + break; + case 'ne': + b = stack.pop(); + a = stack.pop(); + stack.push(a !== b); + break; + case 'neg': + a = stack.pop(); + stack.push(-a); + break; + case 'not': + a = stack.pop(); + if (isBool(a)) { + stack.push(!a); + } else { + stack.push(~a); + } + break; + case 'or': + b = stack.pop(); + a = stack.pop(); + if (isBool(a) && isBool(b)) { + stack.push(a || b); + } else { + stack.push(a | b); + } + break; + case 'pop': + stack.pop(); + break; + case 'roll': + b = stack.pop(); + a = stack.pop(); + stack.roll(a, b); + break; + case 'round': + a = stack.pop(); + stack.push(Math.round(a)); + break; + case 'sin': + a = stack.pop(); + stack.push(Math.sin(a)); + break; + case 'sqrt': + a = stack.pop(); + stack.push(Math.sqrt(a)); + break; + case 'sub': + b = stack.pop(); + a = stack.pop(); + stack.push(a - b); + break; + case 'true': + stack.push(true); + break; + case 'truncate': + a = stack.pop(); + a = a < 0 ? Math.ceil(a) : Math.floor(a); + stack.push(a); + break; + case 'xor': + b = stack.pop(); + a = stack.pop(); + if (isBool(a) && isBool(b)) { + stack.push(a !== b); + } else { + stack.push(a ^ b); + } + break; + default: + error('Unknown operator ' + operator); + break; + } + } + return stack.stack; + } + }; + return PostScriptEvaluator; +}(); +var PostScriptCompiler = function PostScriptCompilerClosure() { + function AstNode(type) { + this.type = type; + } + AstNode.prototype.visit = function (visitor) { + throw new Error('abstract method'); + }; + function AstArgument(index, min, max) { + AstNode.call(this, 'args'); + this.index = index; + this.min = min; + this.max = max; + } + AstArgument.prototype = Object.create(AstNode.prototype); + AstArgument.prototype.visit = function (visitor) { + visitor.visitArgument(this); + }; + function AstLiteral(number) { + AstNode.call(this, 'literal'); + this.number = number; + this.min = number; + this.max = number; + } + AstLiteral.prototype = Object.create(AstNode.prototype); + AstLiteral.prototype.visit = function (visitor) { + visitor.visitLiteral(this); + }; + function AstBinaryOperation(op, arg1, arg2, min, max) { + AstNode.call(this, 'binary'); + this.op = op; + this.arg1 = arg1; + this.arg2 = arg2; + this.min = min; + this.max = max; + } + AstBinaryOperation.prototype = Object.create(AstNode.prototype); + AstBinaryOperation.prototype.visit = function (visitor) { + visitor.visitBinaryOperation(this); + }; + function AstMin(arg, max) { + AstNode.call(this, 'max'); + this.arg = arg; + this.min = arg.min; + this.max = max; + } + AstMin.prototype = Object.create(AstNode.prototype); + AstMin.prototype.visit = function (visitor) { + visitor.visitMin(this); + }; + function AstVariable(index, min, max) { + AstNode.call(this, 'var'); + this.index = index; + this.min = min; + this.max = max; + } + AstVariable.prototype = Object.create(AstNode.prototype); + AstVariable.prototype.visit = function (visitor) { + visitor.visitVariable(this); + }; + function AstVariableDefinition(variable, arg) { + AstNode.call(this, 'definition'); + this.variable = variable; + this.arg = arg; + } + AstVariableDefinition.prototype = Object.create(AstNode.prototype); + AstVariableDefinition.prototype.visit = function (visitor) { + visitor.visitVariableDefinition(this); + }; + function ExpressionBuilderVisitor() { + this.parts = []; + } + ExpressionBuilderVisitor.prototype = { + visitArgument: function (arg) { + this.parts.push('Math.max(', arg.min, ', Math.min(', arg.max, ', src[srcOffset + ', arg.index, ']))'); + }, + visitVariable: function (variable) { + this.parts.push('v', variable.index); + }, + visitLiteral: function (literal) { + this.parts.push(literal.number); + }, + visitBinaryOperation: function (operation) { + this.parts.push('('); + operation.arg1.visit(this); + this.parts.push(' ', operation.op, ' '); + operation.arg2.visit(this); + this.parts.push(')'); + }, + visitVariableDefinition: function (definition) { + this.parts.push('var '); + definition.variable.visit(this); + this.parts.push(' = '); + definition.arg.visit(this); + this.parts.push(';'); + }, + visitMin: function (max) { + this.parts.push('Math.min('); + max.arg.visit(this); + this.parts.push(', ', max.max, ')'); + }, + toString: function () { + return this.parts.join(''); + } + }; + function buildAddOperation(num1, num2) { + if (num2.type === 'literal' && num2.number === 0) { + return num1; + } + if (num1.type === 'literal' && num1.number === 0) { + return num2; + } + if (num2.type === 'literal' && num1.type === 'literal') { + return new AstLiteral(num1.number + num2.number); + } + return new AstBinaryOperation('+', num1, num2, num1.min + num2.min, num1.max + num2.max); + } + function buildMulOperation(num1, num2) { + if (num2.type === 'literal') { + if (num2.number === 0) { + return new AstLiteral(0); + } else if (num2.number === 1) { + return num1; + } else if (num1.type === 'literal') { + return new AstLiteral(num1.number * num2.number); + } + } + if (num1.type === 'literal') { + if (num1.number === 0) { + return new AstLiteral(0); + } else if (num1.number === 1) { + return num2; + } + } + var min = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max); + var max = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max); + return new AstBinaryOperation('*', num1, num2, min, max); + } + function buildSubOperation(num1, num2) { + if (num2.type === 'literal') { + if (num2.number === 0) { + return num1; + } else if (num1.type === 'literal') { + return new AstLiteral(num1.number - num2.number); + } + } + if (num2.type === 'binary' && num2.op === '-' && num1.type === 'literal' && num1.number === 1 && num2.arg1.type === 'literal' && num2.arg1.number === 1) { + return num2.arg2; + } + return new AstBinaryOperation('-', num1, num2, num1.min - num2.max, num1.max - num2.min); + } + function buildMinOperation(num1, max) { + if (num1.min >= max) { + return new AstLiteral(max); + } else if (num1.max <= max) { + return num1; + } + return new AstMin(num1, max); + } + function PostScriptCompiler() { + } + PostScriptCompiler.prototype = { + compile: function PostScriptCompiler_compile(code, domain, range) { + var stack = []; + var i, ii; + var instructions = []; + var inputSize = domain.length >> 1, outputSize = range.length >> 1; + var lastRegister = 0; + var n, j; + var num1, num2, ast1, ast2, tmpVar, item; + for (i = 0; i < inputSize; i++) { + stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1])); + } + for (i = 0, ii = code.length; i < ii; i++) { + item = code[i]; + if (typeof item === 'number') { + stack.push(new AstLiteral(item)); + continue; + } + switch (item) { + case 'add': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildAddOperation(num1, num2)); + break; + case 'cvr': + if (stack.length < 1) { + return null; + } + break; + case 'mul': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildMulOperation(num1, num2)); + break; + case 'sub': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildSubOperation(num1, num2)); + break; + case 'exch': + if (stack.length < 2) { + return null; + } + ast1 = stack.pop(); + ast2 = stack.pop(); + stack.push(ast1, ast2); + break; + case 'pop': + if (stack.length < 1) { + return null; + } + stack.pop(); + break; + case 'index': + if (stack.length < 1) { + return null; + } + num1 = stack.pop(); + if (num1.type !== 'literal') { + return null; + } + n = num1.number; + if (n < 0 || (n | 0) !== n || stack.length < n) { + return null; + } + ast1 = stack[stack.length - n - 1]; + if (ast1.type === 'literal' || ast1.type === 'var') { + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - n - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case 'dup': + if (stack.length < 1) { + return null; + } + if (typeof code[i + 1] === 'number' && code[i + 2] === 'gt' && code[i + 3] === i + 7 && code[i + 4] === 'jz' && code[i + 5] === 'pop' && code[i + 6] === code[i + 1]) { + num1 = stack.pop(); + stack.push(buildMinOperation(num1, code[i + 1])); + i += 6; + break; + } + ast1 = stack[stack.length - 1]; + if (ast1.type === 'literal' || ast1.type === 'var') { + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case 'roll': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + if (num2.type !== 'literal' || num1.type !== 'literal') { + return null; + } + j = num2.number; + n = num1.number; + if (n <= 0 || (n | 0) !== n || (j | 0) !== j || stack.length < n) { + return null; + } + j = (j % n + n) % n; + if (j === 0) { + break; + } + Array.prototype.push.apply(stack, stack.splice(stack.length - n, n - j)); + break; + default: + return null; + } + } + if (stack.length !== outputSize) { + return null; + } + var result = []; + instructions.forEach(function (instruction) { + var statementBuilder = new ExpressionBuilderVisitor(); + instruction.visit(statementBuilder); + result.push(statementBuilder.toString()); + }); + stack.forEach(function (expr, i) { + var statementBuilder = new ExpressionBuilderVisitor(); + expr.visit(statementBuilder); + var min = range[i * 2], max = range[i * 2 + 1]; + var out = [statementBuilder.toString()]; + if (min > expr.min) { + out.unshift('Math.max(', min, ', '); + out.push(')'); + } + if (max < expr.max) { + out.unshift('Math.min(', max, ', '); + out.push(')'); + } + out.unshift('dest[destOffset + ', i, '] = '); + out.push(';'); + result.push(out.join('')); + }); + return result.join('\n'); + } + }; + return PostScriptCompiler; +}(); +exports.isPDFFunction = isPDFFunction; +exports.PDFFunction = PDFFunction; +exports.PostScriptEvaluator = PostScriptEvaluator; +exports.PostScriptCompiler = PostScriptCompiler; + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var getLookupTableFactory = sharedUtil.getLookupTableFactory; +var getGlyphsUnicode = getLookupTableFactory(function (t) { + t['A'] = 0x0041; + t['AE'] = 0x00C6; + t['AEacute'] = 0x01FC; + t['AEmacron'] = 0x01E2; + t['AEsmall'] = 0xF7E6; + t['Aacute'] = 0x00C1; + t['Aacutesmall'] = 0xF7E1; + t['Abreve'] = 0x0102; + t['Abreveacute'] = 0x1EAE; + t['Abrevecyrillic'] = 0x04D0; + t['Abrevedotbelow'] = 0x1EB6; + t['Abrevegrave'] = 0x1EB0; + t['Abrevehookabove'] = 0x1EB2; + t['Abrevetilde'] = 0x1EB4; + t['Acaron'] = 0x01CD; + t['Acircle'] = 0x24B6; + t['Acircumflex'] = 0x00C2; + t['Acircumflexacute'] = 0x1EA4; + t['Acircumflexdotbelow'] = 0x1EAC; + t['Acircumflexgrave'] = 0x1EA6; + t['Acircumflexhookabove'] = 0x1EA8; + t['Acircumflexsmall'] = 0xF7E2; + t['Acircumflextilde'] = 0x1EAA; + t['Acute'] = 0xF6C9; + t['Acutesmall'] = 0xF7B4; + t['Acyrillic'] = 0x0410; + t['Adblgrave'] = 0x0200; + t['Adieresis'] = 0x00C4; + t['Adieresiscyrillic'] = 0x04D2; + t['Adieresismacron'] = 0x01DE; + t['Adieresissmall'] = 0xF7E4; + t['Adotbelow'] = 0x1EA0; + t['Adotmacron'] = 0x01E0; + t['Agrave'] = 0x00C0; + t['Agravesmall'] = 0xF7E0; + t['Ahookabove'] = 0x1EA2; + t['Aiecyrillic'] = 0x04D4; + t['Ainvertedbreve'] = 0x0202; + t['Alpha'] = 0x0391; + t['Alphatonos'] = 0x0386; + t['Amacron'] = 0x0100; + t['Amonospace'] = 0xFF21; + t['Aogonek'] = 0x0104; + t['Aring'] = 0x00C5; + t['Aringacute'] = 0x01FA; + t['Aringbelow'] = 0x1E00; + t['Aringsmall'] = 0xF7E5; + t['Asmall'] = 0xF761; + t['Atilde'] = 0x00C3; + t['Atildesmall'] = 0xF7E3; + t['Aybarmenian'] = 0x0531; + t['B'] = 0x0042; + t['Bcircle'] = 0x24B7; + t['Bdotaccent'] = 0x1E02; + t['Bdotbelow'] = 0x1E04; + t['Becyrillic'] = 0x0411; + t['Benarmenian'] = 0x0532; + t['Beta'] = 0x0392; + t['Bhook'] = 0x0181; + t['Blinebelow'] = 0x1E06; + t['Bmonospace'] = 0xFF22; + t['Brevesmall'] = 0xF6F4; + t['Bsmall'] = 0xF762; + t['Btopbar'] = 0x0182; + t['C'] = 0x0043; + t['Caarmenian'] = 0x053E; + t['Cacute'] = 0x0106; + t['Caron'] = 0xF6CA; + t['Caronsmall'] = 0xF6F5; + t['Ccaron'] = 0x010C; + t['Ccedilla'] = 0x00C7; + t['Ccedillaacute'] = 0x1E08; + t['Ccedillasmall'] = 0xF7E7; + t['Ccircle'] = 0x24B8; + t['Ccircumflex'] = 0x0108; + t['Cdot'] = 0x010A; + t['Cdotaccent'] = 0x010A; + t['Cedillasmall'] = 0xF7B8; + t['Chaarmenian'] = 0x0549; + t['Cheabkhasiancyrillic'] = 0x04BC; + t['Checyrillic'] = 0x0427; + t['Chedescenderabkhasiancyrillic'] = 0x04BE; + t['Chedescendercyrillic'] = 0x04B6; + t['Chedieresiscyrillic'] = 0x04F4; + t['Cheharmenian'] = 0x0543; + t['Chekhakassiancyrillic'] = 0x04CB; + t['Cheverticalstrokecyrillic'] = 0x04B8; + t['Chi'] = 0x03A7; + t['Chook'] = 0x0187; + t['Circumflexsmall'] = 0xF6F6; + t['Cmonospace'] = 0xFF23; + t['Coarmenian'] = 0x0551; + t['Csmall'] = 0xF763; + t['D'] = 0x0044; + t['DZ'] = 0x01F1; + t['DZcaron'] = 0x01C4; + t['Daarmenian'] = 0x0534; + t['Dafrican'] = 0x0189; + t['Dcaron'] = 0x010E; + t['Dcedilla'] = 0x1E10; + t['Dcircle'] = 0x24B9; + t['Dcircumflexbelow'] = 0x1E12; + t['Dcroat'] = 0x0110; + t['Ddotaccent'] = 0x1E0A; + t['Ddotbelow'] = 0x1E0C; + t['Decyrillic'] = 0x0414; + t['Deicoptic'] = 0x03EE; + t['Delta'] = 0x2206; + t['Deltagreek'] = 0x0394; + t['Dhook'] = 0x018A; + t['Dieresis'] = 0xF6CB; + t['DieresisAcute'] = 0xF6CC; + t['DieresisGrave'] = 0xF6CD; + t['Dieresissmall'] = 0xF7A8; + t['Digammagreek'] = 0x03DC; + t['Djecyrillic'] = 0x0402; + t['Dlinebelow'] = 0x1E0E; + t['Dmonospace'] = 0xFF24; + t['Dotaccentsmall'] = 0xF6F7; + t['Dslash'] = 0x0110; + t['Dsmall'] = 0xF764; + t['Dtopbar'] = 0x018B; + t['Dz'] = 0x01F2; + t['Dzcaron'] = 0x01C5; + t['Dzeabkhasiancyrillic'] = 0x04E0; + t['Dzecyrillic'] = 0x0405; + t['Dzhecyrillic'] = 0x040F; + t['E'] = 0x0045; + t['Eacute'] = 0x00C9; + t['Eacutesmall'] = 0xF7E9; + t['Ebreve'] = 0x0114; + t['Ecaron'] = 0x011A; + t['Ecedillabreve'] = 0x1E1C; + t['Echarmenian'] = 0x0535; + t['Ecircle'] = 0x24BA; + t['Ecircumflex'] = 0x00CA; + t['Ecircumflexacute'] = 0x1EBE; + t['Ecircumflexbelow'] = 0x1E18; + t['Ecircumflexdotbelow'] = 0x1EC6; + t['Ecircumflexgrave'] = 0x1EC0; + t['Ecircumflexhookabove'] = 0x1EC2; + t['Ecircumflexsmall'] = 0xF7EA; + t['Ecircumflextilde'] = 0x1EC4; + t['Ecyrillic'] = 0x0404; + t['Edblgrave'] = 0x0204; + t['Edieresis'] = 0x00CB; + t['Edieresissmall'] = 0xF7EB; + t['Edot'] = 0x0116; + t['Edotaccent'] = 0x0116; + t['Edotbelow'] = 0x1EB8; + t['Efcyrillic'] = 0x0424; + t['Egrave'] = 0x00C8; + t['Egravesmall'] = 0xF7E8; + t['Eharmenian'] = 0x0537; + t['Ehookabove'] = 0x1EBA; + t['Eightroman'] = 0x2167; + t['Einvertedbreve'] = 0x0206; + t['Eiotifiedcyrillic'] = 0x0464; + t['Elcyrillic'] = 0x041B; + t['Elevenroman'] = 0x216A; + t['Emacron'] = 0x0112; + t['Emacronacute'] = 0x1E16; + t['Emacrongrave'] = 0x1E14; + t['Emcyrillic'] = 0x041C; + t['Emonospace'] = 0xFF25; + t['Encyrillic'] = 0x041D; + t['Endescendercyrillic'] = 0x04A2; + t['Eng'] = 0x014A; + t['Enghecyrillic'] = 0x04A4; + t['Enhookcyrillic'] = 0x04C7; + t['Eogonek'] = 0x0118; + t['Eopen'] = 0x0190; + t['Epsilon'] = 0x0395; + t['Epsilontonos'] = 0x0388; + t['Ercyrillic'] = 0x0420; + t['Ereversed'] = 0x018E; + t['Ereversedcyrillic'] = 0x042D; + t['Escyrillic'] = 0x0421; + t['Esdescendercyrillic'] = 0x04AA; + t['Esh'] = 0x01A9; + t['Esmall'] = 0xF765; + t['Eta'] = 0x0397; + t['Etarmenian'] = 0x0538; + t['Etatonos'] = 0x0389; + t['Eth'] = 0x00D0; + t['Ethsmall'] = 0xF7F0; + t['Etilde'] = 0x1EBC; + t['Etildebelow'] = 0x1E1A; + t['Euro'] = 0x20AC; + t['Ezh'] = 0x01B7; + t['Ezhcaron'] = 0x01EE; + t['Ezhreversed'] = 0x01B8; + t['F'] = 0x0046; + t['Fcircle'] = 0x24BB; + t['Fdotaccent'] = 0x1E1E; + t['Feharmenian'] = 0x0556; + t['Feicoptic'] = 0x03E4; + t['Fhook'] = 0x0191; + t['Fitacyrillic'] = 0x0472; + t['Fiveroman'] = 0x2164; + t['Fmonospace'] = 0xFF26; + t['Fourroman'] = 0x2163; + t['Fsmall'] = 0xF766; + t['G'] = 0x0047; + t['GBsquare'] = 0x3387; + t['Gacute'] = 0x01F4; + t['Gamma'] = 0x0393; + t['Gammaafrican'] = 0x0194; + t['Gangiacoptic'] = 0x03EA; + t['Gbreve'] = 0x011E; + t['Gcaron'] = 0x01E6; + t['Gcedilla'] = 0x0122; + t['Gcircle'] = 0x24BC; + t['Gcircumflex'] = 0x011C; + t['Gcommaaccent'] = 0x0122; + t['Gdot'] = 0x0120; + t['Gdotaccent'] = 0x0120; + t['Gecyrillic'] = 0x0413; + t['Ghadarmenian'] = 0x0542; + t['Ghemiddlehookcyrillic'] = 0x0494; + t['Ghestrokecyrillic'] = 0x0492; + t['Gheupturncyrillic'] = 0x0490; + t['Ghook'] = 0x0193; + t['Gimarmenian'] = 0x0533; + t['Gjecyrillic'] = 0x0403; + t['Gmacron'] = 0x1E20; + t['Gmonospace'] = 0xFF27; + t['Grave'] = 0xF6CE; + t['Gravesmall'] = 0xF760; + t['Gsmall'] = 0xF767; + t['Gsmallhook'] = 0x029B; + t['Gstroke'] = 0x01E4; + t['H'] = 0x0048; + t['H18533'] = 0x25CF; + t['H18543'] = 0x25AA; + t['H18551'] = 0x25AB; + t['H22073'] = 0x25A1; + t['HPsquare'] = 0x33CB; + t['Haabkhasiancyrillic'] = 0x04A8; + t['Hadescendercyrillic'] = 0x04B2; + t['Hardsigncyrillic'] = 0x042A; + t['Hbar'] = 0x0126; + t['Hbrevebelow'] = 0x1E2A; + t['Hcedilla'] = 0x1E28; + t['Hcircle'] = 0x24BD; + t['Hcircumflex'] = 0x0124; + t['Hdieresis'] = 0x1E26; + t['Hdotaccent'] = 0x1E22; + t['Hdotbelow'] = 0x1E24; + t['Hmonospace'] = 0xFF28; + t['Hoarmenian'] = 0x0540; + t['Horicoptic'] = 0x03E8; + t['Hsmall'] = 0xF768; + t['Hungarumlaut'] = 0xF6CF; + t['Hungarumlautsmall'] = 0xF6F8; + t['Hzsquare'] = 0x3390; + t['I'] = 0x0049; + t['IAcyrillic'] = 0x042F; + t['IJ'] = 0x0132; + t['IUcyrillic'] = 0x042E; + t['Iacute'] = 0x00CD; + t['Iacutesmall'] = 0xF7ED; + t['Ibreve'] = 0x012C; + t['Icaron'] = 0x01CF; + t['Icircle'] = 0x24BE; + t['Icircumflex'] = 0x00CE; + t['Icircumflexsmall'] = 0xF7EE; + t['Icyrillic'] = 0x0406; + t['Idblgrave'] = 0x0208; + t['Idieresis'] = 0x00CF; + t['Idieresisacute'] = 0x1E2E; + t['Idieresiscyrillic'] = 0x04E4; + t['Idieresissmall'] = 0xF7EF; + t['Idot'] = 0x0130; + t['Idotaccent'] = 0x0130; + t['Idotbelow'] = 0x1ECA; + t['Iebrevecyrillic'] = 0x04D6; + t['Iecyrillic'] = 0x0415; + t['Ifraktur'] = 0x2111; + t['Igrave'] = 0x00CC; + t['Igravesmall'] = 0xF7EC; + t['Ihookabove'] = 0x1EC8; + t['Iicyrillic'] = 0x0418; + t['Iinvertedbreve'] = 0x020A; + t['Iishortcyrillic'] = 0x0419; + t['Imacron'] = 0x012A; + t['Imacroncyrillic'] = 0x04E2; + t['Imonospace'] = 0xFF29; + t['Iniarmenian'] = 0x053B; + t['Iocyrillic'] = 0x0401; + t['Iogonek'] = 0x012E; + t['Iota'] = 0x0399; + t['Iotaafrican'] = 0x0196; + t['Iotadieresis'] = 0x03AA; + t['Iotatonos'] = 0x038A; + t['Ismall'] = 0xF769; + t['Istroke'] = 0x0197; + t['Itilde'] = 0x0128; + t['Itildebelow'] = 0x1E2C; + t['Izhitsacyrillic'] = 0x0474; + t['Izhitsadblgravecyrillic'] = 0x0476; + t['J'] = 0x004A; + t['Jaarmenian'] = 0x0541; + t['Jcircle'] = 0x24BF; + t['Jcircumflex'] = 0x0134; + t['Jecyrillic'] = 0x0408; + t['Jheharmenian'] = 0x054B; + t['Jmonospace'] = 0xFF2A; + t['Jsmall'] = 0xF76A; + t['K'] = 0x004B; + t['KBsquare'] = 0x3385; + t['KKsquare'] = 0x33CD; + t['Kabashkircyrillic'] = 0x04A0; + t['Kacute'] = 0x1E30; + t['Kacyrillic'] = 0x041A; + t['Kadescendercyrillic'] = 0x049A; + t['Kahookcyrillic'] = 0x04C3; + t['Kappa'] = 0x039A; + t['Kastrokecyrillic'] = 0x049E; + t['Kaverticalstrokecyrillic'] = 0x049C; + t['Kcaron'] = 0x01E8; + t['Kcedilla'] = 0x0136; + t['Kcircle'] = 0x24C0; + t['Kcommaaccent'] = 0x0136; + t['Kdotbelow'] = 0x1E32; + t['Keharmenian'] = 0x0554; + t['Kenarmenian'] = 0x053F; + t['Khacyrillic'] = 0x0425; + t['Kheicoptic'] = 0x03E6; + t['Khook'] = 0x0198; + t['Kjecyrillic'] = 0x040C; + t['Klinebelow'] = 0x1E34; + t['Kmonospace'] = 0xFF2B; + t['Koppacyrillic'] = 0x0480; + t['Koppagreek'] = 0x03DE; + t['Ksicyrillic'] = 0x046E; + t['Ksmall'] = 0xF76B; + t['L'] = 0x004C; + t['LJ'] = 0x01C7; + t['LL'] = 0xF6BF; + t['Lacute'] = 0x0139; + t['Lambda'] = 0x039B; + t['Lcaron'] = 0x013D; + t['Lcedilla'] = 0x013B; + t['Lcircle'] = 0x24C1; + t['Lcircumflexbelow'] = 0x1E3C; + t['Lcommaaccent'] = 0x013B; + t['Ldot'] = 0x013F; + t['Ldotaccent'] = 0x013F; + t['Ldotbelow'] = 0x1E36; + t['Ldotbelowmacron'] = 0x1E38; + t['Liwnarmenian'] = 0x053C; + t['Lj'] = 0x01C8; + t['Ljecyrillic'] = 0x0409; + t['Llinebelow'] = 0x1E3A; + t['Lmonospace'] = 0xFF2C; + t['Lslash'] = 0x0141; + t['Lslashsmall'] = 0xF6F9; + t['Lsmall'] = 0xF76C; + t['M'] = 0x004D; + t['MBsquare'] = 0x3386; + t['Macron'] = 0xF6D0; + t['Macronsmall'] = 0xF7AF; + t['Macute'] = 0x1E3E; + t['Mcircle'] = 0x24C2; + t['Mdotaccent'] = 0x1E40; + t['Mdotbelow'] = 0x1E42; + t['Menarmenian'] = 0x0544; + t['Mmonospace'] = 0xFF2D; + t['Msmall'] = 0xF76D; + t['Mturned'] = 0x019C; + t['Mu'] = 0x039C; + t['N'] = 0x004E; + t['NJ'] = 0x01CA; + t['Nacute'] = 0x0143; + t['Ncaron'] = 0x0147; + t['Ncedilla'] = 0x0145; + t['Ncircle'] = 0x24C3; + t['Ncircumflexbelow'] = 0x1E4A; + t['Ncommaaccent'] = 0x0145; + t['Ndotaccent'] = 0x1E44; + t['Ndotbelow'] = 0x1E46; + t['Nhookleft'] = 0x019D; + t['Nineroman'] = 0x2168; + t['Nj'] = 0x01CB; + t['Njecyrillic'] = 0x040A; + t['Nlinebelow'] = 0x1E48; + t['Nmonospace'] = 0xFF2E; + t['Nowarmenian'] = 0x0546; + t['Nsmall'] = 0xF76E; + t['Ntilde'] = 0x00D1; + t['Ntildesmall'] = 0xF7F1; + t['Nu'] = 0x039D; + t['O'] = 0x004F; + t['OE'] = 0x0152; + t['OEsmall'] = 0xF6FA; + t['Oacute'] = 0x00D3; + t['Oacutesmall'] = 0xF7F3; + t['Obarredcyrillic'] = 0x04E8; + t['Obarreddieresiscyrillic'] = 0x04EA; + t['Obreve'] = 0x014E; + t['Ocaron'] = 0x01D1; + t['Ocenteredtilde'] = 0x019F; + t['Ocircle'] = 0x24C4; + t['Ocircumflex'] = 0x00D4; + t['Ocircumflexacute'] = 0x1ED0; + t['Ocircumflexdotbelow'] = 0x1ED8; + t['Ocircumflexgrave'] = 0x1ED2; + t['Ocircumflexhookabove'] = 0x1ED4; + t['Ocircumflexsmall'] = 0xF7F4; + t['Ocircumflextilde'] = 0x1ED6; + t['Ocyrillic'] = 0x041E; + t['Odblacute'] = 0x0150; + t['Odblgrave'] = 0x020C; + t['Odieresis'] = 0x00D6; + t['Odieresiscyrillic'] = 0x04E6; + t['Odieresissmall'] = 0xF7F6; + t['Odotbelow'] = 0x1ECC; + t['Ogoneksmall'] = 0xF6FB; + t['Ograve'] = 0x00D2; + t['Ogravesmall'] = 0xF7F2; + t['Oharmenian'] = 0x0555; + t['Ohm'] = 0x2126; + t['Ohookabove'] = 0x1ECE; + t['Ohorn'] = 0x01A0; + t['Ohornacute'] = 0x1EDA; + t['Ohorndotbelow'] = 0x1EE2; + t['Ohorngrave'] = 0x1EDC; + t['Ohornhookabove'] = 0x1EDE; + t['Ohorntilde'] = 0x1EE0; + t['Ohungarumlaut'] = 0x0150; + t['Oi'] = 0x01A2; + t['Oinvertedbreve'] = 0x020E; + t['Omacron'] = 0x014C; + t['Omacronacute'] = 0x1E52; + t['Omacrongrave'] = 0x1E50; + t['Omega'] = 0x2126; + t['Omegacyrillic'] = 0x0460; + t['Omegagreek'] = 0x03A9; + t['Omegaroundcyrillic'] = 0x047A; + t['Omegatitlocyrillic'] = 0x047C; + t['Omegatonos'] = 0x038F; + t['Omicron'] = 0x039F; + t['Omicrontonos'] = 0x038C; + t['Omonospace'] = 0xFF2F; + t['Oneroman'] = 0x2160; + t['Oogonek'] = 0x01EA; + t['Oogonekmacron'] = 0x01EC; + t['Oopen'] = 0x0186; + t['Oslash'] = 0x00D8; + t['Oslashacute'] = 0x01FE; + t['Oslashsmall'] = 0xF7F8; + t['Osmall'] = 0xF76F; + t['Ostrokeacute'] = 0x01FE; + t['Otcyrillic'] = 0x047E; + t['Otilde'] = 0x00D5; + t['Otildeacute'] = 0x1E4C; + t['Otildedieresis'] = 0x1E4E; + t['Otildesmall'] = 0xF7F5; + t['P'] = 0x0050; + t['Pacute'] = 0x1E54; + t['Pcircle'] = 0x24C5; + t['Pdotaccent'] = 0x1E56; + t['Pecyrillic'] = 0x041F; + t['Peharmenian'] = 0x054A; + t['Pemiddlehookcyrillic'] = 0x04A6; + t['Phi'] = 0x03A6; + t['Phook'] = 0x01A4; + t['Pi'] = 0x03A0; + t['Piwrarmenian'] = 0x0553; + t['Pmonospace'] = 0xFF30; + t['Psi'] = 0x03A8; + t['Psicyrillic'] = 0x0470; + t['Psmall'] = 0xF770; + t['Q'] = 0x0051; + t['Qcircle'] = 0x24C6; + t['Qmonospace'] = 0xFF31; + t['Qsmall'] = 0xF771; + t['R'] = 0x0052; + t['Raarmenian'] = 0x054C; + t['Racute'] = 0x0154; + t['Rcaron'] = 0x0158; + t['Rcedilla'] = 0x0156; + t['Rcircle'] = 0x24C7; + t['Rcommaaccent'] = 0x0156; + t['Rdblgrave'] = 0x0210; + t['Rdotaccent'] = 0x1E58; + t['Rdotbelow'] = 0x1E5A; + t['Rdotbelowmacron'] = 0x1E5C; + t['Reharmenian'] = 0x0550; + t['Rfraktur'] = 0x211C; + t['Rho'] = 0x03A1; + t['Ringsmall'] = 0xF6FC; + t['Rinvertedbreve'] = 0x0212; + t['Rlinebelow'] = 0x1E5E; + t['Rmonospace'] = 0xFF32; + t['Rsmall'] = 0xF772; + t['Rsmallinverted'] = 0x0281; + t['Rsmallinvertedsuperior'] = 0x02B6; + t['S'] = 0x0053; + t['SF010000'] = 0x250C; + t['SF020000'] = 0x2514; + t['SF030000'] = 0x2510; + t['SF040000'] = 0x2518; + t['SF050000'] = 0x253C; + t['SF060000'] = 0x252C; + t['SF070000'] = 0x2534; + t['SF080000'] = 0x251C; + t['SF090000'] = 0x2524; + t['SF100000'] = 0x2500; + t['SF110000'] = 0x2502; + t['SF190000'] = 0x2561; + t['SF200000'] = 0x2562; + t['SF210000'] = 0x2556; + t['SF220000'] = 0x2555; + t['SF230000'] = 0x2563; + t['SF240000'] = 0x2551; + t['SF250000'] = 0x2557; + t['SF260000'] = 0x255D; + t['SF270000'] = 0x255C; + t['SF280000'] = 0x255B; + t['SF360000'] = 0x255E; + t['SF370000'] = 0x255F; + t['SF380000'] = 0x255A; + t['SF390000'] = 0x2554; + t['SF400000'] = 0x2569; + t['SF410000'] = 0x2566; + t['SF420000'] = 0x2560; + t['SF430000'] = 0x2550; + t['SF440000'] = 0x256C; + t['SF450000'] = 0x2567; + t['SF460000'] = 0x2568; + t['SF470000'] = 0x2564; + t['SF480000'] = 0x2565; + t['SF490000'] = 0x2559; + t['SF500000'] = 0x2558; + t['SF510000'] = 0x2552; + t['SF520000'] = 0x2553; + t['SF530000'] = 0x256B; + t['SF540000'] = 0x256A; + t['Sacute'] = 0x015A; + t['Sacutedotaccent'] = 0x1E64; + t['Sampigreek'] = 0x03E0; + t['Scaron'] = 0x0160; + t['Scarondotaccent'] = 0x1E66; + t['Scaronsmall'] = 0xF6FD; + t['Scedilla'] = 0x015E; + t['Schwa'] = 0x018F; + t['Schwacyrillic'] = 0x04D8; + t['Schwadieresiscyrillic'] = 0x04DA; + t['Scircle'] = 0x24C8; + t['Scircumflex'] = 0x015C; + t['Scommaaccent'] = 0x0218; + t['Sdotaccent'] = 0x1E60; + t['Sdotbelow'] = 0x1E62; + t['Sdotbelowdotaccent'] = 0x1E68; + t['Seharmenian'] = 0x054D; + t['Sevenroman'] = 0x2166; + t['Shaarmenian'] = 0x0547; + t['Shacyrillic'] = 0x0428; + t['Shchacyrillic'] = 0x0429; + t['Sheicoptic'] = 0x03E2; + t['Shhacyrillic'] = 0x04BA; + t['Shimacoptic'] = 0x03EC; + t['Sigma'] = 0x03A3; + t['Sixroman'] = 0x2165; + t['Smonospace'] = 0xFF33; + t['Softsigncyrillic'] = 0x042C; + t['Ssmall'] = 0xF773; + t['Stigmagreek'] = 0x03DA; + t['T'] = 0x0054; + t['Tau'] = 0x03A4; + t['Tbar'] = 0x0166; + t['Tcaron'] = 0x0164; + t['Tcedilla'] = 0x0162; + t['Tcircle'] = 0x24C9; + t['Tcircumflexbelow'] = 0x1E70; + t['Tcommaaccent'] = 0x0162; + t['Tdotaccent'] = 0x1E6A; + t['Tdotbelow'] = 0x1E6C; + t['Tecyrillic'] = 0x0422; + t['Tedescendercyrillic'] = 0x04AC; + t['Tenroman'] = 0x2169; + t['Tetsecyrillic'] = 0x04B4; + t['Theta'] = 0x0398; + t['Thook'] = 0x01AC; + t['Thorn'] = 0x00DE; + t['Thornsmall'] = 0xF7FE; + t['Threeroman'] = 0x2162; + t['Tildesmall'] = 0xF6FE; + t['Tiwnarmenian'] = 0x054F; + t['Tlinebelow'] = 0x1E6E; + t['Tmonospace'] = 0xFF34; + t['Toarmenian'] = 0x0539; + t['Tonefive'] = 0x01BC; + t['Tonesix'] = 0x0184; + t['Tonetwo'] = 0x01A7; + t['Tretroflexhook'] = 0x01AE; + t['Tsecyrillic'] = 0x0426; + t['Tshecyrillic'] = 0x040B; + t['Tsmall'] = 0xF774; + t['Twelveroman'] = 0x216B; + t['Tworoman'] = 0x2161; + t['U'] = 0x0055; + t['Uacute'] = 0x00DA; + t['Uacutesmall'] = 0xF7FA; + t['Ubreve'] = 0x016C; + t['Ucaron'] = 0x01D3; + t['Ucircle'] = 0x24CA; + t['Ucircumflex'] = 0x00DB; + t['Ucircumflexbelow'] = 0x1E76; + t['Ucircumflexsmall'] = 0xF7FB; + t['Ucyrillic'] = 0x0423; + t['Udblacute'] = 0x0170; + t['Udblgrave'] = 0x0214; + t['Udieresis'] = 0x00DC; + t['Udieresisacute'] = 0x01D7; + t['Udieresisbelow'] = 0x1E72; + t['Udieresiscaron'] = 0x01D9; + t['Udieresiscyrillic'] = 0x04F0; + t['Udieresisgrave'] = 0x01DB; + t['Udieresismacron'] = 0x01D5; + t['Udieresissmall'] = 0xF7FC; + t['Udotbelow'] = 0x1EE4; + t['Ugrave'] = 0x00D9; + t['Ugravesmall'] = 0xF7F9; + t['Uhookabove'] = 0x1EE6; + t['Uhorn'] = 0x01AF; + t['Uhornacute'] = 0x1EE8; + t['Uhorndotbelow'] = 0x1EF0; + t['Uhorngrave'] = 0x1EEA; + t['Uhornhookabove'] = 0x1EEC; + t['Uhorntilde'] = 0x1EEE; + t['Uhungarumlaut'] = 0x0170; + t['Uhungarumlautcyrillic'] = 0x04F2; + t['Uinvertedbreve'] = 0x0216; + t['Ukcyrillic'] = 0x0478; + t['Umacron'] = 0x016A; + t['Umacroncyrillic'] = 0x04EE; + t['Umacrondieresis'] = 0x1E7A; + t['Umonospace'] = 0xFF35; + t['Uogonek'] = 0x0172; + t['Upsilon'] = 0x03A5; + t['Upsilon1'] = 0x03D2; + t['Upsilonacutehooksymbolgreek'] = 0x03D3; + t['Upsilonafrican'] = 0x01B1; + t['Upsilondieresis'] = 0x03AB; + t['Upsilondieresishooksymbolgreek'] = 0x03D4; + t['Upsilonhooksymbol'] = 0x03D2; + t['Upsilontonos'] = 0x038E; + t['Uring'] = 0x016E; + t['Ushortcyrillic'] = 0x040E; + t['Usmall'] = 0xF775; + t['Ustraightcyrillic'] = 0x04AE; + t['Ustraightstrokecyrillic'] = 0x04B0; + t['Utilde'] = 0x0168; + t['Utildeacute'] = 0x1E78; + t['Utildebelow'] = 0x1E74; + t['V'] = 0x0056; + t['Vcircle'] = 0x24CB; + t['Vdotbelow'] = 0x1E7E; + t['Vecyrillic'] = 0x0412; + t['Vewarmenian'] = 0x054E; + t['Vhook'] = 0x01B2; + t['Vmonospace'] = 0xFF36; + t['Voarmenian'] = 0x0548; + t['Vsmall'] = 0xF776; + t['Vtilde'] = 0x1E7C; + t['W'] = 0x0057; + t['Wacute'] = 0x1E82; + t['Wcircle'] = 0x24CC; + t['Wcircumflex'] = 0x0174; + t['Wdieresis'] = 0x1E84; + t['Wdotaccent'] = 0x1E86; + t['Wdotbelow'] = 0x1E88; + t['Wgrave'] = 0x1E80; + t['Wmonospace'] = 0xFF37; + t['Wsmall'] = 0xF777; + t['X'] = 0x0058; + t['Xcircle'] = 0x24CD; + t['Xdieresis'] = 0x1E8C; + t['Xdotaccent'] = 0x1E8A; + t['Xeharmenian'] = 0x053D; + t['Xi'] = 0x039E; + t['Xmonospace'] = 0xFF38; + t['Xsmall'] = 0xF778; + t['Y'] = 0x0059; + t['Yacute'] = 0x00DD; + t['Yacutesmall'] = 0xF7FD; + t['Yatcyrillic'] = 0x0462; + t['Ycircle'] = 0x24CE; + t['Ycircumflex'] = 0x0176; + t['Ydieresis'] = 0x0178; + t['Ydieresissmall'] = 0xF7FF; + t['Ydotaccent'] = 0x1E8E; + t['Ydotbelow'] = 0x1EF4; + t['Yericyrillic'] = 0x042B; + t['Yerudieresiscyrillic'] = 0x04F8; + t['Ygrave'] = 0x1EF2; + t['Yhook'] = 0x01B3; + t['Yhookabove'] = 0x1EF6; + t['Yiarmenian'] = 0x0545; + t['Yicyrillic'] = 0x0407; + t['Yiwnarmenian'] = 0x0552; + t['Ymonospace'] = 0xFF39; + t['Ysmall'] = 0xF779; + t['Ytilde'] = 0x1EF8; + t['Yusbigcyrillic'] = 0x046A; + t['Yusbigiotifiedcyrillic'] = 0x046C; + t['Yuslittlecyrillic'] = 0x0466; + t['Yuslittleiotifiedcyrillic'] = 0x0468; + t['Z'] = 0x005A; + t['Zaarmenian'] = 0x0536; + t['Zacute'] = 0x0179; + t['Zcaron'] = 0x017D; + t['Zcaronsmall'] = 0xF6FF; + t['Zcircle'] = 0x24CF; + t['Zcircumflex'] = 0x1E90; + t['Zdot'] = 0x017B; + t['Zdotaccent'] = 0x017B; + t['Zdotbelow'] = 0x1E92; + t['Zecyrillic'] = 0x0417; + t['Zedescendercyrillic'] = 0x0498; + t['Zedieresiscyrillic'] = 0x04DE; + t['Zeta'] = 0x0396; + t['Zhearmenian'] = 0x053A; + t['Zhebrevecyrillic'] = 0x04C1; + t['Zhecyrillic'] = 0x0416; + t['Zhedescendercyrillic'] = 0x0496; + t['Zhedieresiscyrillic'] = 0x04DC; + t['Zlinebelow'] = 0x1E94; + t['Zmonospace'] = 0xFF3A; + t['Zsmall'] = 0xF77A; + t['Zstroke'] = 0x01B5; + t['a'] = 0x0061; + t['aabengali'] = 0x0986; + t['aacute'] = 0x00E1; + t['aadeva'] = 0x0906; + t['aagujarati'] = 0x0A86; + t['aagurmukhi'] = 0x0A06; + t['aamatragurmukhi'] = 0x0A3E; + t['aarusquare'] = 0x3303; + t['aavowelsignbengali'] = 0x09BE; + t['aavowelsigndeva'] = 0x093E; + t['aavowelsigngujarati'] = 0x0ABE; + t['abbreviationmarkarmenian'] = 0x055F; + t['abbreviationsigndeva'] = 0x0970; + t['abengali'] = 0x0985; + t['abopomofo'] = 0x311A; + t['abreve'] = 0x0103; + t['abreveacute'] = 0x1EAF; + t['abrevecyrillic'] = 0x04D1; + t['abrevedotbelow'] = 0x1EB7; + t['abrevegrave'] = 0x1EB1; + t['abrevehookabove'] = 0x1EB3; + t['abrevetilde'] = 0x1EB5; + t['acaron'] = 0x01CE; + t['acircle'] = 0x24D0; + t['acircumflex'] = 0x00E2; + t['acircumflexacute'] = 0x1EA5; + t['acircumflexdotbelow'] = 0x1EAD; + t['acircumflexgrave'] = 0x1EA7; + t['acircumflexhookabove'] = 0x1EA9; + t['acircumflextilde'] = 0x1EAB; + t['acute'] = 0x00B4; + t['acutebelowcmb'] = 0x0317; + t['acutecmb'] = 0x0301; + t['acutecomb'] = 0x0301; + t['acutedeva'] = 0x0954; + t['acutelowmod'] = 0x02CF; + t['acutetonecmb'] = 0x0341; + t['acyrillic'] = 0x0430; + t['adblgrave'] = 0x0201; + t['addakgurmukhi'] = 0x0A71; + t['adeva'] = 0x0905; + t['adieresis'] = 0x00E4; + t['adieresiscyrillic'] = 0x04D3; + t['adieresismacron'] = 0x01DF; + t['adotbelow'] = 0x1EA1; + t['adotmacron'] = 0x01E1; + t['ae'] = 0x00E6; + t['aeacute'] = 0x01FD; + t['aekorean'] = 0x3150; + t['aemacron'] = 0x01E3; + t['afii00208'] = 0x2015; + t['afii08941'] = 0x20A4; + t['afii10017'] = 0x0410; + t['afii10018'] = 0x0411; + t['afii10019'] = 0x0412; + t['afii10020'] = 0x0413; + t['afii10021'] = 0x0414; + t['afii10022'] = 0x0415; + t['afii10023'] = 0x0401; + t['afii10024'] = 0x0416; + t['afii10025'] = 0x0417; + t['afii10026'] = 0x0418; + t['afii10027'] = 0x0419; + t['afii10028'] = 0x041A; + t['afii10029'] = 0x041B; + t['afii10030'] = 0x041C; + t['afii10031'] = 0x041D; + t['afii10032'] = 0x041E; + t['afii10033'] = 0x041F; + t['afii10034'] = 0x0420; + t['afii10035'] = 0x0421; + t['afii10036'] = 0x0422; + t['afii10037'] = 0x0423; + t['afii10038'] = 0x0424; + t['afii10039'] = 0x0425; + t['afii10040'] = 0x0426; + t['afii10041'] = 0x0427; + t['afii10042'] = 0x0428; + t['afii10043'] = 0x0429; + t['afii10044'] = 0x042A; + t['afii10045'] = 0x042B; + t['afii10046'] = 0x042C; + t['afii10047'] = 0x042D; + t['afii10048'] = 0x042E; + t['afii10049'] = 0x042F; + t['afii10050'] = 0x0490; + t['afii10051'] = 0x0402; + t['afii10052'] = 0x0403; + t['afii10053'] = 0x0404; + t['afii10054'] = 0x0405; + t['afii10055'] = 0x0406; + t['afii10056'] = 0x0407; + t['afii10057'] = 0x0408; + t['afii10058'] = 0x0409; + t['afii10059'] = 0x040A; + t['afii10060'] = 0x040B; + t['afii10061'] = 0x040C; + t['afii10062'] = 0x040E; + t['afii10063'] = 0xF6C4; + t['afii10064'] = 0xF6C5; + t['afii10065'] = 0x0430; + t['afii10066'] = 0x0431; + t['afii10067'] = 0x0432; + t['afii10068'] = 0x0433; + t['afii10069'] = 0x0434; + t['afii10070'] = 0x0435; + t['afii10071'] = 0x0451; + t['afii10072'] = 0x0436; + t['afii10073'] = 0x0437; + t['afii10074'] = 0x0438; + t['afii10075'] = 0x0439; + t['afii10076'] = 0x043A; + t['afii10077'] = 0x043B; + t['afii10078'] = 0x043C; + t['afii10079'] = 0x043D; + t['afii10080'] = 0x043E; + t['afii10081'] = 0x043F; + t['afii10082'] = 0x0440; + t['afii10083'] = 0x0441; + t['afii10084'] = 0x0442; + t['afii10085'] = 0x0443; + t['afii10086'] = 0x0444; + t['afii10087'] = 0x0445; + t['afii10088'] = 0x0446; + t['afii10089'] = 0x0447; + t['afii10090'] = 0x0448; + t['afii10091'] = 0x0449; + t['afii10092'] = 0x044A; + t['afii10093'] = 0x044B; + t['afii10094'] = 0x044C; + t['afii10095'] = 0x044D; + t['afii10096'] = 0x044E; + t['afii10097'] = 0x044F; + t['afii10098'] = 0x0491; + t['afii10099'] = 0x0452; + t['afii10100'] = 0x0453; + t['afii10101'] = 0x0454; + t['afii10102'] = 0x0455; + t['afii10103'] = 0x0456; + t['afii10104'] = 0x0457; + t['afii10105'] = 0x0458; + t['afii10106'] = 0x0459; + t['afii10107'] = 0x045A; + t['afii10108'] = 0x045B; + t['afii10109'] = 0x045C; + t['afii10110'] = 0x045E; + t['afii10145'] = 0x040F; + t['afii10146'] = 0x0462; + t['afii10147'] = 0x0472; + t['afii10148'] = 0x0474; + t['afii10192'] = 0xF6C6; + t['afii10193'] = 0x045F; + t['afii10194'] = 0x0463; + t['afii10195'] = 0x0473; + t['afii10196'] = 0x0475; + t['afii10831'] = 0xF6C7; + t['afii10832'] = 0xF6C8; + t['afii10846'] = 0x04D9; + t['afii299'] = 0x200E; + t['afii300'] = 0x200F; + t['afii301'] = 0x200D; + t['afii57381'] = 0x066A; + t['afii57388'] = 0x060C; + t['afii57392'] = 0x0660; + t['afii57393'] = 0x0661; + t['afii57394'] = 0x0662; + t['afii57395'] = 0x0663; + t['afii57396'] = 0x0664; + t['afii57397'] = 0x0665; + t['afii57398'] = 0x0666; + t['afii57399'] = 0x0667; + t['afii57400'] = 0x0668; + t['afii57401'] = 0x0669; + t['afii57403'] = 0x061B; + t['afii57407'] = 0x061F; + t['afii57409'] = 0x0621; + t['afii57410'] = 0x0622; + t['afii57411'] = 0x0623; + t['afii57412'] = 0x0624; + t['afii57413'] = 0x0625; + t['afii57414'] = 0x0626; + t['afii57415'] = 0x0627; + t['afii57416'] = 0x0628; + t['afii57417'] = 0x0629; + t['afii57418'] = 0x062A; + t['afii57419'] = 0x062B; + t['afii57420'] = 0x062C; + t['afii57421'] = 0x062D; + t['afii57422'] = 0x062E; + t['afii57423'] = 0x062F; + t['afii57424'] = 0x0630; + t['afii57425'] = 0x0631; + t['afii57426'] = 0x0632; + t['afii57427'] = 0x0633; + t['afii57428'] = 0x0634; + t['afii57429'] = 0x0635; + t['afii57430'] = 0x0636; + t['afii57431'] = 0x0637; + t['afii57432'] = 0x0638; + t['afii57433'] = 0x0639; + t['afii57434'] = 0x063A; + t['afii57440'] = 0x0640; + t['afii57441'] = 0x0641; + t['afii57442'] = 0x0642; + t['afii57443'] = 0x0643; + t['afii57444'] = 0x0644; + t['afii57445'] = 0x0645; + t['afii57446'] = 0x0646; + t['afii57448'] = 0x0648; + t['afii57449'] = 0x0649; + t['afii57450'] = 0x064A; + t['afii57451'] = 0x064B; + t['afii57452'] = 0x064C; + t['afii57453'] = 0x064D; + t['afii57454'] = 0x064E; + t['afii57455'] = 0x064F; + t['afii57456'] = 0x0650; + t['afii57457'] = 0x0651; + t['afii57458'] = 0x0652; + t['afii57470'] = 0x0647; + t['afii57505'] = 0x06A4; + t['afii57506'] = 0x067E; + t['afii57507'] = 0x0686; + t['afii57508'] = 0x0698; + t['afii57509'] = 0x06AF; + t['afii57511'] = 0x0679; + t['afii57512'] = 0x0688; + t['afii57513'] = 0x0691; + t['afii57514'] = 0x06BA; + t['afii57519'] = 0x06D2; + t['afii57534'] = 0x06D5; + t['afii57636'] = 0x20AA; + t['afii57645'] = 0x05BE; + t['afii57658'] = 0x05C3; + t['afii57664'] = 0x05D0; + t['afii57665'] = 0x05D1; + t['afii57666'] = 0x05D2; + t['afii57667'] = 0x05D3; + t['afii57668'] = 0x05D4; + t['afii57669'] = 0x05D5; + t['afii57670'] = 0x05D6; + t['afii57671'] = 0x05D7; + t['afii57672'] = 0x05D8; + t['afii57673'] = 0x05D9; + t['afii57674'] = 0x05DA; + t['afii57675'] = 0x05DB; + t['afii57676'] = 0x05DC; + t['afii57677'] = 0x05DD; + t['afii57678'] = 0x05DE; + t['afii57679'] = 0x05DF; + t['afii57680'] = 0x05E0; + t['afii57681'] = 0x05E1; + t['afii57682'] = 0x05E2; + t['afii57683'] = 0x05E3; + t['afii57684'] = 0x05E4; + t['afii57685'] = 0x05E5; + t['afii57686'] = 0x05E6; + t['afii57687'] = 0x05E7; + t['afii57688'] = 0x05E8; + t['afii57689'] = 0x05E9; + t['afii57690'] = 0x05EA; + t['afii57694'] = 0xFB2A; + t['afii57695'] = 0xFB2B; + t['afii57700'] = 0xFB4B; + t['afii57705'] = 0xFB1F; + t['afii57716'] = 0x05F0; + t['afii57717'] = 0x05F1; + t['afii57718'] = 0x05F2; + t['afii57723'] = 0xFB35; + t['afii57793'] = 0x05B4; + t['afii57794'] = 0x05B5; + t['afii57795'] = 0x05B6; + t['afii57796'] = 0x05BB; + t['afii57797'] = 0x05B8; + t['afii57798'] = 0x05B7; + t['afii57799'] = 0x05B0; + t['afii57800'] = 0x05B2; + t['afii57801'] = 0x05B1; + t['afii57802'] = 0x05B3; + t['afii57803'] = 0x05C2; + t['afii57804'] = 0x05C1; + t['afii57806'] = 0x05B9; + t['afii57807'] = 0x05BC; + t['afii57839'] = 0x05BD; + t['afii57841'] = 0x05BF; + t['afii57842'] = 0x05C0; + t['afii57929'] = 0x02BC; + t['afii61248'] = 0x2105; + t['afii61289'] = 0x2113; + t['afii61352'] = 0x2116; + t['afii61573'] = 0x202C; + t['afii61574'] = 0x202D; + t['afii61575'] = 0x202E; + t['afii61664'] = 0x200C; + t['afii63167'] = 0x066D; + t['afii64937'] = 0x02BD; + t['agrave'] = 0x00E0; + t['agujarati'] = 0x0A85; + t['agurmukhi'] = 0x0A05; + t['ahiragana'] = 0x3042; + t['ahookabove'] = 0x1EA3; + t['aibengali'] = 0x0990; + t['aibopomofo'] = 0x311E; + t['aideva'] = 0x0910; + t['aiecyrillic'] = 0x04D5; + t['aigujarati'] = 0x0A90; + t['aigurmukhi'] = 0x0A10; + t['aimatragurmukhi'] = 0x0A48; + t['ainarabic'] = 0x0639; + t['ainfinalarabic'] = 0xFECA; + t['aininitialarabic'] = 0xFECB; + t['ainmedialarabic'] = 0xFECC; + t['ainvertedbreve'] = 0x0203; + t['aivowelsignbengali'] = 0x09C8; + t['aivowelsigndeva'] = 0x0948; + t['aivowelsigngujarati'] = 0x0AC8; + t['akatakana'] = 0x30A2; + t['akatakanahalfwidth'] = 0xFF71; + t['akorean'] = 0x314F; + t['alef'] = 0x05D0; + t['alefarabic'] = 0x0627; + t['alefdageshhebrew'] = 0xFB30; + t['aleffinalarabic'] = 0xFE8E; + t['alefhamzaabovearabic'] = 0x0623; + t['alefhamzaabovefinalarabic'] = 0xFE84; + t['alefhamzabelowarabic'] = 0x0625; + t['alefhamzabelowfinalarabic'] = 0xFE88; + t['alefhebrew'] = 0x05D0; + t['aleflamedhebrew'] = 0xFB4F; + t['alefmaddaabovearabic'] = 0x0622; + t['alefmaddaabovefinalarabic'] = 0xFE82; + t['alefmaksuraarabic'] = 0x0649; + t['alefmaksurafinalarabic'] = 0xFEF0; + t['alefmaksurainitialarabic'] = 0xFEF3; + t['alefmaksuramedialarabic'] = 0xFEF4; + t['alefpatahhebrew'] = 0xFB2E; + t['alefqamatshebrew'] = 0xFB2F; + t['aleph'] = 0x2135; + t['allequal'] = 0x224C; + t['alpha'] = 0x03B1; + t['alphatonos'] = 0x03AC; + t['amacron'] = 0x0101; + t['amonospace'] = 0xFF41; + t['ampersand'] = 0x0026; + t['ampersandmonospace'] = 0xFF06; + t['ampersandsmall'] = 0xF726; + t['amsquare'] = 0x33C2; + t['anbopomofo'] = 0x3122; + t['angbopomofo'] = 0x3124; + t['angbracketleft'] = 0x3008; + t['angbracketright'] = 0x3009; + t['angkhankhuthai'] = 0x0E5A; + t['angle'] = 0x2220; + t['anglebracketleft'] = 0x3008; + t['anglebracketleftvertical'] = 0xFE3F; + t['anglebracketright'] = 0x3009; + t['anglebracketrightvertical'] = 0xFE40; + t['angleleft'] = 0x2329; + t['angleright'] = 0x232A; + t['angstrom'] = 0x212B; + t['anoteleia'] = 0x0387; + t['anudattadeva'] = 0x0952; + t['anusvarabengali'] = 0x0982; + t['anusvaradeva'] = 0x0902; + t['anusvaragujarati'] = 0x0A82; + t['aogonek'] = 0x0105; + t['apaatosquare'] = 0x3300; + t['aparen'] = 0x249C; + t['apostrophearmenian'] = 0x055A; + t['apostrophemod'] = 0x02BC; + t['apple'] = 0xF8FF; + t['approaches'] = 0x2250; + t['approxequal'] = 0x2248; + t['approxequalorimage'] = 0x2252; + t['approximatelyequal'] = 0x2245; + t['araeaekorean'] = 0x318E; + t['araeakorean'] = 0x318D; + t['arc'] = 0x2312; + t['arighthalfring'] = 0x1E9A; + t['aring'] = 0x00E5; + t['aringacute'] = 0x01FB; + t['aringbelow'] = 0x1E01; + t['arrowboth'] = 0x2194; + t['arrowdashdown'] = 0x21E3; + t['arrowdashleft'] = 0x21E0; + t['arrowdashright'] = 0x21E2; + t['arrowdashup'] = 0x21E1; + t['arrowdblboth'] = 0x21D4; + t['arrowdbldown'] = 0x21D3; + t['arrowdblleft'] = 0x21D0; + t['arrowdblright'] = 0x21D2; + t['arrowdblup'] = 0x21D1; + t['arrowdown'] = 0x2193; + t['arrowdownleft'] = 0x2199; + t['arrowdownright'] = 0x2198; + t['arrowdownwhite'] = 0x21E9; + t['arrowheaddownmod'] = 0x02C5; + t['arrowheadleftmod'] = 0x02C2; + t['arrowheadrightmod'] = 0x02C3; + t['arrowheadupmod'] = 0x02C4; + t['arrowhorizex'] = 0xF8E7; + t['arrowleft'] = 0x2190; + t['arrowleftdbl'] = 0x21D0; + t['arrowleftdblstroke'] = 0x21CD; + t['arrowleftoverright'] = 0x21C6; + t['arrowleftwhite'] = 0x21E6; + t['arrowright'] = 0x2192; + t['arrowrightdblstroke'] = 0x21CF; + t['arrowrightheavy'] = 0x279E; + t['arrowrightoverleft'] = 0x21C4; + t['arrowrightwhite'] = 0x21E8; + t['arrowtableft'] = 0x21E4; + t['arrowtabright'] = 0x21E5; + t['arrowup'] = 0x2191; + t['arrowupdn'] = 0x2195; + t['arrowupdnbse'] = 0x21A8; + t['arrowupdownbase'] = 0x21A8; + t['arrowupleft'] = 0x2196; + t['arrowupleftofdown'] = 0x21C5; + t['arrowupright'] = 0x2197; + t['arrowupwhite'] = 0x21E7; + t['arrowvertex'] = 0xF8E6; + t['asciicircum'] = 0x005E; + t['asciicircummonospace'] = 0xFF3E; + t['asciitilde'] = 0x007E; + t['asciitildemonospace'] = 0xFF5E; + t['ascript'] = 0x0251; + t['ascriptturned'] = 0x0252; + t['asmallhiragana'] = 0x3041; + t['asmallkatakana'] = 0x30A1; + t['asmallkatakanahalfwidth'] = 0xFF67; + t['asterisk'] = 0x002A; + t['asteriskaltonearabic'] = 0x066D; + t['asteriskarabic'] = 0x066D; + t['asteriskmath'] = 0x2217; + t['asteriskmonospace'] = 0xFF0A; + t['asterisksmall'] = 0xFE61; + t['asterism'] = 0x2042; + t['asuperior'] = 0xF6E9; + t['asymptoticallyequal'] = 0x2243; + t['at'] = 0x0040; + t['atilde'] = 0x00E3; + t['atmonospace'] = 0xFF20; + t['atsmall'] = 0xFE6B; + t['aturned'] = 0x0250; + t['aubengali'] = 0x0994; + t['aubopomofo'] = 0x3120; + t['audeva'] = 0x0914; + t['augujarati'] = 0x0A94; + t['augurmukhi'] = 0x0A14; + t['aulengthmarkbengali'] = 0x09D7; + t['aumatragurmukhi'] = 0x0A4C; + t['auvowelsignbengali'] = 0x09CC; + t['auvowelsigndeva'] = 0x094C; + t['auvowelsigngujarati'] = 0x0ACC; + t['avagrahadeva'] = 0x093D; + t['aybarmenian'] = 0x0561; + t['ayin'] = 0x05E2; + t['ayinaltonehebrew'] = 0xFB20; + t['ayinhebrew'] = 0x05E2; + t['b'] = 0x0062; + t['babengali'] = 0x09AC; + t['backslash'] = 0x005C; + t['backslashmonospace'] = 0xFF3C; + t['badeva'] = 0x092C; + t['bagujarati'] = 0x0AAC; + t['bagurmukhi'] = 0x0A2C; + t['bahiragana'] = 0x3070; + t['bahtthai'] = 0x0E3F; + t['bakatakana'] = 0x30D0; + t['bar'] = 0x007C; + t['barmonospace'] = 0xFF5C; + t['bbopomofo'] = 0x3105; + t['bcircle'] = 0x24D1; + t['bdotaccent'] = 0x1E03; + t['bdotbelow'] = 0x1E05; + t['beamedsixteenthnotes'] = 0x266C; + t['because'] = 0x2235; + t['becyrillic'] = 0x0431; + t['beharabic'] = 0x0628; + t['behfinalarabic'] = 0xFE90; + t['behinitialarabic'] = 0xFE91; + t['behiragana'] = 0x3079; + t['behmedialarabic'] = 0xFE92; + t['behmeeminitialarabic'] = 0xFC9F; + t['behmeemisolatedarabic'] = 0xFC08; + t['behnoonfinalarabic'] = 0xFC6D; + t['bekatakana'] = 0x30D9; + t['benarmenian'] = 0x0562; + t['bet'] = 0x05D1; + t['beta'] = 0x03B2; + t['betasymbolgreek'] = 0x03D0; + t['betdagesh'] = 0xFB31; + t['betdageshhebrew'] = 0xFB31; + t['bethebrew'] = 0x05D1; + t['betrafehebrew'] = 0xFB4C; + t['bhabengali'] = 0x09AD; + t['bhadeva'] = 0x092D; + t['bhagujarati'] = 0x0AAD; + t['bhagurmukhi'] = 0x0A2D; + t['bhook'] = 0x0253; + t['bihiragana'] = 0x3073; + t['bikatakana'] = 0x30D3; + t['bilabialclick'] = 0x0298; + t['bindigurmukhi'] = 0x0A02; + t['birusquare'] = 0x3331; + t['blackcircle'] = 0x25CF; + t['blackdiamond'] = 0x25C6; + t['blackdownpointingtriangle'] = 0x25BC; + t['blackleftpointingpointer'] = 0x25C4; + t['blackleftpointingtriangle'] = 0x25C0; + t['blacklenticularbracketleft'] = 0x3010; + t['blacklenticularbracketleftvertical'] = 0xFE3B; + t['blacklenticularbracketright'] = 0x3011; + t['blacklenticularbracketrightvertical'] = 0xFE3C; + t['blacklowerlefttriangle'] = 0x25E3; + t['blacklowerrighttriangle'] = 0x25E2; + t['blackrectangle'] = 0x25AC; + t['blackrightpointingpointer'] = 0x25BA; + t['blackrightpointingtriangle'] = 0x25B6; + t['blacksmallsquare'] = 0x25AA; + t['blacksmilingface'] = 0x263B; + t['blacksquare'] = 0x25A0; + t['blackstar'] = 0x2605; + t['blackupperlefttriangle'] = 0x25E4; + t['blackupperrighttriangle'] = 0x25E5; + t['blackuppointingsmalltriangle'] = 0x25B4; + t['blackuppointingtriangle'] = 0x25B2; + t['blank'] = 0x2423; + t['blinebelow'] = 0x1E07; + t['block'] = 0x2588; + t['bmonospace'] = 0xFF42; + t['bobaimaithai'] = 0x0E1A; + t['bohiragana'] = 0x307C; + t['bokatakana'] = 0x30DC; + t['bparen'] = 0x249D; + t['bqsquare'] = 0x33C3; + t['braceex'] = 0xF8F4; + t['braceleft'] = 0x007B; + t['braceleftbt'] = 0xF8F3; + t['braceleftmid'] = 0xF8F2; + t['braceleftmonospace'] = 0xFF5B; + t['braceleftsmall'] = 0xFE5B; + t['bracelefttp'] = 0xF8F1; + t['braceleftvertical'] = 0xFE37; + t['braceright'] = 0x007D; + t['bracerightbt'] = 0xF8FE; + t['bracerightmid'] = 0xF8FD; + t['bracerightmonospace'] = 0xFF5D; + t['bracerightsmall'] = 0xFE5C; + t['bracerighttp'] = 0xF8FC; + t['bracerightvertical'] = 0xFE38; + t['bracketleft'] = 0x005B; + t['bracketleftbt'] = 0xF8F0; + t['bracketleftex'] = 0xF8EF; + t['bracketleftmonospace'] = 0xFF3B; + t['bracketlefttp'] = 0xF8EE; + t['bracketright'] = 0x005D; + t['bracketrightbt'] = 0xF8FB; + t['bracketrightex'] = 0xF8FA; + t['bracketrightmonospace'] = 0xFF3D; + t['bracketrighttp'] = 0xF8F9; + t['breve'] = 0x02D8; + t['brevebelowcmb'] = 0x032E; + t['brevecmb'] = 0x0306; + t['breveinvertedbelowcmb'] = 0x032F; + t['breveinvertedcmb'] = 0x0311; + t['breveinverteddoublecmb'] = 0x0361; + t['bridgebelowcmb'] = 0x032A; + t['bridgeinvertedbelowcmb'] = 0x033A; + t['brokenbar'] = 0x00A6; + t['bstroke'] = 0x0180; + t['bsuperior'] = 0xF6EA; + t['btopbar'] = 0x0183; + t['buhiragana'] = 0x3076; + t['bukatakana'] = 0x30D6; + t['bullet'] = 0x2022; + t['bulletinverse'] = 0x25D8; + t['bulletoperator'] = 0x2219; + t['bullseye'] = 0x25CE; + t['c'] = 0x0063; + t['caarmenian'] = 0x056E; + t['cabengali'] = 0x099A; + t['cacute'] = 0x0107; + t['cadeva'] = 0x091A; + t['cagujarati'] = 0x0A9A; + t['cagurmukhi'] = 0x0A1A; + t['calsquare'] = 0x3388; + t['candrabindubengali'] = 0x0981; + t['candrabinducmb'] = 0x0310; + t['candrabindudeva'] = 0x0901; + t['candrabindugujarati'] = 0x0A81; + t['capslock'] = 0x21EA; + t['careof'] = 0x2105; + t['caron'] = 0x02C7; + t['caronbelowcmb'] = 0x032C; + t['caroncmb'] = 0x030C; + t['carriagereturn'] = 0x21B5; + t['cbopomofo'] = 0x3118; + t['ccaron'] = 0x010D; + t['ccedilla'] = 0x00E7; + t['ccedillaacute'] = 0x1E09; + t['ccircle'] = 0x24D2; + t['ccircumflex'] = 0x0109; + t['ccurl'] = 0x0255; + t['cdot'] = 0x010B; + t['cdotaccent'] = 0x010B; + t['cdsquare'] = 0x33C5; + t['cedilla'] = 0x00B8; + t['cedillacmb'] = 0x0327; + t['cent'] = 0x00A2; + t['centigrade'] = 0x2103; + t['centinferior'] = 0xF6DF; + t['centmonospace'] = 0xFFE0; + t['centoldstyle'] = 0xF7A2; + t['centsuperior'] = 0xF6E0; + t['chaarmenian'] = 0x0579; + t['chabengali'] = 0x099B; + t['chadeva'] = 0x091B; + t['chagujarati'] = 0x0A9B; + t['chagurmukhi'] = 0x0A1B; + t['chbopomofo'] = 0x3114; + t['cheabkhasiancyrillic'] = 0x04BD; + t['checkmark'] = 0x2713; + t['checyrillic'] = 0x0447; + t['chedescenderabkhasiancyrillic'] = 0x04BF; + t['chedescendercyrillic'] = 0x04B7; + t['chedieresiscyrillic'] = 0x04F5; + t['cheharmenian'] = 0x0573; + t['chekhakassiancyrillic'] = 0x04CC; + t['cheverticalstrokecyrillic'] = 0x04B9; + t['chi'] = 0x03C7; + t['chieuchacirclekorean'] = 0x3277; + t['chieuchaparenkorean'] = 0x3217; + t['chieuchcirclekorean'] = 0x3269; + t['chieuchkorean'] = 0x314A; + t['chieuchparenkorean'] = 0x3209; + t['chochangthai'] = 0x0E0A; + t['chochanthai'] = 0x0E08; + t['chochingthai'] = 0x0E09; + t['chochoethai'] = 0x0E0C; + t['chook'] = 0x0188; + t['cieucacirclekorean'] = 0x3276; + t['cieucaparenkorean'] = 0x3216; + t['cieuccirclekorean'] = 0x3268; + t['cieuckorean'] = 0x3148; + t['cieucparenkorean'] = 0x3208; + t['cieucuparenkorean'] = 0x321C; + t['circle'] = 0x25CB; + t['circlecopyrt'] = 0x00A9; + t['circlemultiply'] = 0x2297; + t['circleot'] = 0x2299; + t['circleplus'] = 0x2295; + t['circlepostalmark'] = 0x3036; + t['circlewithlefthalfblack'] = 0x25D0; + t['circlewithrighthalfblack'] = 0x25D1; + t['circumflex'] = 0x02C6; + t['circumflexbelowcmb'] = 0x032D; + t['circumflexcmb'] = 0x0302; + t['clear'] = 0x2327; + t['clickalveolar'] = 0x01C2; + t['clickdental'] = 0x01C0; + t['clicklateral'] = 0x01C1; + t['clickretroflex'] = 0x01C3; + t['club'] = 0x2663; + t['clubsuitblack'] = 0x2663; + t['clubsuitwhite'] = 0x2667; + t['cmcubedsquare'] = 0x33A4; + t['cmonospace'] = 0xFF43; + t['cmsquaredsquare'] = 0x33A0; + t['coarmenian'] = 0x0581; + t['colon'] = 0x003A; + t['colonmonetary'] = 0x20A1; + t['colonmonospace'] = 0xFF1A; + t['colonsign'] = 0x20A1; + t['colonsmall'] = 0xFE55; + t['colontriangularhalfmod'] = 0x02D1; + t['colontriangularmod'] = 0x02D0; + t['comma'] = 0x002C; + t['commaabovecmb'] = 0x0313; + t['commaaboverightcmb'] = 0x0315; + t['commaaccent'] = 0xF6C3; + t['commaarabic'] = 0x060C; + t['commaarmenian'] = 0x055D; + t['commainferior'] = 0xF6E1; + t['commamonospace'] = 0xFF0C; + t['commareversedabovecmb'] = 0x0314; + t['commareversedmod'] = 0x02BD; + t['commasmall'] = 0xFE50; + t['commasuperior'] = 0xF6E2; + t['commaturnedabovecmb'] = 0x0312; + t['commaturnedmod'] = 0x02BB; + t['compass'] = 0x263C; + t['congruent'] = 0x2245; + t['contourintegral'] = 0x222E; + t['control'] = 0x2303; + t['controlACK'] = 0x0006; + t['controlBEL'] = 0x0007; + t['controlBS'] = 0x0008; + t['controlCAN'] = 0x0018; + t['controlCR'] = 0x000D; + t['controlDC1'] = 0x0011; + t['controlDC2'] = 0x0012; + t['controlDC3'] = 0x0013; + t['controlDC4'] = 0x0014; + t['controlDEL'] = 0x007F; + t['controlDLE'] = 0x0010; + t['controlEM'] = 0x0019; + t['controlENQ'] = 0x0005; + t['controlEOT'] = 0x0004; + t['controlESC'] = 0x001B; + t['controlETB'] = 0x0017; + t['controlETX'] = 0x0003; + t['controlFF'] = 0x000C; + t['controlFS'] = 0x001C; + t['controlGS'] = 0x001D; + t['controlHT'] = 0x0009; + t['controlLF'] = 0x000A; + t['controlNAK'] = 0x0015; + t['controlNULL'] = 0x0000; + t['controlRS'] = 0x001E; + t['controlSI'] = 0x000F; + t['controlSO'] = 0x000E; + t['controlSOT'] = 0x0002; + t['controlSTX'] = 0x0001; + t['controlSUB'] = 0x001A; + t['controlSYN'] = 0x0016; + t['controlUS'] = 0x001F; + t['controlVT'] = 0x000B; + t['copyright'] = 0x00A9; + t['copyrightsans'] = 0xF8E9; + t['copyrightserif'] = 0xF6D9; + t['cornerbracketleft'] = 0x300C; + t['cornerbracketlefthalfwidth'] = 0xFF62; + t['cornerbracketleftvertical'] = 0xFE41; + t['cornerbracketright'] = 0x300D; + t['cornerbracketrighthalfwidth'] = 0xFF63; + t['cornerbracketrightvertical'] = 0xFE42; + t['corporationsquare'] = 0x337F; + t['cosquare'] = 0x33C7; + t['coverkgsquare'] = 0x33C6; + t['cparen'] = 0x249E; + t['cruzeiro'] = 0x20A2; + t['cstretched'] = 0x0297; + t['curlyand'] = 0x22CF; + t['curlyor'] = 0x22CE; + t['currency'] = 0x00A4; + t['cyrBreve'] = 0xF6D1; + t['cyrFlex'] = 0xF6D2; + t['cyrbreve'] = 0xF6D4; + t['cyrflex'] = 0xF6D5; + t['d'] = 0x0064; + t['daarmenian'] = 0x0564; + t['dabengali'] = 0x09A6; + t['dadarabic'] = 0x0636; + t['dadeva'] = 0x0926; + t['dadfinalarabic'] = 0xFEBE; + t['dadinitialarabic'] = 0xFEBF; + t['dadmedialarabic'] = 0xFEC0; + t['dagesh'] = 0x05BC; + t['dageshhebrew'] = 0x05BC; + t['dagger'] = 0x2020; + t['daggerdbl'] = 0x2021; + t['dagujarati'] = 0x0AA6; + t['dagurmukhi'] = 0x0A26; + t['dahiragana'] = 0x3060; + t['dakatakana'] = 0x30C0; + t['dalarabic'] = 0x062F; + t['dalet'] = 0x05D3; + t['daletdagesh'] = 0xFB33; + t['daletdageshhebrew'] = 0xFB33; + t['dalethebrew'] = 0x05D3; + t['dalfinalarabic'] = 0xFEAA; + t['dammaarabic'] = 0x064F; + t['dammalowarabic'] = 0x064F; + t['dammatanaltonearabic'] = 0x064C; + t['dammatanarabic'] = 0x064C; + t['danda'] = 0x0964; + t['dargahebrew'] = 0x05A7; + t['dargalefthebrew'] = 0x05A7; + t['dasiapneumatacyrilliccmb'] = 0x0485; + t['dblGrave'] = 0xF6D3; + t['dblanglebracketleft'] = 0x300A; + t['dblanglebracketleftvertical'] = 0xFE3D; + t['dblanglebracketright'] = 0x300B; + t['dblanglebracketrightvertical'] = 0xFE3E; + t['dblarchinvertedbelowcmb'] = 0x032B; + t['dblarrowleft'] = 0x21D4; + t['dblarrowright'] = 0x21D2; + t['dbldanda'] = 0x0965; + t['dblgrave'] = 0xF6D6; + t['dblgravecmb'] = 0x030F; + t['dblintegral'] = 0x222C; + t['dbllowline'] = 0x2017; + t['dbllowlinecmb'] = 0x0333; + t['dbloverlinecmb'] = 0x033F; + t['dblprimemod'] = 0x02BA; + t['dblverticalbar'] = 0x2016; + t['dblverticallineabovecmb'] = 0x030E; + t['dbopomofo'] = 0x3109; + t['dbsquare'] = 0x33C8; + t['dcaron'] = 0x010F; + t['dcedilla'] = 0x1E11; + t['dcircle'] = 0x24D3; + t['dcircumflexbelow'] = 0x1E13; + t['dcroat'] = 0x0111; + t['ddabengali'] = 0x09A1; + t['ddadeva'] = 0x0921; + t['ddagujarati'] = 0x0AA1; + t['ddagurmukhi'] = 0x0A21; + t['ddalarabic'] = 0x0688; + t['ddalfinalarabic'] = 0xFB89; + t['dddhadeva'] = 0x095C; + t['ddhabengali'] = 0x09A2; + t['ddhadeva'] = 0x0922; + t['ddhagujarati'] = 0x0AA2; + t['ddhagurmukhi'] = 0x0A22; + t['ddotaccent'] = 0x1E0B; + t['ddotbelow'] = 0x1E0D; + t['decimalseparatorarabic'] = 0x066B; + t['decimalseparatorpersian'] = 0x066B; + t['decyrillic'] = 0x0434; + t['degree'] = 0x00B0; + t['dehihebrew'] = 0x05AD; + t['dehiragana'] = 0x3067; + t['deicoptic'] = 0x03EF; + t['dekatakana'] = 0x30C7; + t['deleteleft'] = 0x232B; + t['deleteright'] = 0x2326; + t['delta'] = 0x03B4; + t['deltaturned'] = 0x018D; + t['denominatorminusonenumeratorbengali'] = 0x09F8; + t['dezh'] = 0x02A4; + t['dhabengali'] = 0x09A7; + t['dhadeva'] = 0x0927; + t['dhagujarati'] = 0x0AA7; + t['dhagurmukhi'] = 0x0A27; + t['dhook'] = 0x0257; + t['dialytikatonos'] = 0x0385; + t['dialytikatonoscmb'] = 0x0344; + t['diamond'] = 0x2666; + t['diamondsuitwhite'] = 0x2662; + t['dieresis'] = 0x00A8; + t['dieresisacute'] = 0xF6D7; + t['dieresisbelowcmb'] = 0x0324; + t['dieresiscmb'] = 0x0308; + t['dieresisgrave'] = 0xF6D8; + t['dieresistonos'] = 0x0385; + t['dihiragana'] = 0x3062; + t['dikatakana'] = 0x30C2; + t['dittomark'] = 0x3003; + t['divide'] = 0x00F7; + t['divides'] = 0x2223; + t['divisionslash'] = 0x2215; + t['djecyrillic'] = 0x0452; + t['dkshade'] = 0x2593; + t['dlinebelow'] = 0x1E0F; + t['dlsquare'] = 0x3397; + t['dmacron'] = 0x0111; + t['dmonospace'] = 0xFF44; + t['dnblock'] = 0x2584; + t['dochadathai'] = 0x0E0E; + t['dodekthai'] = 0x0E14; + t['dohiragana'] = 0x3069; + t['dokatakana'] = 0x30C9; + t['dollar'] = 0x0024; + t['dollarinferior'] = 0xF6E3; + t['dollarmonospace'] = 0xFF04; + t['dollaroldstyle'] = 0xF724; + t['dollarsmall'] = 0xFE69; + t['dollarsuperior'] = 0xF6E4; + t['dong'] = 0x20AB; + t['dorusquare'] = 0x3326; + t['dotaccent'] = 0x02D9; + t['dotaccentcmb'] = 0x0307; + t['dotbelowcmb'] = 0x0323; + t['dotbelowcomb'] = 0x0323; + t['dotkatakana'] = 0x30FB; + t['dotlessi'] = 0x0131; + t['dotlessj'] = 0xF6BE; + t['dotlessjstrokehook'] = 0x0284; + t['dotmath'] = 0x22C5; + t['dottedcircle'] = 0x25CC; + t['doubleyodpatah'] = 0xFB1F; + t['doubleyodpatahhebrew'] = 0xFB1F; + t['downtackbelowcmb'] = 0x031E; + t['downtackmod'] = 0x02D5; + t['dparen'] = 0x249F; + t['dsuperior'] = 0xF6EB; + t['dtail'] = 0x0256; + t['dtopbar'] = 0x018C; + t['duhiragana'] = 0x3065; + t['dukatakana'] = 0x30C5; + t['dz'] = 0x01F3; + t['dzaltone'] = 0x02A3; + t['dzcaron'] = 0x01C6; + t['dzcurl'] = 0x02A5; + t['dzeabkhasiancyrillic'] = 0x04E1; + t['dzecyrillic'] = 0x0455; + t['dzhecyrillic'] = 0x045F; + t['e'] = 0x0065; + t['eacute'] = 0x00E9; + t['earth'] = 0x2641; + t['ebengali'] = 0x098F; + t['ebopomofo'] = 0x311C; + t['ebreve'] = 0x0115; + t['ecandradeva'] = 0x090D; + t['ecandragujarati'] = 0x0A8D; + t['ecandravowelsigndeva'] = 0x0945; + t['ecandravowelsigngujarati'] = 0x0AC5; + t['ecaron'] = 0x011B; + t['ecedillabreve'] = 0x1E1D; + t['echarmenian'] = 0x0565; + t['echyiwnarmenian'] = 0x0587; + t['ecircle'] = 0x24D4; + t['ecircumflex'] = 0x00EA; + t['ecircumflexacute'] = 0x1EBF; + t['ecircumflexbelow'] = 0x1E19; + t['ecircumflexdotbelow'] = 0x1EC7; + t['ecircumflexgrave'] = 0x1EC1; + t['ecircumflexhookabove'] = 0x1EC3; + t['ecircumflextilde'] = 0x1EC5; + t['ecyrillic'] = 0x0454; + t['edblgrave'] = 0x0205; + t['edeva'] = 0x090F; + t['edieresis'] = 0x00EB; + t['edot'] = 0x0117; + t['edotaccent'] = 0x0117; + t['edotbelow'] = 0x1EB9; + t['eegurmukhi'] = 0x0A0F; + t['eematragurmukhi'] = 0x0A47; + t['efcyrillic'] = 0x0444; + t['egrave'] = 0x00E8; + t['egujarati'] = 0x0A8F; + t['eharmenian'] = 0x0567; + t['ehbopomofo'] = 0x311D; + t['ehiragana'] = 0x3048; + t['ehookabove'] = 0x1EBB; + t['eibopomofo'] = 0x311F; + t['eight'] = 0x0038; + t['eightarabic'] = 0x0668; + t['eightbengali'] = 0x09EE; + t['eightcircle'] = 0x2467; + t['eightcircleinversesansserif'] = 0x2791; + t['eightdeva'] = 0x096E; + t['eighteencircle'] = 0x2471; + t['eighteenparen'] = 0x2485; + t['eighteenperiod'] = 0x2499; + t['eightgujarati'] = 0x0AEE; + t['eightgurmukhi'] = 0x0A6E; + t['eighthackarabic'] = 0x0668; + t['eighthangzhou'] = 0x3028; + t['eighthnotebeamed'] = 0x266B; + t['eightideographicparen'] = 0x3227; + t['eightinferior'] = 0x2088; + t['eightmonospace'] = 0xFF18; + t['eightoldstyle'] = 0xF738; + t['eightparen'] = 0x247B; + t['eightperiod'] = 0x248F; + t['eightpersian'] = 0x06F8; + t['eightroman'] = 0x2177; + t['eightsuperior'] = 0x2078; + t['eightthai'] = 0x0E58; + t['einvertedbreve'] = 0x0207; + t['eiotifiedcyrillic'] = 0x0465; + t['ekatakana'] = 0x30A8; + t['ekatakanahalfwidth'] = 0xFF74; + t['ekonkargurmukhi'] = 0x0A74; + t['ekorean'] = 0x3154; + t['elcyrillic'] = 0x043B; + t['element'] = 0x2208; + t['elevencircle'] = 0x246A; + t['elevenparen'] = 0x247E; + t['elevenperiod'] = 0x2492; + t['elevenroman'] = 0x217A; + t['ellipsis'] = 0x2026; + t['ellipsisvertical'] = 0x22EE; + t['emacron'] = 0x0113; + t['emacronacute'] = 0x1E17; + t['emacrongrave'] = 0x1E15; + t['emcyrillic'] = 0x043C; + t['emdash'] = 0x2014; + t['emdashvertical'] = 0xFE31; + t['emonospace'] = 0xFF45; + t['emphasismarkarmenian'] = 0x055B; + t['emptyset'] = 0x2205; + t['enbopomofo'] = 0x3123; + t['encyrillic'] = 0x043D; + t['endash'] = 0x2013; + t['endashvertical'] = 0xFE32; + t['endescendercyrillic'] = 0x04A3; + t['eng'] = 0x014B; + t['engbopomofo'] = 0x3125; + t['enghecyrillic'] = 0x04A5; + t['enhookcyrillic'] = 0x04C8; + t['enspace'] = 0x2002; + t['eogonek'] = 0x0119; + t['eokorean'] = 0x3153; + t['eopen'] = 0x025B; + t['eopenclosed'] = 0x029A; + t['eopenreversed'] = 0x025C; + t['eopenreversedclosed'] = 0x025E; + t['eopenreversedhook'] = 0x025D; + t['eparen'] = 0x24A0; + t['epsilon'] = 0x03B5; + t['epsilontonos'] = 0x03AD; + t['equal'] = 0x003D; + t['equalmonospace'] = 0xFF1D; + t['equalsmall'] = 0xFE66; + t['equalsuperior'] = 0x207C; + t['equivalence'] = 0x2261; + t['erbopomofo'] = 0x3126; + t['ercyrillic'] = 0x0440; + t['ereversed'] = 0x0258; + t['ereversedcyrillic'] = 0x044D; + t['escyrillic'] = 0x0441; + t['esdescendercyrillic'] = 0x04AB; + t['esh'] = 0x0283; + t['eshcurl'] = 0x0286; + t['eshortdeva'] = 0x090E; + t['eshortvowelsigndeva'] = 0x0946; + t['eshreversedloop'] = 0x01AA; + t['eshsquatreversed'] = 0x0285; + t['esmallhiragana'] = 0x3047; + t['esmallkatakana'] = 0x30A7; + t['esmallkatakanahalfwidth'] = 0xFF6A; + t['estimated'] = 0x212E; + t['esuperior'] = 0xF6EC; + t['eta'] = 0x03B7; + t['etarmenian'] = 0x0568; + t['etatonos'] = 0x03AE; + t['eth'] = 0x00F0; + t['etilde'] = 0x1EBD; + t['etildebelow'] = 0x1E1B; + t['etnahtafoukhhebrew'] = 0x0591; + t['etnahtafoukhlefthebrew'] = 0x0591; + t['etnahtahebrew'] = 0x0591; + t['etnahtalefthebrew'] = 0x0591; + t['eturned'] = 0x01DD; + t['eukorean'] = 0x3161; + t['euro'] = 0x20AC; + t['evowelsignbengali'] = 0x09C7; + t['evowelsigndeva'] = 0x0947; + t['evowelsigngujarati'] = 0x0AC7; + t['exclam'] = 0x0021; + t['exclamarmenian'] = 0x055C; + t['exclamdbl'] = 0x203C; + t['exclamdown'] = 0x00A1; + t['exclamdownsmall'] = 0xF7A1; + t['exclammonospace'] = 0xFF01; + t['exclamsmall'] = 0xF721; + t['existential'] = 0x2203; + t['ezh'] = 0x0292; + t['ezhcaron'] = 0x01EF; + t['ezhcurl'] = 0x0293; + t['ezhreversed'] = 0x01B9; + t['ezhtail'] = 0x01BA; + t['f'] = 0x0066; + t['fadeva'] = 0x095E; + t['fagurmukhi'] = 0x0A5E; + t['fahrenheit'] = 0x2109; + t['fathaarabic'] = 0x064E; + t['fathalowarabic'] = 0x064E; + t['fathatanarabic'] = 0x064B; + t['fbopomofo'] = 0x3108; + t['fcircle'] = 0x24D5; + t['fdotaccent'] = 0x1E1F; + t['feharabic'] = 0x0641; + t['feharmenian'] = 0x0586; + t['fehfinalarabic'] = 0xFED2; + t['fehinitialarabic'] = 0xFED3; + t['fehmedialarabic'] = 0xFED4; + t['feicoptic'] = 0x03E5; + t['female'] = 0x2640; + t['ff'] = 0xFB00; + t['ffi'] = 0xFB03; + t['ffl'] = 0xFB04; + t['fi'] = 0xFB01; + t['fifteencircle'] = 0x246E; + t['fifteenparen'] = 0x2482; + t['fifteenperiod'] = 0x2496; + t['figuredash'] = 0x2012; + t['filledbox'] = 0x25A0; + t['filledrect'] = 0x25AC; + t['finalkaf'] = 0x05DA; + t['finalkafdagesh'] = 0xFB3A; + t['finalkafdageshhebrew'] = 0xFB3A; + t['finalkafhebrew'] = 0x05DA; + t['finalmem'] = 0x05DD; + t['finalmemhebrew'] = 0x05DD; + t['finalnun'] = 0x05DF; + t['finalnunhebrew'] = 0x05DF; + t['finalpe'] = 0x05E3; + t['finalpehebrew'] = 0x05E3; + t['finaltsadi'] = 0x05E5; + t['finaltsadihebrew'] = 0x05E5; + t['firsttonechinese'] = 0x02C9; + t['fisheye'] = 0x25C9; + t['fitacyrillic'] = 0x0473; + t['five'] = 0x0035; + t['fivearabic'] = 0x0665; + t['fivebengali'] = 0x09EB; + t['fivecircle'] = 0x2464; + t['fivecircleinversesansserif'] = 0x278E; + t['fivedeva'] = 0x096B; + t['fiveeighths'] = 0x215D; + t['fivegujarati'] = 0x0AEB; + t['fivegurmukhi'] = 0x0A6B; + t['fivehackarabic'] = 0x0665; + t['fivehangzhou'] = 0x3025; + t['fiveideographicparen'] = 0x3224; + t['fiveinferior'] = 0x2085; + t['fivemonospace'] = 0xFF15; + t['fiveoldstyle'] = 0xF735; + t['fiveparen'] = 0x2478; + t['fiveperiod'] = 0x248C; + t['fivepersian'] = 0x06F5; + t['fiveroman'] = 0x2174; + t['fivesuperior'] = 0x2075; + t['fivethai'] = 0x0E55; + t['fl'] = 0xFB02; + t['florin'] = 0x0192; + t['fmonospace'] = 0xFF46; + t['fmsquare'] = 0x3399; + t['fofanthai'] = 0x0E1F; + t['fofathai'] = 0x0E1D; + t['fongmanthai'] = 0x0E4F; + t['forall'] = 0x2200; + t['four'] = 0x0034; + t['fourarabic'] = 0x0664; + t['fourbengali'] = 0x09EA; + t['fourcircle'] = 0x2463; + t['fourcircleinversesansserif'] = 0x278D; + t['fourdeva'] = 0x096A; + t['fourgujarati'] = 0x0AEA; + t['fourgurmukhi'] = 0x0A6A; + t['fourhackarabic'] = 0x0664; + t['fourhangzhou'] = 0x3024; + t['fourideographicparen'] = 0x3223; + t['fourinferior'] = 0x2084; + t['fourmonospace'] = 0xFF14; + t['fournumeratorbengali'] = 0x09F7; + t['fouroldstyle'] = 0xF734; + t['fourparen'] = 0x2477; + t['fourperiod'] = 0x248B; + t['fourpersian'] = 0x06F4; + t['fourroman'] = 0x2173; + t['foursuperior'] = 0x2074; + t['fourteencircle'] = 0x246D; + t['fourteenparen'] = 0x2481; + t['fourteenperiod'] = 0x2495; + t['fourthai'] = 0x0E54; + t['fourthtonechinese'] = 0x02CB; + t['fparen'] = 0x24A1; + t['fraction'] = 0x2044; + t['franc'] = 0x20A3; + t['g'] = 0x0067; + t['gabengali'] = 0x0997; + t['gacute'] = 0x01F5; + t['gadeva'] = 0x0917; + t['gafarabic'] = 0x06AF; + t['gaffinalarabic'] = 0xFB93; + t['gafinitialarabic'] = 0xFB94; + t['gafmedialarabic'] = 0xFB95; + t['gagujarati'] = 0x0A97; + t['gagurmukhi'] = 0x0A17; + t['gahiragana'] = 0x304C; + t['gakatakana'] = 0x30AC; + t['gamma'] = 0x03B3; + t['gammalatinsmall'] = 0x0263; + t['gammasuperior'] = 0x02E0; + t['gangiacoptic'] = 0x03EB; + t['gbopomofo'] = 0x310D; + t['gbreve'] = 0x011F; + t['gcaron'] = 0x01E7; + t['gcedilla'] = 0x0123; + t['gcircle'] = 0x24D6; + t['gcircumflex'] = 0x011D; + t['gcommaaccent'] = 0x0123; + t['gdot'] = 0x0121; + t['gdotaccent'] = 0x0121; + t['gecyrillic'] = 0x0433; + t['gehiragana'] = 0x3052; + t['gekatakana'] = 0x30B2; + t['geometricallyequal'] = 0x2251; + t['gereshaccenthebrew'] = 0x059C; + t['gereshhebrew'] = 0x05F3; + t['gereshmuqdamhebrew'] = 0x059D; + t['germandbls'] = 0x00DF; + t['gershayimaccenthebrew'] = 0x059E; + t['gershayimhebrew'] = 0x05F4; + t['getamark'] = 0x3013; + t['ghabengali'] = 0x0998; + t['ghadarmenian'] = 0x0572; + t['ghadeva'] = 0x0918; + t['ghagujarati'] = 0x0A98; + t['ghagurmukhi'] = 0x0A18; + t['ghainarabic'] = 0x063A; + t['ghainfinalarabic'] = 0xFECE; + t['ghaininitialarabic'] = 0xFECF; + t['ghainmedialarabic'] = 0xFED0; + t['ghemiddlehookcyrillic'] = 0x0495; + t['ghestrokecyrillic'] = 0x0493; + t['gheupturncyrillic'] = 0x0491; + t['ghhadeva'] = 0x095A; + t['ghhagurmukhi'] = 0x0A5A; + t['ghook'] = 0x0260; + t['ghzsquare'] = 0x3393; + t['gihiragana'] = 0x304E; + t['gikatakana'] = 0x30AE; + t['gimarmenian'] = 0x0563; + t['gimel'] = 0x05D2; + t['gimeldagesh'] = 0xFB32; + t['gimeldageshhebrew'] = 0xFB32; + t['gimelhebrew'] = 0x05D2; + t['gjecyrillic'] = 0x0453; + t['glottalinvertedstroke'] = 0x01BE; + t['glottalstop'] = 0x0294; + t['glottalstopinverted'] = 0x0296; + t['glottalstopmod'] = 0x02C0; + t['glottalstopreversed'] = 0x0295; + t['glottalstopreversedmod'] = 0x02C1; + t['glottalstopreversedsuperior'] = 0x02E4; + t['glottalstopstroke'] = 0x02A1; + t['glottalstopstrokereversed'] = 0x02A2; + t['gmacron'] = 0x1E21; + t['gmonospace'] = 0xFF47; + t['gohiragana'] = 0x3054; + t['gokatakana'] = 0x30B4; + t['gparen'] = 0x24A2; + t['gpasquare'] = 0x33AC; + t['gradient'] = 0x2207; + t['grave'] = 0x0060; + t['gravebelowcmb'] = 0x0316; + t['gravecmb'] = 0x0300; + t['gravecomb'] = 0x0300; + t['gravedeva'] = 0x0953; + t['gravelowmod'] = 0x02CE; + t['gravemonospace'] = 0xFF40; + t['gravetonecmb'] = 0x0340; + t['greater'] = 0x003E; + t['greaterequal'] = 0x2265; + t['greaterequalorless'] = 0x22DB; + t['greatermonospace'] = 0xFF1E; + t['greaterorequivalent'] = 0x2273; + t['greaterorless'] = 0x2277; + t['greateroverequal'] = 0x2267; + t['greatersmall'] = 0xFE65; + t['gscript'] = 0x0261; + t['gstroke'] = 0x01E5; + t['guhiragana'] = 0x3050; + t['guillemotleft'] = 0x00AB; + t['guillemotright'] = 0x00BB; + t['guilsinglleft'] = 0x2039; + t['guilsinglright'] = 0x203A; + t['gukatakana'] = 0x30B0; + t['guramusquare'] = 0x3318; + t['gysquare'] = 0x33C9; + t['h'] = 0x0068; + t['haabkhasiancyrillic'] = 0x04A9; + t['haaltonearabic'] = 0x06C1; + t['habengali'] = 0x09B9; + t['hadescendercyrillic'] = 0x04B3; + t['hadeva'] = 0x0939; + t['hagujarati'] = 0x0AB9; + t['hagurmukhi'] = 0x0A39; + t['haharabic'] = 0x062D; + t['hahfinalarabic'] = 0xFEA2; + t['hahinitialarabic'] = 0xFEA3; + t['hahiragana'] = 0x306F; + t['hahmedialarabic'] = 0xFEA4; + t['haitusquare'] = 0x332A; + t['hakatakana'] = 0x30CF; + t['hakatakanahalfwidth'] = 0xFF8A; + t['halantgurmukhi'] = 0x0A4D; + t['hamzaarabic'] = 0x0621; + t['hamzalowarabic'] = 0x0621; + t['hangulfiller'] = 0x3164; + t['hardsigncyrillic'] = 0x044A; + t['harpoonleftbarbup'] = 0x21BC; + t['harpoonrightbarbup'] = 0x21C0; + t['hasquare'] = 0x33CA; + t['hatafpatah'] = 0x05B2; + t['hatafpatah16'] = 0x05B2; + t['hatafpatah23'] = 0x05B2; + t['hatafpatah2f'] = 0x05B2; + t['hatafpatahhebrew'] = 0x05B2; + t['hatafpatahnarrowhebrew'] = 0x05B2; + t['hatafpatahquarterhebrew'] = 0x05B2; + t['hatafpatahwidehebrew'] = 0x05B2; + t['hatafqamats'] = 0x05B3; + t['hatafqamats1b'] = 0x05B3; + t['hatafqamats28'] = 0x05B3; + t['hatafqamats34'] = 0x05B3; + t['hatafqamatshebrew'] = 0x05B3; + t['hatafqamatsnarrowhebrew'] = 0x05B3; + t['hatafqamatsquarterhebrew'] = 0x05B3; + t['hatafqamatswidehebrew'] = 0x05B3; + t['hatafsegol'] = 0x05B1; + t['hatafsegol17'] = 0x05B1; + t['hatafsegol24'] = 0x05B1; + t['hatafsegol30'] = 0x05B1; + t['hatafsegolhebrew'] = 0x05B1; + t['hatafsegolnarrowhebrew'] = 0x05B1; + t['hatafsegolquarterhebrew'] = 0x05B1; + t['hatafsegolwidehebrew'] = 0x05B1; + t['hbar'] = 0x0127; + t['hbopomofo'] = 0x310F; + t['hbrevebelow'] = 0x1E2B; + t['hcedilla'] = 0x1E29; + t['hcircle'] = 0x24D7; + t['hcircumflex'] = 0x0125; + t['hdieresis'] = 0x1E27; + t['hdotaccent'] = 0x1E23; + t['hdotbelow'] = 0x1E25; + t['he'] = 0x05D4; + t['heart'] = 0x2665; + t['heartsuitblack'] = 0x2665; + t['heartsuitwhite'] = 0x2661; + t['hedagesh'] = 0xFB34; + t['hedageshhebrew'] = 0xFB34; + t['hehaltonearabic'] = 0x06C1; + t['heharabic'] = 0x0647; + t['hehebrew'] = 0x05D4; + t['hehfinalaltonearabic'] = 0xFBA7; + t['hehfinalalttwoarabic'] = 0xFEEA; + t['hehfinalarabic'] = 0xFEEA; + t['hehhamzaabovefinalarabic'] = 0xFBA5; + t['hehhamzaaboveisolatedarabic'] = 0xFBA4; + t['hehinitialaltonearabic'] = 0xFBA8; + t['hehinitialarabic'] = 0xFEEB; + t['hehiragana'] = 0x3078; + t['hehmedialaltonearabic'] = 0xFBA9; + t['hehmedialarabic'] = 0xFEEC; + t['heiseierasquare'] = 0x337B; + t['hekatakana'] = 0x30D8; + t['hekatakanahalfwidth'] = 0xFF8D; + t['hekutaarusquare'] = 0x3336; + t['henghook'] = 0x0267; + t['herutusquare'] = 0x3339; + t['het'] = 0x05D7; + t['hethebrew'] = 0x05D7; + t['hhook'] = 0x0266; + t['hhooksuperior'] = 0x02B1; + t['hieuhacirclekorean'] = 0x327B; + t['hieuhaparenkorean'] = 0x321B; + t['hieuhcirclekorean'] = 0x326D; + t['hieuhkorean'] = 0x314E; + t['hieuhparenkorean'] = 0x320D; + t['hihiragana'] = 0x3072; + t['hikatakana'] = 0x30D2; + t['hikatakanahalfwidth'] = 0xFF8B; + t['hiriq'] = 0x05B4; + t['hiriq14'] = 0x05B4; + t['hiriq21'] = 0x05B4; + t['hiriq2d'] = 0x05B4; + t['hiriqhebrew'] = 0x05B4; + t['hiriqnarrowhebrew'] = 0x05B4; + t['hiriqquarterhebrew'] = 0x05B4; + t['hiriqwidehebrew'] = 0x05B4; + t['hlinebelow'] = 0x1E96; + t['hmonospace'] = 0xFF48; + t['hoarmenian'] = 0x0570; + t['hohipthai'] = 0x0E2B; + t['hohiragana'] = 0x307B; + t['hokatakana'] = 0x30DB; + t['hokatakanahalfwidth'] = 0xFF8E; + t['holam'] = 0x05B9; + t['holam19'] = 0x05B9; + t['holam26'] = 0x05B9; + t['holam32'] = 0x05B9; + t['holamhebrew'] = 0x05B9; + t['holamnarrowhebrew'] = 0x05B9; + t['holamquarterhebrew'] = 0x05B9; + t['holamwidehebrew'] = 0x05B9; + t['honokhukthai'] = 0x0E2E; + t['hookabovecomb'] = 0x0309; + t['hookcmb'] = 0x0309; + t['hookpalatalizedbelowcmb'] = 0x0321; + t['hookretroflexbelowcmb'] = 0x0322; + t['hoonsquare'] = 0x3342; + t['horicoptic'] = 0x03E9; + t['horizontalbar'] = 0x2015; + t['horncmb'] = 0x031B; + t['hotsprings'] = 0x2668; + t['house'] = 0x2302; + t['hparen'] = 0x24A3; + t['hsuperior'] = 0x02B0; + t['hturned'] = 0x0265; + t['huhiragana'] = 0x3075; + t['huiitosquare'] = 0x3333; + t['hukatakana'] = 0x30D5; + t['hukatakanahalfwidth'] = 0xFF8C; + t['hungarumlaut'] = 0x02DD; + t['hungarumlautcmb'] = 0x030B; + t['hv'] = 0x0195; + t['hyphen'] = 0x002D; + t['hypheninferior'] = 0xF6E5; + t['hyphenmonospace'] = 0xFF0D; + t['hyphensmall'] = 0xFE63; + t['hyphensuperior'] = 0xF6E6; + t['hyphentwo'] = 0x2010; + t['i'] = 0x0069; + t['iacute'] = 0x00ED; + t['iacyrillic'] = 0x044F; + t['ibengali'] = 0x0987; + t['ibopomofo'] = 0x3127; + t['ibreve'] = 0x012D; + t['icaron'] = 0x01D0; + t['icircle'] = 0x24D8; + t['icircumflex'] = 0x00EE; + t['icyrillic'] = 0x0456; + t['idblgrave'] = 0x0209; + t['ideographearthcircle'] = 0x328F; + t['ideographfirecircle'] = 0x328B; + t['ideographicallianceparen'] = 0x323F; + t['ideographiccallparen'] = 0x323A; + t['ideographiccentrecircle'] = 0x32A5; + t['ideographicclose'] = 0x3006; + t['ideographiccomma'] = 0x3001; + t['ideographiccommaleft'] = 0xFF64; + t['ideographiccongratulationparen'] = 0x3237; + t['ideographiccorrectcircle'] = 0x32A3; + t['ideographicearthparen'] = 0x322F; + t['ideographicenterpriseparen'] = 0x323D; + t['ideographicexcellentcircle'] = 0x329D; + t['ideographicfestivalparen'] = 0x3240; + t['ideographicfinancialcircle'] = 0x3296; + t['ideographicfinancialparen'] = 0x3236; + t['ideographicfireparen'] = 0x322B; + t['ideographichaveparen'] = 0x3232; + t['ideographichighcircle'] = 0x32A4; + t['ideographiciterationmark'] = 0x3005; + t['ideographiclaborcircle'] = 0x3298; + t['ideographiclaborparen'] = 0x3238; + t['ideographicleftcircle'] = 0x32A7; + t['ideographiclowcircle'] = 0x32A6; + t['ideographicmedicinecircle'] = 0x32A9; + t['ideographicmetalparen'] = 0x322E; + t['ideographicmoonparen'] = 0x322A; + t['ideographicnameparen'] = 0x3234; + t['ideographicperiod'] = 0x3002; + t['ideographicprintcircle'] = 0x329E; + t['ideographicreachparen'] = 0x3243; + t['ideographicrepresentparen'] = 0x3239; + t['ideographicresourceparen'] = 0x323E; + t['ideographicrightcircle'] = 0x32A8; + t['ideographicsecretcircle'] = 0x3299; + t['ideographicselfparen'] = 0x3242; + t['ideographicsocietyparen'] = 0x3233; + t['ideographicspace'] = 0x3000; + t['ideographicspecialparen'] = 0x3235; + t['ideographicstockparen'] = 0x3231; + t['ideographicstudyparen'] = 0x323B; + t['ideographicsunparen'] = 0x3230; + t['ideographicsuperviseparen'] = 0x323C; + t['ideographicwaterparen'] = 0x322C; + t['ideographicwoodparen'] = 0x322D; + t['ideographiczero'] = 0x3007; + t['ideographmetalcircle'] = 0x328E; + t['ideographmooncircle'] = 0x328A; + t['ideographnamecircle'] = 0x3294; + t['ideographsuncircle'] = 0x3290; + t['ideographwatercircle'] = 0x328C; + t['ideographwoodcircle'] = 0x328D; + t['ideva'] = 0x0907; + t['idieresis'] = 0x00EF; + t['idieresisacute'] = 0x1E2F; + t['idieresiscyrillic'] = 0x04E5; + t['idotbelow'] = 0x1ECB; + t['iebrevecyrillic'] = 0x04D7; + t['iecyrillic'] = 0x0435; + t['ieungacirclekorean'] = 0x3275; + t['ieungaparenkorean'] = 0x3215; + t['ieungcirclekorean'] = 0x3267; + t['ieungkorean'] = 0x3147; + t['ieungparenkorean'] = 0x3207; + t['igrave'] = 0x00EC; + t['igujarati'] = 0x0A87; + t['igurmukhi'] = 0x0A07; + t['ihiragana'] = 0x3044; + t['ihookabove'] = 0x1EC9; + t['iibengali'] = 0x0988; + t['iicyrillic'] = 0x0438; + t['iideva'] = 0x0908; + t['iigujarati'] = 0x0A88; + t['iigurmukhi'] = 0x0A08; + t['iimatragurmukhi'] = 0x0A40; + t['iinvertedbreve'] = 0x020B; + t['iishortcyrillic'] = 0x0439; + t['iivowelsignbengali'] = 0x09C0; + t['iivowelsigndeva'] = 0x0940; + t['iivowelsigngujarati'] = 0x0AC0; + t['ij'] = 0x0133; + t['ikatakana'] = 0x30A4; + t['ikatakanahalfwidth'] = 0xFF72; + t['ikorean'] = 0x3163; + t['ilde'] = 0x02DC; + t['iluyhebrew'] = 0x05AC; + t['imacron'] = 0x012B; + t['imacroncyrillic'] = 0x04E3; + t['imageorapproximatelyequal'] = 0x2253; + t['imatragurmukhi'] = 0x0A3F; + t['imonospace'] = 0xFF49; + t['increment'] = 0x2206; + t['infinity'] = 0x221E; + t['iniarmenian'] = 0x056B; + t['integral'] = 0x222B; + t['integralbottom'] = 0x2321; + t['integralbt'] = 0x2321; + t['integralex'] = 0xF8F5; + t['integraltop'] = 0x2320; + t['integraltp'] = 0x2320; + t['intersection'] = 0x2229; + t['intisquare'] = 0x3305; + t['invbullet'] = 0x25D8; + t['invcircle'] = 0x25D9; + t['invsmileface'] = 0x263B; + t['iocyrillic'] = 0x0451; + t['iogonek'] = 0x012F; + t['iota'] = 0x03B9; + t['iotadieresis'] = 0x03CA; + t['iotadieresistonos'] = 0x0390; + t['iotalatin'] = 0x0269; + t['iotatonos'] = 0x03AF; + t['iparen'] = 0x24A4; + t['irigurmukhi'] = 0x0A72; + t['ismallhiragana'] = 0x3043; + t['ismallkatakana'] = 0x30A3; + t['ismallkatakanahalfwidth'] = 0xFF68; + t['issharbengali'] = 0x09FA; + t['istroke'] = 0x0268; + t['isuperior'] = 0xF6ED; + t['iterationhiragana'] = 0x309D; + t['iterationkatakana'] = 0x30FD; + t['itilde'] = 0x0129; + t['itildebelow'] = 0x1E2D; + t['iubopomofo'] = 0x3129; + t['iucyrillic'] = 0x044E; + t['ivowelsignbengali'] = 0x09BF; + t['ivowelsigndeva'] = 0x093F; + t['ivowelsigngujarati'] = 0x0ABF; + t['izhitsacyrillic'] = 0x0475; + t['izhitsadblgravecyrillic'] = 0x0477; + t['j'] = 0x006A; + t['jaarmenian'] = 0x0571; + t['jabengali'] = 0x099C; + t['jadeva'] = 0x091C; + t['jagujarati'] = 0x0A9C; + t['jagurmukhi'] = 0x0A1C; + t['jbopomofo'] = 0x3110; + t['jcaron'] = 0x01F0; + t['jcircle'] = 0x24D9; + t['jcircumflex'] = 0x0135; + t['jcrossedtail'] = 0x029D; + t['jdotlessstroke'] = 0x025F; + t['jecyrillic'] = 0x0458; + t['jeemarabic'] = 0x062C; + t['jeemfinalarabic'] = 0xFE9E; + t['jeeminitialarabic'] = 0xFE9F; + t['jeemmedialarabic'] = 0xFEA0; + t['jeharabic'] = 0x0698; + t['jehfinalarabic'] = 0xFB8B; + t['jhabengali'] = 0x099D; + t['jhadeva'] = 0x091D; + t['jhagujarati'] = 0x0A9D; + t['jhagurmukhi'] = 0x0A1D; + t['jheharmenian'] = 0x057B; + t['jis'] = 0x3004; + t['jmonospace'] = 0xFF4A; + t['jparen'] = 0x24A5; + t['jsuperior'] = 0x02B2; + t['k'] = 0x006B; + t['kabashkircyrillic'] = 0x04A1; + t['kabengali'] = 0x0995; + t['kacute'] = 0x1E31; + t['kacyrillic'] = 0x043A; + t['kadescendercyrillic'] = 0x049B; + t['kadeva'] = 0x0915; + t['kaf'] = 0x05DB; + t['kafarabic'] = 0x0643; + t['kafdagesh'] = 0xFB3B; + t['kafdageshhebrew'] = 0xFB3B; + t['kaffinalarabic'] = 0xFEDA; + t['kafhebrew'] = 0x05DB; + t['kafinitialarabic'] = 0xFEDB; + t['kafmedialarabic'] = 0xFEDC; + t['kafrafehebrew'] = 0xFB4D; + t['kagujarati'] = 0x0A95; + t['kagurmukhi'] = 0x0A15; + t['kahiragana'] = 0x304B; + t['kahookcyrillic'] = 0x04C4; + t['kakatakana'] = 0x30AB; + t['kakatakanahalfwidth'] = 0xFF76; + t['kappa'] = 0x03BA; + t['kappasymbolgreek'] = 0x03F0; + t['kapyeounmieumkorean'] = 0x3171; + t['kapyeounphieuphkorean'] = 0x3184; + t['kapyeounpieupkorean'] = 0x3178; + t['kapyeounssangpieupkorean'] = 0x3179; + t['karoriisquare'] = 0x330D; + t['kashidaautoarabic'] = 0x0640; + t['kashidaautonosidebearingarabic'] = 0x0640; + t['kasmallkatakana'] = 0x30F5; + t['kasquare'] = 0x3384; + t['kasraarabic'] = 0x0650; + t['kasratanarabic'] = 0x064D; + t['kastrokecyrillic'] = 0x049F; + t['katahiraprolongmarkhalfwidth'] = 0xFF70; + t['kaverticalstrokecyrillic'] = 0x049D; + t['kbopomofo'] = 0x310E; + t['kcalsquare'] = 0x3389; + t['kcaron'] = 0x01E9; + t['kcedilla'] = 0x0137; + t['kcircle'] = 0x24DA; + t['kcommaaccent'] = 0x0137; + t['kdotbelow'] = 0x1E33; + t['keharmenian'] = 0x0584; + t['kehiragana'] = 0x3051; + t['kekatakana'] = 0x30B1; + t['kekatakanahalfwidth'] = 0xFF79; + t['kenarmenian'] = 0x056F; + t['kesmallkatakana'] = 0x30F6; + t['kgreenlandic'] = 0x0138; + t['khabengali'] = 0x0996; + t['khacyrillic'] = 0x0445; + t['khadeva'] = 0x0916; + t['khagujarati'] = 0x0A96; + t['khagurmukhi'] = 0x0A16; + t['khaharabic'] = 0x062E; + t['khahfinalarabic'] = 0xFEA6; + t['khahinitialarabic'] = 0xFEA7; + t['khahmedialarabic'] = 0xFEA8; + t['kheicoptic'] = 0x03E7; + t['khhadeva'] = 0x0959; + t['khhagurmukhi'] = 0x0A59; + t['khieukhacirclekorean'] = 0x3278; + t['khieukhaparenkorean'] = 0x3218; + t['khieukhcirclekorean'] = 0x326A; + t['khieukhkorean'] = 0x314B; + t['khieukhparenkorean'] = 0x320A; + t['khokhaithai'] = 0x0E02; + t['khokhonthai'] = 0x0E05; + t['khokhuatthai'] = 0x0E03; + t['khokhwaithai'] = 0x0E04; + t['khomutthai'] = 0x0E5B; + t['khook'] = 0x0199; + t['khorakhangthai'] = 0x0E06; + t['khzsquare'] = 0x3391; + t['kihiragana'] = 0x304D; + t['kikatakana'] = 0x30AD; + t['kikatakanahalfwidth'] = 0xFF77; + t['kiroguramusquare'] = 0x3315; + t['kiromeetorusquare'] = 0x3316; + t['kirosquare'] = 0x3314; + t['kiyeokacirclekorean'] = 0x326E; + t['kiyeokaparenkorean'] = 0x320E; + t['kiyeokcirclekorean'] = 0x3260; + t['kiyeokkorean'] = 0x3131; + t['kiyeokparenkorean'] = 0x3200; + t['kiyeoksioskorean'] = 0x3133; + t['kjecyrillic'] = 0x045C; + t['klinebelow'] = 0x1E35; + t['klsquare'] = 0x3398; + t['kmcubedsquare'] = 0x33A6; + t['kmonospace'] = 0xFF4B; + t['kmsquaredsquare'] = 0x33A2; + t['kohiragana'] = 0x3053; + t['kohmsquare'] = 0x33C0; + t['kokaithai'] = 0x0E01; + t['kokatakana'] = 0x30B3; + t['kokatakanahalfwidth'] = 0xFF7A; + t['kooposquare'] = 0x331E; + t['koppacyrillic'] = 0x0481; + t['koreanstandardsymbol'] = 0x327F; + t['koroniscmb'] = 0x0343; + t['kparen'] = 0x24A6; + t['kpasquare'] = 0x33AA; + t['ksicyrillic'] = 0x046F; + t['ktsquare'] = 0x33CF; + t['kturned'] = 0x029E; + t['kuhiragana'] = 0x304F; + t['kukatakana'] = 0x30AF; + t['kukatakanahalfwidth'] = 0xFF78; + t['kvsquare'] = 0x33B8; + t['kwsquare'] = 0x33BE; + t['l'] = 0x006C; + t['labengali'] = 0x09B2; + t['lacute'] = 0x013A; + t['ladeva'] = 0x0932; + t['lagujarati'] = 0x0AB2; + t['lagurmukhi'] = 0x0A32; + t['lakkhangyaothai'] = 0x0E45; + t['lamaleffinalarabic'] = 0xFEFC; + t['lamalefhamzaabovefinalarabic'] = 0xFEF8; + t['lamalefhamzaaboveisolatedarabic'] = 0xFEF7; + t['lamalefhamzabelowfinalarabic'] = 0xFEFA; + t['lamalefhamzabelowisolatedarabic'] = 0xFEF9; + t['lamalefisolatedarabic'] = 0xFEFB; + t['lamalefmaddaabovefinalarabic'] = 0xFEF6; + t['lamalefmaddaaboveisolatedarabic'] = 0xFEF5; + t['lamarabic'] = 0x0644; + t['lambda'] = 0x03BB; + t['lambdastroke'] = 0x019B; + t['lamed'] = 0x05DC; + t['lameddagesh'] = 0xFB3C; + t['lameddageshhebrew'] = 0xFB3C; + t['lamedhebrew'] = 0x05DC; + t['lamfinalarabic'] = 0xFEDE; + t['lamhahinitialarabic'] = 0xFCCA; + t['laminitialarabic'] = 0xFEDF; + t['lamjeeminitialarabic'] = 0xFCC9; + t['lamkhahinitialarabic'] = 0xFCCB; + t['lamlamhehisolatedarabic'] = 0xFDF2; + t['lammedialarabic'] = 0xFEE0; + t['lammeemhahinitialarabic'] = 0xFD88; + t['lammeeminitialarabic'] = 0xFCCC; + t['largecircle'] = 0x25EF; + t['lbar'] = 0x019A; + t['lbelt'] = 0x026C; + t['lbopomofo'] = 0x310C; + t['lcaron'] = 0x013E; + t['lcedilla'] = 0x013C; + t['lcircle'] = 0x24DB; + t['lcircumflexbelow'] = 0x1E3D; + t['lcommaaccent'] = 0x013C; + t['ldot'] = 0x0140; + t['ldotaccent'] = 0x0140; + t['ldotbelow'] = 0x1E37; + t['ldotbelowmacron'] = 0x1E39; + t['leftangleabovecmb'] = 0x031A; + t['lefttackbelowcmb'] = 0x0318; + t['less'] = 0x003C; + t['lessequal'] = 0x2264; + t['lessequalorgreater'] = 0x22DA; + t['lessmonospace'] = 0xFF1C; + t['lessorequivalent'] = 0x2272; + t['lessorgreater'] = 0x2276; + t['lessoverequal'] = 0x2266; + t['lesssmall'] = 0xFE64; + t['lezh'] = 0x026E; + t['lfblock'] = 0x258C; + t['lhookretroflex'] = 0x026D; + t['lira'] = 0x20A4; + t['liwnarmenian'] = 0x056C; + t['lj'] = 0x01C9; + t['ljecyrillic'] = 0x0459; + t['ll'] = 0xF6C0; + t['lladeva'] = 0x0933; + t['llagujarati'] = 0x0AB3; + t['llinebelow'] = 0x1E3B; + t['llladeva'] = 0x0934; + t['llvocalicbengali'] = 0x09E1; + t['llvocalicdeva'] = 0x0961; + t['llvocalicvowelsignbengali'] = 0x09E3; + t['llvocalicvowelsigndeva'] = 0x0963; + t['lmiddletilde'] = 0x026B; + t['lmonospace'] = 0xFF4C; + t['lmsquare'] = 0x33D0; + t['lochulathai'] = 0x0E2C; + t['logicaland'] = 0x2227; + t['logicalnot'] = 0x00AC; + t['logicalnotreversed'] = 0x2310; + t['logicalor'] = 0x2228; + t['lolingthai'] = 0x0E25; + t['longs'] = 0x017F; + t['lowlinecenterline'] = 0xFE4E; + t['lowlinecmb'] = 0x0332; + t['lowlinedashed'] = 0xFE4D; + t['lozenge'] = 0x25CA; + t['lparen'] = 0x24A7; + t['lslash'] = 0x0142; + t['lsquare'] = 0x2113; + t['lsuperior'] = 0xF6EE; + t['ltshade'] = 0x2591; + t['luthai'] = 0x0E26; + t['lvocalicbengali'] = 0x098C; + t['lvocalicdeva'] = 0x090C; + t['lvocalicvowelsignbengali'] = 0x09E2; + t['lvocalicvowelsigndeva'] = 0x0962; + t['lxsquare'] = 0x33D3; + t['m'] = 0x006D; + t['mabengali'] = 0x09AE; + t['macron'] = 0x00AF; + t['macronbelowcmb'] = 0x0331; + t['macroncmb'] = 0x0304; + t['macronlowmod'] = 0x02CD; + t['macronmonospace'] = 0xFFE3; + t['macute'] = 0x1E3F; + t['madeva'] = 0x092E; + t['magujarati'] = 0x0AAE; + t['magurmukhi'] = 0x0A2E; + t['mahapakhhebrew'] = 0x05A4; + t['mahapakhlefthebrew'] = 0x05A4; + t['mahiragana'] = 0x307E; + t['maichattawalowleftthai'] = 0xF895; + t['maichattawalowrightthai'] = 0xF894; + t['maichattawathai'] = 0x0E4B; + t['maichattawaupperleftthai'] = 0xF893; + t['maieklowleftthai'] = 0xF88C; + t['maieklowrightthai'] = 0xF88B; + t['maiekthai'] = 0x0E48; + t['maiekupperleftthai'] = 0xF88A; + t['maihanakatleftthai'] = 0xF884; + t['maihanakatthai'] = 0x0E31; + t['maitaikhuleftthai'] = 0xF889; + t['maitaikhuthai'] = 0x0E47; + t['maitholowleftthai'] = 0xF88F; + t['maitholowrightthai'] = 0xF88E; + t['maithothai'] = 0x0E49; + t['maithoupperleftthai'] = 0xF88D; + t['maitrilowleftthai'] = 0xF892; + t['maitrilowrightthai'] = 0xF891; + t['maitrithai'] = 0x0E4A; + t['maitriupperleftthai'] = 0xF890; + t['maiyamokthai'] = 0x0E46; + t['makatakana'] = 0x30DE; + t['makatakanahalfwidth'] = 0xFF8F; + t['male'] = 0x2642; + t['mansyonsquare'] = 0x3347; + t['maqafhebrew'] = 0x05BE; + t['mars'] = 0x2642; + t['masoracirclehebrew'] = 0x05AF; + t['masquare'] = 0x3383; + t['mbopomofo'] = 0x3107; + t['mbsquare'] = 0x33D4; + t['mcircle'] = 0x24DC; + t['mcubedsquare'] = 0x33A5; + t['mdotaccent'] = 0x1E41; + t['mdotbelow'] = 0x1E43; + t['meemarabic'] = 0x0645; + t['meemfinalarabic'] = 0xFEE2; + t['meeminitialarabic'] = 0xFEE3; + t['meemmedialarabic'] = 0xFEE4; + t['meemmeeminitialarabic'] = 0xFCD1; + t['meemmeemisolatedarabic'] = 0xFC48; + t['meetorusquare'] = 0x334D; + t['mehiragana'] = 0x3081; + t['meizierasquare'] = 0x337E; + t['mekatakana'] = 0x30E1; + t['mekatakanahalfwidth'] = 0xFF92; + t['mem'] = 0x05DE; + t['memdagesh'] = 0xFB3E; + t['memdageshhebrew'] = 0xFB3E; + t['memhebrew'] = 0x05DE; + t['menarmenian'] = 0x0574; + t['merkhahebrew'] = 0x05A5; + t['merkhakefulahebrew'] = 0x05A6; + t['merkhakefulalefthebrew'] = 0x05A6; + t['merkhalefthebrew'] = 0x05A5; + t['mhook'] = 0x0271; + t['mhzsquare'] = 0x3392; + t['middledotkatakanahalfwidth'] = 0xFF65; + t['middot'] = 0x00B7; + t['mieumacirclekorean'] = 0x3272; + t['mieumaparenkorean'] = 0x3212; + t['mieumcirclekorean'] = 0x3264; + t['mieumkorean'] = 0x3141; + t['mieumpansioskorean'] = 0x3170; + t['mieumparenkorean'] = 0x3204; + t['mieumpieupkorean'] = 0x316E; + t['mieumsioskorean'] = 0x316F; + t['mihiragana'] = 0x307F; + t['mikatakana'] = 0x30DF; + t['mikatakanahalfwidth'] = 0xFF90; + t['minus'] = 0x2212; + t['minusbelowcmb'] = 0x0320; + t['minuscircle'] = 0x2296; + t['minusmod'] = 0x02D7; + t['minusplus'] = 0x2213; + t['minute'] = 0x2032; + t['miribaarusquare'] = 0x334A; + t['mirisquare'] = 0x3349; + t['mlonglegturned'] = 0x0270; + t['mlsquare'] = 0x3396; + t['mmcubedsquare'] = 0x33A3; + t['mmonospace'] = 0xFF4D; + t['mmsquaredsquare'] = 0x339F; + t['mohiragana'] = 0x3082; + t['mohmsquare'] = 0x33C1; + t['mokatakana'] = 0x30E2; + t['mokatakanahalfwidth'] = 0xFF93; + t['molsquare'] = 0x33D6; + t['momathai'] = 0x0E21; + t['moverssquare'] = 0x33A7; + t['moverssquaredsquare'] = 0x33A8; + t['mparen'] = 0x24A8; + t['mpasquare'] = 0x33AB; + t['mssquare'] = 0x33B3; + t['msuperior'] = 0xF6EF; + t['mturned'] = 0x026F; + t['mu'] = 0x00B5; + t['mu1'] = 0x00B5; + t['muasquare'] = 0x3382; + t['muchgreater'] = 0x226B; + t['muchless'] = 0x226A; + t['mufsquare'] = 0x338C; + t['mugreek'] = 0x03BC; + t['mugsquare'] = 0x338D; + t['muhiragana'] = 0x3080; + t['mukatakana'] = 0x30E0; + t['mukatakanahalfwidth'] = 0xFF91; + t['mulsquare'] = 0x3395; + t['multiply'] = 0x00D7; + t['mumsquare'] = 0x339B; + t['munahhebrew'] = 0x05A3; + t['munahlefthebrew'] = 0x05A3; + t['musicalnote'] = 0x266A; + t['musicalnotedbl'] = 0x266B; + t['musicflatsign'] = 0x266D; + t['musicsharpsign'] = 0x266F; + t['mussquare'] = 0x33B2; + t['muvsquare'] = 0x33B6; + t['muwsquare'] = 0x33BC; + t['mvmegasquare'] = 0x33B9; + t['mvsquare'] = 0x33B7; + t['mwmegasquare'] = 0x33BF; + t['mwsquare'] = 0x33BD; + t['n'] = 0x006E; + t['nabengali'] = 0x09A8; + t['nabla'] = 0x2207; + t['nacute'] = 0x0144; + t['nadeva'] = 0x0928; + t['nagujarati'] = 0x0AA8; + t['nagurmukhi'] = 0x0A28; + t['nahiragana'] = 0x306A; + t['nakatakana'] = 0x30CA; + t['nakatakanahalfwidth'] = 0xFF85; + t['napostrophe'] = 0x0149; + t['nasquare'] = 0x3381; + t['nbopomofo'] = 0x310B; + t['nbspace'] = 0x00A0; + t['ncaron'] = 0x0148; + t['ncedilla'] = 0x0146; + t['ncircle'] = 0x24DD; + t['ncircumflexbelow'] = 0x1E4B; + t['ncommaaccent'] = 0x0146; + t['ndotaccent'] = 0x1E45; + t['ndotbelow'] = 0x1E47; + t['nehiragana'] = 0x306D; + t['nekatakana'] = 0x30CD; + t['nekatakanahalfwidth'] = 0xFF88; + t['newsheqelsign'] = 0x20AA; + t['nfsquare'] = 0x338B; + t['ngabengali'] = 0x0999; + t['ngadeva'] = 0x0919; + t['ngagujarati'] = 0x0A99; + t['ngagurmukhi'] = 0x0A19; + t['ngonguthai'] = 0x0E07; + t['nhiragana'] = 0x3093; + t['nhookleft'] = 0x0272; + t['nhookretroflex'] = 0x0273; + t['nieunacirclekorean'] = 0x326F; + t['nieunaparenkorean'] = 0x320F; + t['nieuncieuckorean'] = 0x3135; + t['nieuncirclekorean'] = 0x3261; + t['nieunhieuhkorean'] = 0x3136; + t['nieunkorean'] = 0x3134; + t['nieunpansioskorean'] = 0x3168; + t['nieunparenkorean'] = 0x3201; + t['nieunsioskorean'] = 0x3167; + t['nieuntikeutkorean'] = 0x3166; + t['nihiragana'] = 0x306B; + t['nikatakana'] = 0x30CB; + t['nikatakanahalfwidth'] = 0xFF86; + t['nikhahitleftthai'] = 0xF899; + t['nikhahitthai'] = 0x0E4D; + t['nine'] = 0x0039; + t['ninearabic'] = 0x0669; + t['ninebengali'] = 0x09EF; + t['ninecircle'] = 0x2468; + t['ninecircleinversesansserif'] = 0x2792; + t['ninedeva'] = 0x096F; + t['ninegujarati'] = 0x0AEF; + t['ninegurmukhi'] = 0x0A6F; + t['ninehackarabic'] = 0x0669; + t['ninehangzhou'] = 0x3029; + t['nineideographicparen'] = 0x3228; + t['nineinferior'] = 0x2089; + t['ninemonospace'] = 0xFF19; + t['nineoldstyle'] = 0xF739; + t['nineparen'] = 0x247C; + t['nineperiod'] = 0x2490; + t['ninepersian'] = 0x06F9; + t['nineroman'] = 0x2178; + t['ninesuperior'] = 0x2079; + t['nineteencircle'] = 0x2472; + t['nineteenparen'] = 0x2486; + t['nineteenperiod'] = 0x249A; + t['ninethai'] = 0x0E59; + t['nj'] = 0x01CC; + t['njecyrillic'] = 0x045A; + t['nkatakana'] = 0x30F3; + t['nkatakanahalfwidth'] = 0xFF9D; + t['nlegrightlong'] = 0x019E; + t['nlinebelow'] = 0x1E49; + t['nmonospace'] = 0xFF4E; + t['nmsquare'] = 0x339A; + t['nnabengali'] = 0x09A3; + t['nnadeva'] = 0x0923; + t['nnagujarati'] = 0x0AA3; + t['nnagurmukhi'] = 0x0A23; + t['nnnadeva'] = 0x0929; + t['nohiragana'] = 0x306E; + t['nokatakana'] = 0x30CE; + t['nokatakanahalfwidth'] = 0xFF89; + t['nonbreakingspace'] = 0x00A0; + t['nonenthai'] = 0x0E13; + t['nonuthai'] = 0x0E19; + t['noonarabic'] = 0x0646; + t['noonfinalarabic'] = 0xFEE6; + t['noonghunnaarabic'] = 0x06BA; + t['noonghunnafinalarabic'] = 0xFB9F; + t['nooninitialarabic'] = 0xFEE7; + t['noonjeeminitialarabic'] = 0xFCD2; + t['noonjeemisolatedarabic'] = 0xFC4B; + t['noonmedialarabic'] = 0xFEE8; + t['noonmeeminitialarabic'] = 0xFCD5; + t['noonmeemisolatedarabic'] = 0xFC4E; + t['noonnoonfinalarabic'] = 0xFC8D; + t['notcontains'] = 0x220C; + t['notelement'] = 0x2209; + t['notelementof'] = 0x2209; + t['notequal'] = 0x2260; + t['notgreater'] = 0x226F; + t['notgreaternorequal'] = 0x2271; + t['notgreaternorless'] = 0x2279; + t['notidentical'] = 0x2262; + t['notless'] = 0x226E; + t['notlessnorequal'] = 0x2270; + t['notparallel'] = 0x2226; + t['notprecedes'] = 0x2280; + t['notsubset'] = 0x2284; + t['notsucceeds'] = 0x2281; + t['notsuperset'] = 0x2285; + t['nowarmenian'] = 0x0576; + t['nparen'] = 0x24A9; + t['nssquare'] = 0x33B1; + t['nsuperior'] = 0x207F; + t['ntilde'] = 0x00F1; + t['nu'] = 0x03BD; + t['nuhiragana'] = 0x306C; + t['nukatakana'] = 0x30CC; + t['nukatakanahalfwidth'] = 0xFF87; + t['nuktabengali'] = 0x09BC; + t['nuktadeva'] = 0x093C; + t['nuktagujarati'] = 0x0ABC; + t['nuktagurmukhi'] = 0x0A3C; + t['numbersign'] = 0x0023; + t['numbersignmonospace'] = 0xFF03; + t['numbersignsmall'] = 0xFE5F; + t['numeralsigngreek'] = 0x0374; + t['numeralsignlowergreek'] = 0x0375; + t['numero'] = 0x2116; + t['nun'] = 0x05E0; + t['nundagesh'] = 0xFB40; + t['nundageshhebrew'] = 0xFB40; + t['nunhebrew'] = 0x05E0; + t['nvsquare'] = 0x33B5; + t['nwsquare'] = 0x33BB; + t['nyabengali'] = 0x099E; + t['nyadeva'] = 0x091E; + t['nyagujarati'] = 0x0A9E; + t['nyagurmukhi'] = 0x0A1E; + t['o'] = 0x006F; + t['oacute'] = 0x00F3; + t['oangthai'] = 0x0E2D; + t['obarred'] = 0x0275; + t['obarredcyrillic'] = 0x04E9; + t['obarreddieresiscyrillic'] = 0x04EB; + t['obengali'] = 0x0993; + t['obopomofo'] = 0x311B; + t['obreve'] = 0x014F; + t['ocandradeva'] = 0x0911; + t['ocandragujarati'] = 0x0A91; + t['ocandravowelsigndeva'] = 0x0949; + t['ocandravowelsigngujarati'] = 0x0AC9; + t['ocaron'] = 0x01D2; + t['ocircle'] = 0x24DE; + t['ocircumflex'] = 0x00F4; + t['ocircumflexacute'] = 0x1ED1; + t['ocircumflexdotbelow'] = 0x1ED9; + t['ocircumflexgrave'] = 0x1ED3; + t['ocircumflexhookabove'] = 0x1ED5; + t['ocircumflextilde'] = 0x1ED7; + t['ocyrillic'] = 0x043E; + t['odblacute'] = 0x0151; + t['odblgrave'] = 0x020D; + t['odeva'] = 0x0913; + t['odieresis'] = 0x00F6; + t['odieresiscyrillic'] = 0x04E7; + t['odotbelow'] = 0x1ECD; + t['oe'] = 0x0153; + t['oekorean'] = 0x315A; + t['ogonek'] = 0x02DB; + t['ogonekcmb'] = 0x0328; + t['ograve'] = 0x00F2; + t['ogujarati'] = 0x0A93; + t['oharmenian'] = 0x0585; + t['ohiragana'] = 0x304A; + t['ohookabove'] = 0x1ECF; + t['ohorn'] = 0x01A1; + t['ohornacute'] = 0x1EDB; + t['ohorndotbelow'] = 0x1EE3; + t['ohorngrave'] = 0x1EDD; + t['ohornhookabove'] = 0x1EDF; + t['ohorntilde'] = 0x1EE1; + t['ohungarumlaut'] = 0x0151; + t['oi'] = 0x01A3; + t['oinvertedbreve'] = 0x020F; + t['okatakana'] = 0x30AA; + t['okatakanahalfwidth'] = 0xFF75; + t['okorean'] = 0x3157; + t['olehebrew'] = 0x05AB; + t['omacron'] = 0x014D; + t['omacronacute'] = 0x1E53; + t['omacrongrave'] = 0x1E51; + t['omdeva'] = 0x0950; + t['omega'] = 0x03C9; + t['omega1'] = 0x03D6; + t['omegacyrillic'] = 0x0461; + t['omegalatinclosed'] = 0x0277; + t['omegaroundcyrillic'] = 0x047B; + t['omegatitlocyrillic'] = 0x047D; + t['omegatonos'] = 0x03CE; + t['omgujarati'] = 0x0AD0; + t['omicron'] = 0x03BF; + t['omicrontonos'] = 0x03CC; + t['omonospace'] = 0xFF4F; + t['one'] = 0x0031; + t['onearabic'] = 0x0661; + t['onebengali'] = 0x09E7; + t['onecircle'] = 0x2460; + t['onecircleinversesansserif'] = 0x278A; + t['onedeva'] = 0x0967; + t['onedotenleader'] = 0x2024; + t['oneeighth'] = 0x215B; + t['onefitted'] = 0xF6DC; + t['onegujarati'] = 0x0AE7; + t['onegurmukhi'] = 0x0A67; + t['onehackarabic'] = 0x0661; + t['onehalf'] = 0x00BD; + t['onehangzhou'] = 0x3021; + t['oneideographicparen'] = 0x3220; + t['oneinferior'] = 0x2081; + t['onemonospace'] = 0xFF11; + t['onenumeratorbengali'] = 0x09F4; + t['oneoldstyle'] = 0xF731; + t['oneparen'] = 0x2474; + t['oneperiod'] = 0x2488; + t['onepersian'] = 0x06F1; + t['onequarter'] = 0x00BC; + t['oneroman'] = 0x2170; + t['onesuperior'] = 0x00B9; + t['onethai'] = 0x0E51; + t['onethird'] = 0x2153; + t['oogonek'] = 0x01EB; + t['oogonekmacron'] = 0x01ED; + t['oogurmukhi'] = 0x0A13; + t['oomatragurmukhi'] = 0x0A4B; + t['oopen'] = 0x0254; + t['oparen'] = 0x24AA; + t['openbullet'] = 0x25E6; + t['option'] = 0x2325; + t['ordfeminine'] = 0x00AA; + t['ordmasculine'] = 0x00BA; + t['orthogonal'] = 0x221F; + t['oshortdeva'] = 0x0912; + t['oshortvowelsigndeva'] = 0x094A; + t['oslash'] = 0x00F8; + t['oslashacute'] = 0x01FF; + t['osmallhiragana'] = 0x3049; + t['osmallkatakana'] = 0x30A9; + t['osmallkatakanahalfwidth'] = 0xFF6B; + t['ostrokeacute'] = 0x01FF; + t['osuperior'] = 0xF6F0; + t['otcyrillic'] = 0x047F; + t['otilde'] = 0x00F5; + t['otildeacute'] = 0x1E4D; + t['otildedieresis'] = 0x1E4F; + t['oubopomofo'] = 0x3121; + t['overline'] = 0x203E; + t['overlinecenterline'] = 0xFE4A; + t['overlinecmb'] = 0x0305; + t['overlinedashed'] = 0xFE49; + t['overlinedblwavy'] = 0xFE4C; + t['overlinewavy'] = 0xFE4B; + t['overscore'] = 0x00AF; + t['ovowelsignbengali'] = 0x09CB; + t['ovowelsigndeva'] = 0x094B; + t['ovowelsigngujarati'] = 0x0ACB; + t['p'] = 0x0070; + t['paampssquare'] = 0x3380; + t['paasentosquare'] = 0x332B; + t['pabengali'] = 0x09AA; + t['pacute'] = 0x1E55; + t['padeva'] = 0x092A; + t['pagedown'] = 0x21DF; + t['pageup'] = 0x21DE; + t['pagujarati'] = 0x0AAA; + t['pagurmukhi'] = 0x0A2A; + t['pahiragana'] = 0x3071; + t['paiyannoithai'] = 0x0E2F; + t['pakatakana'] = 0x30D1; + t['palatalizationcyrilliccmb'] = 0x0484; + t['palochkacyrillic'] = 0x04C0; + t['pansioskorean'] = 0x317F; + t['paragraph'] = 0x00B6; + t['parallel'] = 0x2225; + t['parenleft'] = 0x0028; + t['parenleftaltonearabic'] = 0xFD3E; + t['parenleftbt'] = 0xF8ED; + t['parenleftex'] = 0xF8EC; + t['parenleftinferior'] = 0x208D; + t['parenleftmonospace'] = 0xFF08; + t['parenleftsmall'] = 0xFE59; + t['parenleftsuperior'] = 0x207D; + t['parenlefttp'] = 0xF8EB; + t['parenleftvertical'] = 0xFE35; + t['parenright'] = 0x0029; + t['parenrightaltonearabic'] = 0xFD3F; + t['parenrightbt'] = 0xF8F8; + t['parenrightex'] = 0xF8F7; + t['parenrightinferior'] = 0x208E; + t['parenrightmonospace'] = 0xFF09; + t['parenrightsmall'] = 0xFE5A; + t['parenrightsuperior'] = 0x207E; + t['parenrighttp'] = 0xF8F6; + t['parenrightvertical'] = 0xFE36; + t['partialdiff'] = 0x2202; + t['paseqhebrew'] = 0x05C0; + t['pashtahebrew'] = 0x0599; + t['pasquare'] = 0x33A9; + t['patah'] = 0x05B7; + t['patah11'] = 0x05B7; + t['patah1d'] = 0x05B7; + t['patah2a'] = 0x05B7; + t['patahhebrew'] = 0x05B7; + t['patahnarrowhebrew'] = 0x05B7; + t['patahquarterhebrew'] = 0x05B7; + t['patahwidehebrew'] = 0x05B7; + t['pazerhebrew'] = 0x05A1; + t['pbopomofo'] = 0x3106; + t['pcircle'] = 0x24DF; + t['pdotaccent'] = 0x1E57; + t['pe'] = 0x05E4; + t['pecyrillic'] = 0x043F; + t['pedagesh'] = 0xFB44; + t['pedageshhebrew'] = 0xFB44; + t['peezisquare'] = 0x333B; + t['pefinaldageshhebrew'] = 0xFB43; + t['peharabic'] = 0x067E; + t['peharmenian'] = 0x057A; + t['pehebrew'] = 0x05E4; + t['pehfinalarabic'] = 0xFB57; + t['pehinitialarabic'] = 0xFB58; + t['pehiragana'] = 0x307A; + t['pehmedialarabic'] = 0xFB59; + t['pekatakana'] = 0x30DA; + t['pemiddlehookcyrillic'] = 0x04A7; + t['perafehebrew'] = 0xFB4E; + t['percent'] = 0x0025; + t['percentarabic'] = 0x066A; + t['percentmonospace'] = 0xFF05; + t['percentsmall'] = 0xFE6A; + t['period'] = 0x002E; + t['periodarmenian'] = 0x0589; + t['periodcentered'] = 0x00B7; + t['periodhalfwidth'] = 0xFF61; + t['periodinferior'] = 0xF6E7; + t['periodmonospace'] = 0xFF0E; + t['periodsmall'] = 0xFE52; + t['periodsuperior'] = 0xF6E8; + t['perispomenigreekcmb'] = 0x0342; + t['perpendicular'] = 0x22A5; + t['perthousand'] = 0x2030; + t['peseta'] = 0x20A7; + t['pfsquare'] = 0x338A; + t['phabengali'] = 0x09AB; + t['phadeva'] = 0x092B; + t['phagujarati'] = 0x0AAB; + t['phagurmukhi'] = 0x0A2B; + t['phi'] = 0x03C6; + t['phi1'] = 0x03D5; + t['phieuphacirclekorean'] = 0x327A; + t['phieuphaparenkorean'] = 0x321A; + t['phieuphcirclekorean'] = 0x326C; + t['phieuphkorean'] = 0x314D; + t['phieuphparenkorean'] = 0x320C; + t['philatin'] = 0x0278; + t['phinthuthai'] = 0x0E3A; + t['phisymbolgreek'] = 0x03D5; + t['phook'] = 0x01A5; + t['phophanthai'] = 0x0E1E; + t['phophungthai'] = 0x0E1C; + t['phosamphaothai'] = 0x0E20; + t['pi'] = 0x03C0; + t['pieupacirclekorean'] = 0x3273; + t['pieupaparenkorean'] = 0x3213; + t['pieupcieuckorean'] = 0x3176; + t['pieupcirclekorean'] = 0x3265; + t['pieupkiyeokkorean'] = 0x3172; + t['pieupkorean'] = 0x3142; + t['pieupparenkorean'] = 0x3205; + t['pieupsioskiyeokkorean'] = 0x3174; + t['pieupsioskorean'] = 0x3144; + t['pieupsiostikeutkorean'] = 0x3175; + t['pieupthieuthkorean'] = 0x3177; + t['pieuptikeutkorean'] = 0x3173; + t['pihiragana'] = 0x3074; + t['pikatakana'] = 0x30D4; + t['pisymbolgreek'] = 0x03D6; + t['piwrarmenian'] = 0x0583; + t['plus'] = 0x002B; + t['plusbelowcmb'] = 0x031F; + t['pluscircle'] = 0x2295; + t['plusminus'] = 0x00B1; + t['plusmod'] = 0x02D6; + t['plusmonospace'] = 0xFF0B; + t['plussmall'] = 0xFE62; + t['plussuperior'] = 0x207A; + t['pmonospace'] = 0xFF50; + t['pmsquare'] = 0x33D8; + t['pohiragana'] = 0x307D; + t['pointingindexdownwhite'] = 0x261F; + t['pointingindexleftwhite'] = 0x261C; + t['pointingindexrightwhite'] = 0x261E; + t['pointingindexupwhite'] = 0x261D; + t['pokatakana'] = 0x30DD; + t['poplathai'] = 0x0E1B; + t['postalmark'] = 0x3012; + t['postalmarkface'] = 0x3020; + t['pparen'] = 0x24AB; + t['precedes'] = 0x227A; + t['prescription'] = 0x211E; + t['primemod'] = 0x02B9; + t['primereversed'] = 0x2035; + t['product'] = 0x220F; + t['projective'] = 0x2305; + t['prolongedkana'] = 0x30FC; + t['propellor'] = 0x2318; + t['propersubset'] = 0x2282; + t['propersuperset'] = 0x2283; + t['proportion'] = 0x2237; + t['proportional'] = 0x221D; + t['psi'] = 0x03C8; + t['psicyrillic'] = 0x0471; + t['psilipneumatacyrilliccmb'] = 0x0486; + t['pssquare'] = 0x33B0; + t['puhiragana'] = 0x3077; + t['pukatakana'] = 0x30D7; + t['pvsquare'] = 0x33B4; + t['pwsquare'] = 0x33BA; + t['q'] = 0x0071; + t['qadeva'] = 0x0958; + t['qadmahebrew'] = 0x05A8; + t['qafarabic'] = 0x0642; + t['qaffinalarabic'] = 0xFED6; + t['qafinitialarabic'] = 0xFED7; + t['qafmedialarabic'] = 0xFED8; + t['qamats'] = 0x05B8; + t['qamats10'] = 0x05B8; + t['qamats1a'] = 0x05B8; + t['qamats1c'] = 0x05B8; + t['qamats27'] = 0x05B8; + t['qamats29'] = 0x05B8; + t['qamats33'] = 0x05B8; + t['qamatsde'] = 0x05B8; + t['qamatshebrew'] = 0x05B8; + t['qamatsnarrowhebrew'] = 0x05B8; + t['qamatsqatanhebrew'] = 0x05B8; + t['qamatsqatannarrowhebrew'] = 0x05B8; + t['qamatsqatanquarterhebrew'] = 0x05B8; + t['qamatsqatanwidehebrew'] = 0x05B8; + t['qamatsquarterhebrew'] = 0x05B8; + t['qamatswidehebrew'] = 0x05B8; + t['qarneyparahebrew'] = 0x059F; + t['qbopomofo'] = 0x3111; + t['qcircle'] = 0x24E0; + t['qhook'] = 0x02A0; + t['qmonospace'] = 0xFF51; + t['qof'] = 0x05E7; + t['qofdagesh'] = 0xFB47; + t['qofdageshhebrew'] = 0xFB47; + t['qofhebrew'] = 0x05E7; + t['qparen'] = 0x24AC; + t['quarternote'] = 0x2669; + t['qubuts'] = 0x05BB; + t['qubuts18'] = 0x05BB; + t['qubuts25'] = 0x05BB; + t['qubuts31'] = 0x05BB; + t['qubutshebrew'] = 0x05BB; + t['qubutsnarrowhebrew'] = 0x05BB; + t['qubutsquarterhebrew'] = 0x05BB; + t['qubutswidehebrew'] = 0x05BB; + t['question'] = 0x003F; + t['questionarabic'] = 0x061F; + t['questionarmenian'] = 0x055E; + t['questiondown'] = 0x00BF; + t['questiondownsmall'] = 0xF7BF; + t['questiongreek'] = 0x037E; + t['questionmonospace'] = 0xFF1F; + t['questionsmall'] = 0xF73F; + t['quotedbl'] = 0x0022; + t['quotedblbase'] = 0x201E; + t['quotedblleft'] = 0x201C; + t['quotedblmonospace'] = 0xFF02; + t['quotedblprime'] = 0x301E; + t['quotedblprimereversed'] = 0x301D; + t['quotedblright'] = 0x201D; + t['quoteleft'] = 0x2018; + t['quoteleftreversed'] = 0x201B; + t['quotereversed'] = 0x201B; + t['quoteright'] = 0x2019; + t['quoterightn'] = 0x0149; + t['quotesinglbase'] = 0x201A; + t['quotesingle'] = 0x0027; + t['quotesinglemonospace'] = 0xFF07; + t['r'] = 0x0072; + t['raarmenian'] = 0x057C; + t['rabengali'] = 0x09B0; + t['racute'] = 0x0155; + t['radeva'] = 0x0930; + t['radical'] = 0x221A; + t['radicalex'] = 0xF8E5; + t['radoverssquare'] = 0x33AE; + t['radoverssquaredsquare'] = 0x33AF; + t['radsquare'] = 0x33AD; + t['rafe'] = 0x05BF; + t['rafehebrew'] = 0x05BF; + t['ragujarati'] = 0x0AB0; + t['ragurmukhi'] = 0x0A30; + t['rahiragana'] = 0x3089; + t['rakatakana'] = 0x30E9; + t['rakatakanahalfwidth'] = 0xFF97; + t['ralowerdiagonalbengali'] = 0x09F1; + t['ramiddlediagonalbengali'] = 0x09F0; + t['ramshorn'] = 0x0264; + t['ratio'] = 0x2236; + t['rbopomofo'] = 0x3116; + t['rcaron'] = 0x0159; + t['rcedilla'] = 0x0157; + t['rcircle'] = 0x24E1; + t['rcommaaccent'] = 0x0157; + t['rdblgrave'] = 0x0211; + t['rdotaccent'] = 0x1E59; + t['rdotbelow'] = 0x1E5B; + t['rdotbelowmacron'] = 0x1E5D; + t['referencemark'] = 0x203B; + t['reflexsubset'] = 0x2286; + t['reflexsuperset'] = 0x2287; + t['registered'] = 0x00AE; + t['registersans'] = 0xF8E8; + t['registerserif'] = 0xF6DA; + t['reharabic'] = 0x0631; + t['reharmenian'] = 0x0580; + t['rehfinalarabic'] = 0xFEAE; + t['rehiragana'] = 0x308C; + t['rekatakana'] = 0x30EC; + t['rekatakanahalfwidth'] = 0xFF9A; + t['resh'] = 0x05E8; + t['reshdageshhebrew'] = 0xFB48; + t['reshhebrew'] = 0x05E8; + t['reversedtilde'] = 0x223D; + t['reviahebrew'] = 0x0597; + t['reviamugrashhebrew'] = 0x0597; + t['revlogicalnot'] = 0x2310; + t['rfishhook'] = 0x027E; + t['rfishhookreversed'] = 0x027F; + t['rhabengali'] = 0x09DD; + t['rhadeva'] = 0x095D; + t['rho'] = 0x03C1; + t['rhook'] = 0x027D; + t['rhookturned'] = 0x027B; + t['rhookturnedsuperior'] = 0x02B5; + t['rhosymbolgreek'] = 0x03F1; + t['rhotichookmod'] = 0x02DE; + t['rieulacirclekorean'] = 0x3271; + t['rieulaparenkorean'] = 0x3211; + t['rieulcirclekorean'] = 0x3263; + t['rieulhieuhkorean'] = 0x3140; + t['rieulkiyeokkorean'] = 0x313A; + t['rieulkiyeoksioskorean'] = 0x3169; + t['rieulkorean'] = 0x3139; + t['rieulmieumkorean'] = 0x313B; + t['rieulpansioskorean'] = 0x316C; + t['rieulparenkorean'] = 0x3203; + t['rieulphieuphkorean'] = 0x313F; + t['rieulpieupkorean'] = 0x313C; + t['rieulpieupsioskorean'] = 0x316B; + t['rieulsioskorean'] = 0x313D; + t['rieulthieuthkorean'] = 0x313E; + t['rieultikeutkorean'] = 0x316A; + t['rieulyeorinhieuhkorean'] = 0x316D; + t['rightangle'] = 0x221F; + t['righttackbelowcmb'] = 0x0319; + t['righttriangle'] = 0x22BF; + t['rihiragana'] = 0x308A; + t['rikatakana'] = 0x30EA; + t['rikatakanahalfwidth'] = 0xFF98; + t['ring'] = 0x02DA; + t['ringbelowcmb'] = 0x0325; + t['ringcmb'] = 0x030A; + t['ringhalfleft'] = 0x02BF; + t['ringhalfleftarmenian'] = 0x0559; + t['ringhalfleftbelowcmb'] = 0x031C; + t['ringhalfleftcentered'] = 0x02D3; + t['ringhalfright'] = 0x02BE; + t['ringhalfrightbelowcmb'] = 0x0339; + t['ringhalfrightcentered'] = 0x02D2; + t['rinvertedbreve'] = 0x0213; + t['rittorusquare'] = 0x3351; + t['rlinebelow'] = 0x1E5F; + t['rlongleg'] = 0x027C; + t['rlonglegturned'] = 0x027A; + t['rmonospace'] = 0xFF52; + t['rohiragana'] = 0x308D; + t['rokatakana'] = 0x30ED; + t['rokatakanahalfwidth'] = 0xFF9B; + t['roruathai'] = 0x0E23; + t['rparen'] = 0x24AD; + t['rrabengali'] = 0x09DC; + t['rradeva'] = 0x0931; + t['rragurmukhi'] = 0x0A5C; + t['rreharabic'] = 0x0691; + t['rrehfinalarabic'] = 0xFB8D; + t['rrvocalicbengali'] = 0x09E0; + t['rrvocalicdeva'] = 0x0960; + t['rrvocalicgujarati'] = 0x0AE0; + t['rrvocalicvowelsignbengali'] = 0x09C4; + t['rrvocalicvowelsigndeva'] = 0x0944; + t['rrvocalicvowelsigngujarati'] = 0x0AC4; + t['rsuperior'] = 0xF6F1; + t['rtblock'] = 0x2590; + t['rturned'] = 0x0279; + t['rturnedsuperior'] = 0x02B4; + t['ruhiragana'] = 0x308B; + t['rukatakana'] = 0x30EB; + t['rukatakanahalfwidth'] = 0xFF99; + t['rupeemarkbengali'] = 0x09F2; + t['rupeesignbengali'] = 0x09F3; + t['rupiah'] = 0xF6DD; + t['ruthai'] = 0x0E24; + t['rvocalicbengali'] = 0x098B; + t['rvocalicdeva'] = 0x090B; + t['rvocalicgujarati'] = 0x0A8B; + t['rvocalicvowelsignbengali'] = 0x09C3; + t['rvocalicvowelsigndeva'] = 0x0943; + t['rvocalicvowelsigngujarati'] = 0x0AC3; + t['s'] = 0x0073; + t['sabengali'] = 0x09B8; + t['sacute'] = 0x015B; + t['sacutedotaccent'] = 0x1E65; + t['sadarabic'] = 0x0635; + t['sadeva'] = 0x0938; + t['sadfinalarabic'] = 0xFEBA; + t['sadinitialarabic'] = 0xFEBB; + t['sadmedialarabic'] = 0xFEBC; + t['sagujarati'] = 0x0AB8; + t['sagurmukhi'] = 0x0A38; + t['sahiragana'] = 0x3055; + t['sakatakana'] = 0x30B5; + t['sakatakanahalfwidth'] = 0xFF7B; + t['sallallahoualayhewasallamarabic'] = 0xFDFA; + t['samekh'] = 0x05E1; + t['samekhdagesh'] = 0xFB41; + t['samekhdageshhebrew'] = 0xFB41; + t['samekhhebrew'] = 0x05E1; + t['saraaathai'] = 0x0E32; + t['saraaethai'] = 0x0E41; + t['saraaimaimalaithai'] = 0x0E44; + t['saraaimaimuanthai'] = 0x0E43; + t['saraamthai'] = 0x0E33; + t['saraathai'] = 0x0E30; + t['saraethai'] = 0x0E40; + t['saraiileftthai'] = 0xF886; + t['saraiithai'] = 0x0E35; + t['saraileftthai'] = 0xF885; + t['saraithai'] = 0x0E34; + t['saraothai'] = 0x0E42; + t['saraueeleftthai'] = 0xF888; + t['saraueethai'] = 0x0E37; + t['saraueleftthai'] = 0xF887; + t['sarauethai'] = 0x0E36; + t['sarauthai'] = 0x0E38; + t['sarauuthai'] = 0x0E39; + t['sbopomofo'] = 0x3119; + t['scaron'] = 0x0161; + t['scarondotaccent'] = 0x1E67; + t['scedilla'] = 0x015F; + t['schwa'] = 0x0259; + t['schwacyrillic'] = 0x04D9; + t['schwadieresiscyrillic'] = 0x04DB; + t['schwahook'] = 0x025A; + t['scircle'] = 0x24E2; + t['scircumflex'] = 0x015D; + t['scommaaccent'] = 0x0219; + t['sdotaccent'] = 0x1E61; + t['sdotbelow'] = 0x1E63; + t['sdotbelowdotaccent'] = 0x1E69; + t['seagullbelowcmb'] = 0x033C; + t['second'] = 0x2033; + t['secondtonechinese'] = 0x02CA; + t['section'] = 0x00A7; + t['seenarabic'] = 0x0633; + t['seenfinalarabic'] = 0xFEB2; + t['seeninitialarabic'] = 0xFEB3; + t['seenmedialarabic'] = 0xFEB4; + t['segol'] = 0x05B6; + t['segol13'] = 0x05B6; + t['segol1f'] = 0x05B6; + t['segol2c'] = 0x05B6; + t['segolhebrew'] = 0x05B6; + t['segolnarrowhebrew'] = 0x05B6; + t['segolquarterhebrew'] = 0x05B6; + t['segoltahebrew'] = 0x0592; + t['segolwidehebrew'] = 0x05B6; + t['seharmenian'] = 0x057D; + t['sehiragana'] = 0x305B; + t['sekatakana'] = 0x30BB; + t['sekatakanahalfwidth'] = 0xFF7E; + t['semicolon'] = 0x003B; + t['semicolonarabic'] = 0x061B; + t['semicolonmonospace'] = 0xFF1B; + t['semicolonsmall'] = 0xFE54; + t['semivoicedmarkkana'] = 0x309C; + t['semivoicedmarkkanahalfwidth'] = 0xFF9F; + t['sentisquare'] = 0x3322; + t['sentosquare'] = 0x3323; + t['seven'] = 0x0037; + t['sevenarabic'] = 0x0667; + t['sevenbengali'] = 0x09ED; + t['sevencircle'] = 0x2466; + t['sevencircleinversesansserif'] = 0x2790; + t['sevendeva'] = 0x096D; + t['seveneighths'] = 0x215E; + t['sevengujarati'] = 0x0AED; + t['sevengurmukhi'] = 0x0A6D; + t['sevenhackarabic'] = 0x0667; + t['sevenhangzhou'] = 0x3027; + t['sevenideographicparen'] = 0x3226; + t['seveninferior'] = 0x2087; + t['sevenmonospace'] = 0xFF17; + t['sevenoldstyle'] = 0xF737; + t['sevenparen'] = 0x247A; + t['sevenperiod'] = 0x248E; + t['sevenpersian'] = 0x06F7; + t['sevenroman'] = 0x2176; + t['sevensuperior'] = 0x2077; + t['seventeencircle'] = 0x2470; + t['seventeenparen'] = 0x2484; + t['seventeenperiod'] = 0x2498; + t['seventhai'] = 0x0E57; + t['sfthyphen'] = 0x00AD; + t['shaarmenian'] = 0x0577; + t['shabengali'] = 0x09B6; + t['shacyrillic'] = 0x0448; + t['shaddaarabic'] = 0x0651; + t['shaddadammaarabic'] = 0xFC61; + t['shaddadammatanarabic'] = 0xFC5E; + t['shaddafathaarabic'] = 0xFC60; + t['shaddakasraarabic'] = 0xFC62; + t['shaddakasratanarabic'] = 0xFC5F; + t['shade'] = 0x2592; + t['shadedark'] = 0x2593; + t['shadelight'] = 0x2591; + t['shademedium'] = 0x2592; + t['shadeva'] = 0x0936; + t['shagujarati'] = 0x0AB6; + t['shagurmukhi'] = 0x0A36; + t['shalshelethebrew'] = 0x0593; + t['shbopomofo'] = 0x3115; + t['shchacyrillic'] = 0x0449; + t['sheenarabic'] = 0x0634; + t['sheenfinalarabic'] = 0xFEB6; + t['sheeninitialarabic'] = 0xFEB7; + t['sheenmedialarabic'] = 0xFEB8; + t['sheicoptic'] = 0x03E3; + t['sheqel'] = 0x20AA; + t['sheqelhebrew'] = 0x20AA; + t['sheva'] = 0x05B0; + t['sheva115'] = 0x05B0; + t['sheva15'] = 0x05B0; + t['sheva22'] = 0x05B0; + t['sheva2e'] = 0x05B0; + t['shevahebrew'] = 0x05B0; + t['shevanarrowhebrew'] = 0x05B0; + t['shevaquarterhebrew'] = 0x05B0; + t['shevawidehebrew'] = 0x05B0; + t['shhacyrillic'] = 0x04BB; + t['shimacoptic'] = 0x03ED; + t['shin'] = 0x05E9; + t['shindagesh'] = 0xFB49; + t['shindageshhebrew'] = 0xFB49; + t['shindageshshindot'] = 0xFB2C; + t['shindageshshindothebrew'] = 0xFB2C; + t['shindageshsindot'] = 0xFB2D; + t['shindageshsindothebrew'] = 0xFB2D; + t['shindothebrew'] = 0x05C1; + t['shinhebrew'] = 0x05E9; + t['shinshindot'] = 0xFB2A; + t['shinshindothebrew'] = 0xFB2A; + t['shinsindot'] = 0xFB2B; + t['shinsindothebrew'] = 0xFB2B; + t['shook'] = 0x0282; + t['sigma'] = 0x03C3; + t['sigma1'] = 0x03C2; + t['sigmafinal'] = 0x03C2; + t['sigmalunatesymbolgreek'] = 0x03F2; + t['sihiragana'] = 0x3057; + t['sikatakana'] = 0x30B7; + t['sikatakanahalfwidth'] = 0xFF7C; + t['siluqhebrew'] = 0x05BD; + t['siluqlefthebrew'] = 0x05BD; + t['similar'] = 0x223C; + t['sindothebrew'] = 0x05C2; + t['siosacirclekorean'] = 0x3274; + t['siosaparenkorean'] = 0x3214; + t['sioscieuckorean'] = 0x317E; + t['sioscirclekorean'] = 0x3266; + t['sioskiyeokkorean'] = 0x317A; + t['sioskorean'] = 0x3145; + t['siosnieunkorean'] = 0x317B; + t['siosparenkorean'] = 0x3206; + t['siospieupkorean'] = 0x317D; + t['siostikeutkorean'] = 0x317C; + t['six'] = 0x0036; + t['sixarabic'] = 0x0666; + t['sixbengali'] = 0x09EC; + t['sixcircle'] = 0x2465; + t['sixcircleinversesansserif'] = 0x278F; + t['sixdeva'] = 0x096C; + t['sixgujarati'] = 0x0AEC; + t['sixgurmukhi'] = 0x0A6C; + t['sixhackarabic'] = 0x0666; + t['sixhangzhou'] = 0x3026; + t['sixideographicparen'] = 0x3225; + t['sixinferior'] = 0x2086; + t['sixmonospace'] = 0xFF16; + t['sixoldstyle'] = 0xF736; + t['sixparen'] = 0x2479; + t['sixperiod'] = 0x248D; + t['sixpersian'] = 0x06F6; + t['sixroman'] = 0x2175; + t['sixsuperior'] = 0x2076; + t['sixteencircle'] = 0x246F; + t['sixteencurrencydenominatorbengali'] = 0x09F9; + t['sixteenparen'] = 0x2483; + t['sixteenperiod'] = 0x2497; + t['sixthai'] = 0x0E56; + t['slash'] = 0x002F; + t['slashmonospace'] = 0xFF0F; + t['slong'] = 0x017F; + t['slongdotaccent'] = 0x1E9B; + t['smileface'] = 0x263A; + t['smonospace'] = 0xFF53; + t['sofpasuqhebrew'] = 0x05C3; + t['softhyphen'] = 0x00AD; + t['softsigncyrillic'] = 0x044C; + t['sohiragana'] = 0x305D; + t['sokatakana'] = 0x30BD; + t['sokatakanahalfwidth'] = 0xFF7F; + t['soliduslongoverlaycmb'] = 0x0338; + t['solidusshortoverlaycmb'] = 0x0337; + t['sorusithai'] = 0x0E29; + t['sosalathai'] = 0x0E28; + t['sosothai'] = 0x0E0B; + t['sosuathai'] = 0x0E2A; + t['space'] = 0x0020; + t['spacehackarabic'] = 0x0020; + t['spade'] = 0x2660; + t['spadesuitblack'] = 0x2660; + t['spadesuitwhite'] = 0x2664; + t['sparen'] = 0x24AE; + t['squarebelowcmb'] = 0x033B; + t['squarecc'] = 0x33C4; + t['squarecm'] = 0x339D; + t['squarediagonalcrosshatchfill'] = 0x25A9; + t['squarehorizontalfill'] = 0x25A4; + t['squarekg'] = 0x338F; + t['squarekm'] = 0x339E; + t['squarekmcapital'] = 0x33CE; + t['squareln'] = 0x33D1; + t['squarelog'] = 0x33D2; + t['squaremg'] = 0x338E; + t['squaremil'] = 0x33D5; + t['squaremm'] = 0x339C; + t['squaremsquared'] = 0x33A1; + t['squareorthogonalcrosshatchfill'] = 0x25A6; + t['squareupperlefttolowerrightfill'] = 0x25A7; + t['squareupperrighttolowerleftfill'] = 0x25A8; + t['squareverticalfill'] = 0x25A5; + t['squarewhitewithsmallblack'] = 0x25A3; + t['srsquare'] = 0x33DB; + t['ssabengali'] = 0x09B7; + t['ssadeva'] = 0x0937; + t['ssagujarati'] = 0x0AB7; + t['ssangcieuckorean'] = 0x3149; + t['ssanghieuhkorean'] = 0x3185; + t['ssangieungkorean'] = 0x3180; + t['ssangkiyeokkorean'] = 0x3132; + t['ssangnieunkorean'] = 0x3165; + t['ssangpieupkorean'] = 0x3143; + t['ssangsioskorean'] = 0x3146; + t['ssangtikeutkorean'] = 0x3138; + t['ssuperior'] = 0xF6F2; + t['sterling'] = 0x00A3; + t['sterlingmonospace'] = 0xFFE1; + t['strokelongoverlaycmb'] = 0x0336; + t['strokeshortoverlaycmb'] = 0x0335; + t['subset'] = 0x2282; + t['subsetnotequal'] = 0x228A; + t['subsetorequal'] = 0x2286; + t['succeeds'] = 0x227B; + t['suchthat'] = 0x220B; + t['suhiragana'] = 0x3059; + t['sukatakana'] = 0x30B9; + t['sukatakanahalfwidth'] = 0xFF7D; + t['sukunarabic'] = 0x0652; + t['summation'] = 0x2211; + t['sun'] = 0x263C; + t['superset'] = 0x2283; + t['supersetnotequal'] = 0x228B; + t['supersetorequal'] = 0x2287; + t['svsquare'] = 0x33DC; + t['syouwaerasquare'] = 0x337C; + t['t'] = 0x0074; + t['tabengali'] = 0x09A4; + t['tackdown'] = 0x22A4; + t['tackleft'] = 0x22A3; + t['tadeva'] = 0x0924; + t['tagujarati'] = 0x0AA4; + t['tagurmukhi'] = 0x0A24; + t['taharabic'] = 0x0637; + t['tahfinalarabic'] = 0xFEC2; + t['tahinitialarabic'] = 0xFEC3; + t['tahiragana'] = 0x305F; + t['tahmedialarabic'] = 0xFEC4; + t['taisyouerasquare'] = 0x337D; + t['takatakana'] = 0x30BF; + t['takatakanahalfwidth'] = 0xFF80; + t['tatweelarabic'] = 0x0640; + t['tau'] = 0x03C4; + t['tav'] = 0x05EA; + t['tavdages'] = 0xFB4A; + t['tavdagesh'] = 0xFB4A; + t['tavdageshhebrew'] = 0xFB4A; + t['tavhebrew'] = 0x05EA; + t['tbar'] = 0x0167; + t['tbopomofo'] = 0x310A; + t['tcaron'] = 0x0165; + t['tccurl'] = 0x02A8; + t['tcedilla'] = 0x0163; + t['tcheharabic'] = 0x0686; + t['tchehfinalarabic'] = 0xFB7B; + t['tchehinitialarabic'] = 0xFB7C; + t['tchehmedialarabic'] = 0xFB7D; + t['tcircle'] = 0x24E3; + t['tcircumflexbelow'] = 0x1E71; + t['tcommaaccent'] = 0x0163; + t['tdieresis'] = 0x1E97; + t['tdotaccent'] = 0x1E6B; + t['tdotbelow'] = 0x1E6D; + t['tecyrillic'] = 0x0442; + t['tedescendercyrillic'] = 0x04AD; + t['teharabic'] = 0x062A; + t['tehfinalarabic'] = 0xFE96; + t['tehhahinitialarabic'] = 0xFCA2; + t['tehhahisolatedarabic'] = 0xFC0C; + t['tehinitialarabic'] = 0xFE97; + t['tehiragana'] = 0x3066; + t['tehjeeminitialarabic'] = 0xFCA1; + t['tehjeemisolatedarabic'] = 0xFC0B; + t['tehmarbutaarabic'] = 0x0629; + t['tehmarbutafinalarabic'] = 0xFE94; + t['tehmedialarabic'] = 0xFE98; + t['tehmeeminitialarabic'] = 0xFCA4; + t['tehmeemisolatedarabic'] = 0xFC0E; + t['tehnoonfinalarabic'] = 0xFC73; + t['tekatakana'] = 0x30C6; + t['tekatakanahalfwidth'] = 0xFF83; + t['telephone'] = 0x2121; + t['telephoneblack'] = 0x260E; + t['telishagedolahebrew'] = 0x05A0; + t['telishaqetanahebrew'] = 0x05A9; + t['tencircle'] = 0x2469; + t['tenideographicparen'] = 0x3229; + t['tenparen'] = 0x247D; + t['tenperiod'] = 0x2491; + t['tenroman'] = 0x2179; + t['tesh'] = 0x02A7; + t['tet'] = 0x05D8; + t['tetdagesh'] = 0xFB38; + t['tetdageshhebrew'] = 0xFB38; + t['tethebrew'] = 0x05D8; + t['tetsecyrillic'] = 0x04B5; + t['tevirhebrew'] = 0x059B; + t['tevirlefthebrew'] = 0x059B; + t['thabengali'] = 0x09A5; + t['thadeva'] = 0x0925; + t['thagujarati'] = 0x0AA5; + t['thagurmukhi'] = 0x0A25; + t['thalarabic'] = 0x0630; + t['thalfinalarabic'] = 0xFEAC; + t['thanthakhatlowleftthai'] = 0xF898; + t['thanthakhatlowrightthai'] = 0xF897; + t['thanthakhatthai'] = 0x0E4C; + t['thanthakhatupperleftthai'] = 0xF896; + t['theharabic'] = 0x062B; + t['thehfinalarabic'] = 0xFE9A; + t['thehinitialarabic'] = 0xFE9B; + t['thehmedialarabic'] = 0xFE9C; + t['thereexists'] = 0x2203; + t['therefore'] = 0x2234; + t['theta'] = 0x03B8; + t['theta1'] = 0x03D1; + t['thetasymbolgreek'] = 0x03D1; + t['thieuthacirclekorean'] = 0x3279; + t['thieuthaparenkorean'] = 0x3219; + t['thieuthcirclekorean'] = 0x326B; + t['thieuthkorean'] = 0x314C; + t['thieuthparenkorean'] = 0x320B; + t['thirteencircle'] = 0x246C; + t['thirteenparen'] = 0x2480; + t['thirteenperiod'] = 0x2494; + t['thonangmonthothai'] = 0x0E11; + t['thook'] = 0x01AD; + t['thophuthaothai'] = 0x0E12; + t['thorn'] = 0x00FE; + t['thothahanthai'] = 0x0E17; + t['thothanthai'] = 0x0E10; + t['thothongthai'] = 0x0E18; + t['thothungthai'] = 0x0E16; + t['thousandcyrillic'] = 0x0482; + t['thousandsseparatorarabic'] = 0x066C; + t['thousandsseparatorpersian'] = 0x066C; + t['three'] = 0x0033; + t['threearabic'] = 0x0663; + t['threebengali'] = 0x09E9; + t['threecircle'] = 0x2462; + t['threecircleinversesansserif'] = 0x278C; + t['threedeva'] = 0x0969; + t['threeeighths'] = 0x215C; + t['threegujarati'] = 0x0AE9; + t['threegurmukhi'] = 0x0A69; + t['threehackarabic'] = 0x0663; + t['threehangzhou'] = 0x3023; + t['threeideographicparen'] = 0x3222; + t['threeinferior'] = 0x2083; + t['threemonospace'] = 0xFF13; + t['threenumeratorbengali'] = 0x09F6; + t['threeoldstyle'] = 0xF733; + t['threeparen'] = 0x2476; + t['threeperiod'] = 0x248A; + t['threepersian'] = 0x06F3; + t['threequarters'] = 0x00BE; + t['threequartersemdash'] = 0xF6DE; + t['threeroman'] = 0x2172; + t['threesuperior'] = 0x00B3; + t['threethai'] = 0x0E53; + t['thzsquare'] = 0x3394; + t['tihiragana'] = 0x3061; + t['tikatakana'] = 0x30C1; + t['tikatakanahalfwidth'] = 0xFF81; + t['tikeutacirclekorean'] = 0x3270; + t['tikeutaparenkorean'] = 0x3210; + t['tikeutcirclekorean'] = 0x3262; + t['tikeutkorean'] = 0x3137; + t['tikeutparenkorean'] = 0x3202; + t['tilde'] = 0x02DC; + t['tildebelowcmb'] = 0x0330; + t['tildecmb'] = 0x0303; + t['tildecomb'] = 0x0303; + t['tildedoublecmb'] = 0x0360; + t['tildeoperator'] = 0x223C; + t['tildeoverlaycmb'] = 0x0334; + t['tildeverticalcmb'] = 0x033E; + t['timescircle'] = 0x2297; + t['tipehahebrew'] = 0x0596; + t['tipehalefthebrew'] = 0x0596; + t['tippigurmukhi'] = 0x0A70; + t['titlocyrilliccmb'] = 0x0483; + t['tiwnarmenian'] = 0x057F; + t['tlinebelow'] = 0x1E6F; + t['tmonospace'] = 0xFF54; + t['toarmenian'] = 0x0569; + t['tohiragana'] = 0x3068; + t['tokatakana'] = 0x30C8; + t['tokatakanahalfwidth'] = 0xFF84; + t['tonebarextrahighmod'] = 0x02E5; + t['tonebarextralowmod'] = 0x02E9; + t['tonebarhighmod'] = 0x02E6; + t['tonebarlowmod'] = 0x02E8; + t['tonebarmidmod'] = 0x02E7; + t['tonefive'] = 0x01BD; + t['tonesix'] = 0x0185; + t['tonetwo'] = 0x01A8; + t['tonos'] = 0x0384; + t['tonsquare'] = 0x3327; + t['topatakthai'] = 0x0E0F; + t['tortoiseshellbracketleft'] = 0x3014; + t['tortoiseshellbracketleftsmall'] = 0xFE5D; + t['tortoiseshellbracketleftvertical'] = 0xFE39; + t['tortoiseshellbracketright'] = 0x3015; + t['tortoiseshellbracketrightsmall'] = 0xFE5E; + t['tortoiseshellbracketrightvertical'] = 0xFE3A; + t['totaothai'] = 0x0E15; + t['tpalatalhook'] = 0x01AB; + t['tparen'] = 0x24AF; + t['trademark'] = 0x2122; + t['trademarksans'] = 0xF8EA; + t['trademarkserif'] = 0xF6DB; + t['tretroflexhook'] = 0x0288; + t['triagdn'] = 0x25BC; + t['triaglf'] = 0x25C4; + t['triagrt'] = 0x25BA; + t['triagup'] = 0x25B2; + t['ts'] = 0x02A6; + t['tsadi'] = 0x05E6; + t['tsadidagesh'] = 0xFB46; + t['tsadidageshhebrew'] = 0xFB46; + t['tsadihebrew'] = 0x05E6; + t['tsecyrillic'] = 0x0446; + t['tsere'] = 0x05B5; + t['tsere12'] = 0x05B5; + t['tsere1e'] = 0x05B5; + t['tsere2b'] = 0x05B5; + t['tserehebrew'] = 0x05B5; + t['tserenarrowhebrew'] = 0x05B5; + t['tserequarterhebrew'] = 0x05B5; + t['tserewidehebrew'] = 0x05B5; + t['tshecyrillic'] = 0x045B; + t['tsuperior'] = 0xF6F3; + t['ttabengali'] = 0x099F; + t['ttadeva'] = 0x091F; + t['ttagujarati'] = 0x0A9F; + t['ttagurmukhi'] = 0x0A1F; + t['tteharabic'] = 0x0679; + t['ttehfinalarabic'] = 0xFB67; + t['ttehinitialarabic'] = 0xFB68; + t['ttehmedialarabic'] = 0xFB69; + t['tthabengali'] = 0x09A0; + t['tthadeva'] = 0x0920; + t['tthagujarati'] = 0x0AA0; + t['tthagurmukhi'] = 0x0A20; + t['tturned'] = 0x0287; + t['tuhiragana'] = 0x3064; + t['tukatakana'] = 0x30C4; + t['tukatakanahalfwidth'] = 0xFF82; + t['tusmallhiragana'] = 0x3063; + t['tusmallkatakana'] = 0x30C3; + t['tusmallkatakanahalfwidth'] = 0xFF6F; + t['twelvecircle'] = 0x246B; + t['twelveparen'] = 0x247F; + t['twelveperiod'] = 0x2493; + t['twelveroman'] = 0x217B; + t['twentycircle'] = 0x2473; + t['twentyhangzhou'] = 0x5344; + t['twentyparen'] = 0x2487; + t['twentyperiod'] = 0x249B; + t['two'] = 0x0032; + t['twoarabic'] = 0x0662; + t['twobengali'] = 0x09E8; + t['twocircle'] = 0x2461; + t['twocircleinversesansserif'] = 0x278B; + t['twodeva'] = 0x0968; + t['twodotenleader'] = 0x2025; + t['twodotleader'] = 0x2025; + t['twodotleadervertical'] = 0xFE30; + t['twogujarati'] = 0x0AE8; + t['twogurmukhi'] = 0x0A68; + t['twohackarabic'] = 0x0662; + t['twohangzhou'] = 0x3022; + t['twoideographicparen'] = 0x3221; + t['twoinferior'] = 0x2082; + t['twomonospace'] = 0xFF12; + t['twonumeratorbengali'] = 0x09F5; + t['twooldstyle'] = 0xF732; + t['twoparen'] = 0x2475; + t['twoperiod'] = 0x2489; + t['twopersian'] = 0x06F2; + t['tworoman'] = 0x2171; + t['twostroke'] = 0x01BB; + t['twosuperior'] = 0x00B2; + t['twothai'] = 0x0E52; + t['twothirds'] = 0x2154; + t['u'] = 0x0075; + t['uacute'] = 0x00FA; + t['ubar'] = 0x0289; + t['ubengali'] = 0x0989; + t['ubopomofo'] = 0x3128; + t['ubreve'] = 0x016D; + t['ucaron'] = 0x01D4; + t['ucircle'] = 0x24E4; + t['ucircumflex'] = 0x00FB; + t['ucircumflexbelow'] = 0x1E77; + t['ucyrillic'] = 0x0443; + t['udattadeva'] = 0x0951; + t['udblacute'] = 0x0171; + t['udblgrave'] = 0x0215; + t['udeva'] = 0x0909; + t['udieresis'] = 0x00FC; + t['udieresisacute'] = 0x01D8; + t['udieresisbelow'] = 0x1E73; + t['udieresiscaron'] = 0x01DA; + t['udieresiscyrillic'] = 0x04F1; + t['udieresisgrave'] = 0x01DC; + t['udieresismacron'] = 0x01D6; + t['udotbelow'] = 0x1EE5; + t['ugrave'] = 0x00F9; + t['ugujarati'] = 0x0A89; + t['ugurmukhi'] = 0x0A09; + t['uhiragana'] = 0x3046; + t['uhookabove'] = 0x1EE7; + t['uhorn'] = 0x01B0; + t['uhornacute'] = 0x1EE9; + t['uhorndotbelow'] = 0x1EF1; + t['uhorngrave'] = 0x1EEB; + t['uhornhookabove'] = 0x1EED; + t['uhorntilde'] = 0x1EEF; + t['uhungarumlaut'] = 0x0171; + t['uhungarumlautcyrillic'] = 0x04F3; + t['uinvertedbreve'] = 0x0217; + t['ukatakana'] = 0x30A6; + t['ukatakanahalfwidth'] = 0xFF73; + t['ukcyrillic'] = 0x0479; + t['ukorean'] = 0x315C; + t['umacron'] = 0x016B; + t['umacroncyrillic'] = 0x04EF; + t['umacrondieresis'] = 0x1E7B; + t['umatragurmukhi'] = 0x0A41; + t['umonospace'] = 0xFF55; + t['underscore'] = 0x005F; + t['underscoredbl'] = 0x2017; + t['underscoremonospace'] = 0xFF3F; + t['underscorevertical'] = 0xFE33; + t['underscorewavy'] = 0xFE4F; + t['union'] = 0x222A; + t['universal'] = 0x2200; + t['uogonek'] = 0x0173; + t['uparen'] = 0x24B0; + t['upblock'] = 0x2580; + t['upperdothebrew'] = 0x05C4; + t['upsilon'] = 0x03C5; + t['upsilondieresis'] = 0x03CB; + t['upsilondieresistonos'] = 0x03B0; + t['upsilonlatin'] = 0x028A; + t['upsilontonos'] = 0x03CD; + t['uptackbelowcmb'] = 0x031D; + t['uptackmod'] = 0x02D4; + t['uragurmukhi'] = 0x0A73; + t['uring'] = 0x016F; + t['ushortcyrillic'] = 0x045E; + t['usmallhiragana'] = 0x3045; + t['usmallkatakana'] = 0x30A5; + t['usmallkatakanahalfwidth'] = 0xFF69; + t['ustraightcyrillic'] = 0x04AF; + t['ustraightstrokecyrillic'] = 0x04B1; + t['utilde'] = 0x0169; + t['utildeacute'] = 0x1E79; + t['utildebelow'] = 0x1E75; + t['uubengali'] = 0x098A; + t['uudeva'] = 0x090A; + t['uugujarati'] = 0x0A8A; + t['uugurmukhi'] = 0x0A0A; + t['uumatragurmukhi'] = 0x0A42; + t['uuvowelsignbengali'] = 0x09C2; + t['uuvowelsigndeva'] = 0x0942; + t['uuvowelsigngujarati'] = 0x0AC2; + t['uvowelsignbengali'] = 0x09C1; + t['uvowelsigndeva'] = 0x0941; + t['uvowelsigngujarati'] = 0x0AC1; + t['v'] = 0x0076; + t['vadeva'] = 0x0935; + t['vagujarati'] = 0x0AB5; + t['vagurmukhi'] = 0x0A35; + t['vakatakana'] = 0x30F7; + t['vav'] = 0x05D5; + t['vavdagesh'] = 0xFB35; + t['vavdagesh65'] = 0xFB35; + t['vavdageshhebrew'] = 0xFB35; + t['vavhebrew'] = 0x05D5; + t['vavholam'] = 0xFB4B; + t['vavholamhebrew'] = 0xFB4B; + t['vavvavhebrew'] = 0x05F0; + t['vavyodhebrew'] = 0x05F1; + t['vcircle'] = 0x24E5; + t['vdotbelow'] = 0x1E7F; + t['vecyrillic'] = 0x0432; + t['veharabic'] = 0x06A4; + t['vehfinalarabic'] = 0xFB6B; + t['vehinitialarabic'] = 0xFB6C; + t['vehmedialarabic'] = 0xFB6D; + t['vekatakana'] = 0x30F9; + t['venus'] = 0x2640; + t['verticalbar'] = 0x007C; + t['verticallineabovecmb'] = 0x030D; + t['verticallinebelowcmb'] = 0x0329; + t['verticallinelowmod'] = 0x02CC; + t['verticallinemod'] = 0x02C8; + t['vewarmenian'] = 0x057E; + t['vhook'] = 0x028B; + t['vikatakana'] = 0x30F8; + t['viramabengali'] = 0x09CD; + t['viramadeva'] = 0x094D; + t['viramagujarati'] = 0x0ACD; + t['visargabengali'] = 0x0983; + t['visargadeva'] = 0x0903; + t['visargagujarati'] = 0x0A83; + t['vmonospace'] = 0xFF56; + t['voarmenian'] = 0x0578; + t['voicediterationhiragana'] = 0x309E; + t['voicediterationkatakana'] = 0x30FE; + t['voicedmarkkana'] = 0x309B; + t['voicedmarkkanahalfwidth'] = 0xFF9E; + t['vokatakana'] = 0x30FA; + t['vparen'] = 0x24B1; + t['vtilde'] = 0x1E7D; + t['vturned'] = 0x028C; + t['vuhiragana'] = 0x3094; + t['vukatakana'] = 0x30F4; + t['w'] = 0x0077; + t['wacute'] = 0x1E83; + t['waekorean'] = 0x3159; + t['wahiragana'] = 0x308F; + t['wakatakana'] = 0x30EF; + t['wakatakanahalfwidth'] = 0xFF9C; + t['wakorean'] = 0x3158; + t['wasmallhiragana'] = 0x308E; + t['wasmallkatakana'] = 0x30EE; + t['wattosquare'] = 0x3357; + t['wavedash'] = 0x301C; + t['wavyunderscorevertical'] = 0xFE34; + t['wawarabic'] = 0x0648; + t['wawfinalarabic'] = 0xFEEE; + t['wawhamzaabovearabic'] = 0x0624; + t['wawhamzaabovefinalarabic'] = 0xFE86; + t['wbsquare'] = 0x33DD; + t['wcircle'] = 0x24E6; + t['wcircumflex'] = 0x0175; + t['wdieresis'] = 0x1E85; + t['wdotaccent'] = 0x1E87; + t['wdotbelow'] = 0x1E89; + t['wehiragana'] = 0x3091; + t['weierstrass'] = 0x2118; + t['wekatakana'] = 0x30F1; + t['wekorean'] = 0x315E; + t['weokorean'] = 0x315D; + t['wgrave'] = 0x1E81; + t['whitebullet'] = 0x25E6; + t['whitecircle'] = 0x25CB; + t['whitecircleinverse'] = 0x25D9; + t['whitecornerbracketleft'] = 0x300E; + t['whitecornerbracketleftvertical'] = 0xFE43; + t['whitecornerbracketright'] = 0x300F; + t['whitecornerbracketrightvertical'] = 0xFE44; + t['whitediamond'] = 0x25C7; + t['whitediamondcontainingblacksmalldiamond'] = 0x25C8; + t['whitedownpointingsmalltriangle'] = 0x25BF; + t['whitedownpointingtriangle'] = 0x25BD; + t['whiteleftpointingsmalltriangle'] = 0x25C3; + t['whiteleftpointingtriangle'] = 0x25C1; + t['whitelenticularbracketleft'] = 0x3016; + t['whitelenticularbracketright'] = 0x3017; + t['whiterightpointingsmalltriangle'] = 0x25B9; + t['whiterightpointingtriangle'] = 0x25B7; + t['whitesmallsquare'] = 0x25AB; + t['whitesmilingface'] = 0x263A; + t['whitesquare'] = 0x25A1; + t['whitestar'] = 0x2606; + t['whitetelephone'] = 0x260F; + t['whitetortoiseshellbracketleft'] = 0x3018; + t['whitetortoiseshellbracketright'] = 0x3019; + t['whiteuppointingsmalltriangle'] = 0x25B5; + t['whiteuppointingtriangle'] = 0x25B3; + t['wihiragana'] = 0x3090; + t['wikatakana'] = 0x30F0; + t['wikorean'] = 0x315F; + t['wmonospace'] = 0xFF57; + t['wohiragana'] = 0x3092; + t['wokatakana'] = 0x30F2; + t['wokatakanahalfwidth'] = 0xFF66; + t['won'] = 0x20A9; + t['wonmonospace'] = 0xFFE6; + t['wowaenthai'] = 0x0E27; + t['wparen'] = 0x24B2; + t['wring'] = 0x1E98; + t['wsuperior'] = 0x02B7; + t['wturned'] = 0x028D; + t['wynn'] = 0x01BF; + t['x'] = 0x0078; + t['xabovecmb'] = 0x033D; + t['xbopomofo'] = 0x3112; + t['xcircle'] = 0x24E7; + t['xdieresis'] = 0x1E8D; + t['xdotaccent'] = 0x1E8B; + t['xeharmenian'] = 0x056D; + t['xi'] = 0x03BE; + t['xmonospace'] = 0xFF58; + t['xparen'] = 0x24B3; + t['xsuperior'] = 0x02E3; + t['y'] = 0x0079; + t['yaadosquare'] = 0x334E; + t['yabengali'] = 0x09AF; + t['yacute'] = 0x00FD; + t['yadeva'] = 0x092F; + t['yaekorean'] = 0x3152; + t['yagujarati'] = 0x0AAF; + t['yagurmukhi'] = 0x0A2F; + t['yahiragana'] = 0x3084; + t['yakatakana'] = 0x30E4; + t['yakatakanahalfwidth'] = 0xFF94; + t['yakorean'] = 0x3151; + t['yamakkanthai'] = 0x0E4E; + t['yasmallhiragana'] = 0x3083; + t['yasmallkatakana'] = 0x30E3; + t['yasmallkatakanahalfwidth'] = 0xFF6C; + t['yatcyrillic'] = 0x0463; + t['ycircle'] = 0x24E8; + t['ycircumflex'] = 0x0177; + t['ydieresis'] = 0x00FF; + t['ydotaccent'] = 0x1E8F; + t['ydotbelow'] = 0x1EF5; + t['yeharabic'] = 0x064A; + t['yehbarreearabic'] = 0x06D2; + t['yehbarreefinalarabic'] = 0xFBAF; + t['yehfinalarabic'] = 0xFEF2; + t['yehhamzaabovearabic'] = 0x0626; + t['yehhamzaabovefinalarabic'] = 0xFE8A; + t['yehhamzaaboveinitialarabic'] = 0xFE8B; + t['yehhamzaabovemedialarabic'] = 0xFE8C; + t['yehinitialarabic'] = 0xFEF3; + t['yehmedialarabic'] = 0xFEF4; + t['yehmeeminitialarabic'] = 0xFCDD; + t['yehmeemisolatedarabic'] = 0xFC58; + t['yehnoonfinalarabic'] = 0xFC94; + t['yehthreedotsbelowarabic'] = 0x06D1; + t['yekorean'] = 0x3156; + t['yen'] = 0x00A5; + t['yenmonospace'] = 0xFFE5; + t['yeokorean'] = 0x3155; + t['yeorinhieuhkorean'] = 0x3186; + t['yerahbenyomohebrew'] = 0x05AA; + t['yerahbenyomolefthebrew'] = 0x05AA; + t['yericyrillic'] = 0x044B; + t['yerudieresiscyrillic'] = 0x04F9; + t['yesieungkorean'] = 0x3181; + t['yesieungpansioskorean'] = 0x3183; + t['yesieungsioskorean'] = 0x3182; + t['yetivhebrew'] = 0x059A; + t['ygrave'] = 0x1EF3; + t['yhook'] = 0x01B4; + t['yhookabove'] = 0x1EF7; + t['yiarmenian'] = 0x0575; + t['yicyrillic'] = 0x0457; + t['yikorean'] = 0x3162; + t['yinyang'] = 0x262F; + t['yiwnarmenian'] = 0x0582; + t['ymonospace'] = 0xFF59; + t['yod'] = 0x05D9; + t['yoddagesh'] = 0xFB39; + t['yoddageshhebrew'] = 0xFB39; + t['yodhebrew'] = 0x05D9; + t['yodyodhebrew'] = 0x05F2; + t['yodyodpatahhebrew'] = 0xFB1F; + t['yohiragana'] = 0x3088; + t['yoikorean'] = 0x3189; + t['yokatakana'] = 0x30E8; + t['yokatakanahalfwidth'] = 0xFF96; + t['yokorean'] = 0x315B; + t['yosmallhiragana'] = 0x3087; + t['yosmallkatakana'] = 0x30E7; + t['yosmallkatakanahalfwidth'] = 0xFF6E; + t['yotgreek'] = 0x03F3; + t['yoyaekorean'] = 0x3188; + t['yoyakorean'] = 0x3187; + t['yoyakthai'] = 0x0E22; + t['yoyingthai'] = 0x0E0D; + t['yparen'] = 0x24B4; + t['ypogegrammeni'] = 0x037A; + t['ypogegrammenigreekcmb'] = 0x0345; + t['yr'] = 0x01A6; + t['yring'] = 0x1E99; + t['ysuperior'] = 0x02B8; + t['ytilde'] = 0x1EF9; + t['yturned'] = 0x028E; + t['yuhiragana'] = 0x3086; + t['yuikorean'] = 0x318C; + t['yukatakana'] = 0x30E6; + t['yukatakanahalfwidth'] = 0xFF95; + t['yukorean'] = 0x3160; + t['yusbigcyrillic'] = 0x046B; + t['yusbigiotifiedcyrillic'] = 0x046D; + t['yuslittlecyrillic'] = 0x0467; + t['yuslittleiotifiedcyrillic'] = 0x0469; + t['yusmallhiragana'] = 0x3085; + t['yusmallkatakana'] = 0x30E5; + t['yusmallkatakanahalfwidth'] = 0xFF6D; + t['yuyekorean'] = 0x318B; + t['yuyeokorean'] = 0x318A; + t['yyabengali'] = 0x09DF; + t['yyadeva'] = 0x095F; + t['z'] = 0x007A; + t['zaarmenian'] = 0x0566; + t['zacute'] = 0x017A; + t['zadeva'] = 0x095B; + t['zagurmukhi'] = 0x0A5B; + t['zaharabic'] = 0x0638; + t['zahfinalarabic'] = 0xFEC6; + t['zahinitialarabic'] = 0xFEC7; + t['zahiragana'] = 0x3056; + t['zahmedialarabic'] = 0xFEC8; + t['zainarabic'] = 0x0632; + t['zainfinalarabic'] = 0xFEB0; + t['zakatakana'] = 0x30B6; + t['zaqefgadolhebrew'] = 0x0595; + t['zaqefqatanhebrew'] = 0x0594; + t['zarqahebrew'] = 0x0598; + t['zayin'] = 0x05D6; + t['zayindagesh'] = 0xFB36; + t['zayindageshhebrew'] = 0xFB36; + t['zayinhebrew'] = 0x05D6; + t['zbopomofo'] = 0x3117; + t['zcaron'] = 0x017E; + t['zcircle'] = 0x24E9; + t['zcircumflex'] = 0x1E91; + t['zcurl'] = 0x0291; + t['zdot'] = 0x017C; + t['zdotaccent'] = 0x017C; + t['zdotbelow'] = 0x1E93; + t['zecyrillic'] = 0x0437; + t['zedescendercyrillic'] = 0x0499; + t['zedieresiscyrillic'] = 0x04DF; + t['zehiragana'] = 0x305C; + t['zekatakana'] = 0x30BC; + t['zero'] = 0x0030; + t['zeroarabic'] = 0x0660; + t['zerobengali'] = 0x09E6; + t['zerodeva'] = 0x0966; + t['zerogujarati'] = 0x0AE6; + t['zerogurmukhi'] = 0x0A66; + t['zerohackarabic'] = 0x0660; + t['zeroinferior'] = 0x2080; + t['zeromonospace'] = 0xFF10; + t['zerooldstyle'] = 0xF730; + t['zeropersian'] = 0x06F0; + t['zerosuperior'] = 0x2070; + t['zerothai'] = 0x0E50; + t['zerowidthjoiner'] = 0xFEFF; + t['zerowidthnonjoiner'] = 0x200C; + t['zerowidthspace'] = 0x200B; + t['zeta'] = 0x03B6; + t['zhbopomofo'] = 0x3113; + t['zhearmenian'] = 0x056A; + t['zhebrevecyrillic'] = 0x04C2; + t['zhecyrillic'] = 0x0436; + t['zhedescendercyrillic'] = 0x0497; + t['zhedieresiscyrillic'] = 0x04DD; + t['zihiragana'] = 0x3058; + t['zikatakana'] = 0x30B8; + t['zinorhebrew'] = 0x05AE; + t['zlinebelow'] = 0x1E95; + t['zmonospace'] = 0xFF5A; + t['zohiragana'] = 0x305E; + t['zokatakana'] = 0x30BE; + t['zparen'] = 0x24B5; + t['zretroflexhook'] = 0x0290; + t['zstroke'] = 0x01B6; + t['zuhiragana'] = 0x305A; + t['zukatakana'] = 0x30BA; + t['.notdef'] = 0x0000; + t['angbracketleftbig'] = 0x2329; + t['angbracketleftBig'] = 0x2329; + t['angbracketleftbigg'] = 0x2329; + t['angbracketleftBigg'] = 0x2329; + t['angbracketrightBig'] = 0x232A; + t['angbracketrightbig'] = 0x232A; + t['angbracketrightBigg'] = 0x232A; + t['angbracketrightbigg'] = 0x232A; + t['arrowhookleft'] = 0x21AA; + t['arrowhookright'] = 0x21A9; + t['arrowlefttophalf'] = 0x21BC; + t['arrowleftbothalf'] = 0x21BD; + t['arrownortheast'] = 0x2197; + t['arrownorthwest'] = 0x2196; + t['arrowrighttophalf'] = 0x21C0; + t['arrowrightbothalf'] = 0x21C1; + t['arrowsoutheast'] = 0x2198; + t['arrowsouthwest'] = 0x2199; + t['backslashbig'] = 0x2216; + t['backslashBig'] = 0x2216; + t['backslashBigg'] = 0x2216; + t['backslashbigg'] = 0x2216; + t['bardbl'] = 0x2016; + t['bracehtipdownleft'] = 0xFE37; + t['bracehtipdownright'] = 0xFE37; + t['bracehtipupleft'] = 0xFE38; + t['bracehtipupright'] = 0xFE38; + t['braceleftBig'] = 0x007B; + t['braceleftbig'] = 0x007B; + t['braceleftbigg'] = 0x007B; + t['braceleftBigg'] = 0x007B; + t['bracerightBig'] = 0x007D; + t['bracerightbig'] = 0x007D; + t['bracerightbigg'] = 0x007D; + t['bracerightBigg'] = 0x007D; + t['bracketleftbig'] = 0x005B; + t['bracketleftBig'] = 0x005B; + t['bracketleftbigg'] = 0x005B; + t['bracketleftBigg'] = 0x005B; + t['bracketrightBig'] = 0x005D; + t['bracketrightbig'] = 0x005D; + t['bracketrightbigg'] = 0x005D; + t['bracketrightBigg'] = 0x005D; + t['ceilingleftbig'] = 0x2308; + t['ceilingleftBig'] = 0x2308; + t['ceilingleftBigg'] = 0x2308; + t['ceilingleftbigg'] = 0x2308; + t['ceilingrightbig'] = 0x2309; + t['ceilingrightBig'] = 0x2309; + t['ceilingrightbigg'] = 0x2309; + t['ceilingrightBigg'] = 0x2309; + t['circledotdisplay'] = 0x2299; + t['circledottext'] = 0x2299; + t['circlemultiplydisplay'] = 0x2297; + t['circlemultiplytext'] = 0x2297; + t['circleplusdisplay'] = 0x2295; + t['circleplustext'] = 0x2295; + t['contintegraldisplay'] = 0x222E; + t['contintegraltext'] = 0x222E; + t['coproductdisplay'] = 0x2210; + t['coproducttext'] = 0x2210; + t['floorleftBig'] = 0x230A; + t['floorleftbig'] = 0x230A; + t['floorleftbigg'] = 0x230A; + t['floorleftBigg'] = 0x230A; + t['floorrightbig'] = 0x230B; + t['floorrightBig'] = 0x230B; + t['floorrightBigg'] = 0x230B; + t['floorrightbigg'] = 0x230B; + t['hatwide'] = 0x0302; + t['hatwider'] = 0x0302; + t['hatwidest'] = 0x0302; + t['intercal'] = 0x1D40; + t['integraldisplay'] = 0x222B; + t['integraltext'] = 0x222B; + t['intersectiondisplay'] = 0x22C2; + t['intersectiontext'] = 0x22C2; + t['logicalanddisplay'] = 0x2227; + t['logicalandtext'] = 0x2227; + t['logicalordisplay'] = 0x2228; + t['logicalortext'] = 0x2228; + t['parenleftBig'] = 0x0028; + t['parenleftbig'] = 0x0028; + t['parenleftBigg'] = 0x0028; + t['parenleftbigg'] = 0x0028; + t['parenrightBig'] = 0x0029; + t['parenrightbig'] = 0x0029; + t['parenrightBigg'] = 0x0029; + t['parenrightbigg'] = 0x0029; + t['prime'] = 0x2032; + t['productdisplay'] = 0x220F; + t['producttext'] = 0x220F; + t['radicalbig'] = 0x221A; + t['radicalBig'] = 0x221A; + t['radicalBigg'] = 0x221A; + t['radicalbigg'] = 0x221A; + t['radicalbt'] = 0x221A; + t['radicaltp'] = 0x221A; + t['radicalvertex'] = 0x221A; + t['slashbig'] = 0x002F; + t['slashBig'] = 0x002F; + t['slashBigg'] = 0x002F; + t['slashbigg'] = 0x002F; + t['summationdisplay'] = 0x2211; + t['summationtext'] = 0x2211; + t['tildewide'] = 0x02DC; + t['tildewider'] = 0x02DC; + t['tildewidest'] = 0x02DC; + t['uniondisplay'] = 0x22C3; + t['unionmultidisplay'] = 0x228E; + t['unionmultitext'] = 0x228E; + t['unionsqdisplay'] = 0x2294; + t['unionsqtext'] = 0x2294; + t['uniontext'] = 0x22C3; + t['vextenddouble'] = 0x2225; + t['vextendsingle'] = 0x2223; +}); +var getDingbatsGlyphsUnicode = getLookupTableFactory(function (t) { + t['space'] = 0x0020; + t['a1'] = 0x2701; + t['a2'] = 0x2702; + t['a202'] = 0x2703; + t['a3'] = 0x2704; + t['a4'] = 0x260E; + t['a5'] = 0x2706; + t['a119'] = 0x2707; + t['a118'] = 0x2708; + t['a117'] = 0x2709; + t['a11'] = 0x261B; + t['a12'] = 0x261E; + t['a13'] = 0x270C; + t['a14'] = 0x270D; + t['a15'] = 0x270E; + t['a16'] = 0x270F; + t['a105'] = 0x2710; + t['a17'] = 0x2711; + t['a18'] = 0x2712; + t['a19'] = 0x2713; + t['a20'] = 0x2714; + t['a21'] = 0x2715; + t['a22'] = 0x2716; + t['a23'] = 0x2717; + t['a24'] = 0x2718; + t['a25'] = 0x2719; + t['a26'] = 0x271A; + t['a27'] = 0x271B; + t['a28'] = 0x271C; + t['a6'] = 0x271D; + t['a7'] = 0x271E; + t['a8'] = 0x271F; + t['a9'] = 0x2720; + t['a10'] = 0x2721; + t['a29'] = 0x2722; + t['a30'] = 0x2723; + t['a31'] = 0x2724; + t['a32'] = 0x2725; + t['a33'] = 0x2726; + t['a34'] = 0x2727; + t['a35'] = 0x2605; + t['a36'] = 0x2729; + t['a37'] = 0x272A; + t['a38'] = 0x272B; + t['a39'] = 0x272C; + t['a40'] = 0x272D; + t['a41'] = 0x272E; + t['a42'] = 0x272F; + t['a43'] = 0x2730; + t['a44'] = 0x2731; + t['a45'] = 0x2732; + t['a46'] = 0x2733; + t['a47'] = 0x2734; + t['a48'] = 0x2735; + t['a49'] = 0x2736; + t['a50'] = 0x2737; + t['a51'] = 0x2738; + t['a52'] = 0x2739; + t['a53'] = 0x273A; + t['a54'] = 0x273B; + t['a55'] = 0x273C; + t['a56'] = 0x273D; + t['a57'] = 0x273E; + t['a58'] = 0x273F; + t['a59'] = 0x2740; + t['a60'] = 0x2741; + t['a61'] = 0x2742; + t['a62'] = 0x2743; + t['a63'] = 0x2744; + t['a64'] = 0x2745; + t['a65'] = 0x2746; + t['a66'] = 0x2747; + t['a67'] = 0x2748; + t['a68'] = 0x2749; + t['a69'] = 0x274A; + t['a70'] = 0x274B; + t['a71'] = 0x25CF; + t['a72'] = 0x274D; + t['a73'] = 0x25A0; + t['a74'] = 0x274F; + t['a203'] = 0x2750; + t['a75'] = 0x2751; + t['a204'] = 0x2752; + t['a76'] = 0x25B2; + t['a77'] = 0x25BC; + t['a78'] = 0x25C6; + t['a79'] = 0x2756; + t['a81'] = 0x25D7; + t['a82'] = 0x2758; + t['a83'] = 0x2759; + t['a84'] = 0x275A; + t['a97'] = 0x275B; + t['a98'] = 0x275C; + t['a99'] = 0x275D; + t['a100'] = 0x275E; + t['a101'] = 0x2761; + t['a102'] = 0x2762; + t['a103'] = 0x2763; + t['a104'] = 0x2764; + t['a106'] = 0x2765; + t['a107'] = 0x2766; + t['a108'] = 0x2767; + t['a112'] = 0x2663; + t['a111'] = 0x2666; + t['a110'] = 0x2665; + t['a109'] = 0x2660; + t['a120'] = 0x2460; + t['a121'] = 0x2461; + t['a122'] = 0x2462; + t['a123'] = 0x2463; + t['a124'] = 0x2464; + t['a125'] = 0x2465; + t['a126'] = 0x2466; + t['a127'] = 0x2467; + t['a128'] = 0x2468; + t['a129'] = 0x2469; + t['a130'] = 0x2776; + t['a131'] = 0x2777; + t['a132'] = 0x2778; + t['a133'] = 0x2779; + t['a134'] = 0x277A; + t['a135'] = 0x277B; + t['a136'] = 0x277C; + t['a137'] = 0x277D; + t['a138'] = 0x277E; + t['a139'] = 0x277F; + t['a140'] = 0x2780; + t['a141'] = 0x2781; + t['a142'] = 0x2782; + t['a143'] = 0x2783; + t['a144'] = 0x2784; + t['a145'] = 0x2785; + t['a146'] = 0x2786; + t['a147'] = 0x2787; + t['a148'] = 0x2788; + t['a149'] = 0x2789; + t['a150'] = 0x278A; + t['a151'] = 0x278B; + t['a152'] = 0x278C; + t['a153'] = 0x278D; + t['a154'] = 0x278E; + t['a155'] = 0x278F; + t['a156'] = 0x2790; + t['a157'] = 0x2791; + t['a158'] = 0x2792; + t['a159'] = 0x2793; + t['a160'] = 0x2794; + t['a161'] = 0x2192; + t['a163'] = 0x2194; + t['a164'] = 0x2195; + t['a196'] = 0x2798; + t['a165'] = 0x2799; + t['a192'] = 0x279A; + t['a166'] = 0x279B; + t['a167'] = 0x279C; + t['a168'] = 0x279D; + t['a169'] = 0x279E; + t['a170'] = 0x279F; + t['a171'] = 0x27A0; + t['a172'] = 0x27A1; + t['a173'] = 0x27A2; + t['a162'] = 0x27A3; + t['a174'] = 0x27A4; + t['a175'] = 0x27A5; + t['a176'] = 0x27A6; + t['a177'] = 0x27A7; + t['a178'] = 0x27A8; + t['a179'] = 0x27A9; + t['a193'] = 0x27AA; + t['a180'] = 0x27AB; + t['a199'] = 0x27AC; + t['a181'] = 0x27AD; + t['a200'] = 0x27AE; + t['a182'] = 0x27AF; + t['a201'] = 0x27B1; + t['a183'] = 0x27B2; + t['a184'] = 0x27B3; + t['a197'] = 0x27B4; + t['a185'] = 0x27B5; + t['a194'] = 0x27B6; + t['a198'] = 0x27B7; + t['a186'] = 0x27B8; + t['a195'] = 0x27B9; + t['a187'] = 0x27BA; + t['a188'] = 0x27BB; + t['a189'] = 0x27BC; + t['a190'] = 0x27BD; + t['a191'] = 0x27BE; + t['a89'] = 0x2768; + t['a90'] = 0x2769; + t['a93'] = 0x276A; + t['a94'] = 0x276B; + t['a91'] = 0x276C; + t['a92'] = 0x276D; + t['a205'] = 0x276E; + t['a85'] = 0x276F; + t['a206'] = 0x2770; + t['a86'] = 0x2771; + t['a87'] = 0x2772; + t['a88'] = 0x2773; + t['a95'] = 0x2774; + t['a96'] = 0x2775; + t['.notdef'] = 0x0000; +}); +exports.getGlyphsUnicode = getGlyphsUnicode; +exports.getDingbatsGlyphsUnicode = getDingbatsGlyphsUnicode; + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var corePdfManager = __w_pdfjs_require__(33); +var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES; +var InvalidPDFException = sharedUtil.InvalidPDFException; +var MessageHandler = sharedUtil.MessageHandler; +var MissingPDFException = sharedUtil.MissingPDFException; +var UnexpectedResponseException = sharedUtil.UnexpectedResponseException; +var PasswordException = sharedUtil.PasswordException; +var UnknownErrorException = sharedUtil.UnknownErrorException; +var XRefParseException = sharedUtil.XRefParseException; +var arrayByteLength = sharedUtil.arrayByteLength; +var arraysToBytes = sharedUtil.arraysToBytes; +var assert = sharedUtil.assert; +var createPromiseCapability = sharedUtil.createPromiseCapability; +var info = sharedUtil.info; +var warn = sharedUtil.warn; +var setVerbosityLevel = sharedUtil.setVerbosityLevel; +var isNodeJS = sharedUtil.isNodeJS; +var Ref = corePrimitives.Ref; +var LocalPdfManager = corePdfManager.LocalPdfManager; +var NetworkPdfManager = corePdfManager.NetworkPdfManager; +var WorkerTask = function WorkerTaskClosure() { + function WorkerTask(name) { + this.name = name; + this.terminated = false; + this._capability = createPromiseCapability(); + } + WorkerTask.prototype = { + get finished() { + return this._capability.promise; + }, + finish: function () { + this._capability.resolve(); + }, + terminate: function () { + this.terminated = true; + }, + ensureNotTerminated: function () { + if (this.terminated) { + throw new Error('Worker task was terminated'); + } + } + }; + return WorkerTask; +}(); +var PDFWorkerStream = function PDFWorkerStreamClosure() { + function PDFWorkerStream(params, msgHandler) { + this._queuedChunks = []; + var initialData = params.initialData; + if (initialData && initialData.length > 0) { + this._queuedChunks.push(initialData); + } + this._msgHandler = msgHandler; + this._isRangeSupported = !params.disableRange; + this._isStreamingSupported = !params.disableStream; + this._contentLength = params.length; + this._fullRequestReader = null; + this._rangeReaders = []; + msgHandler.on('OnDataRange', this._onReceiveData.bind(this)); + msgHandler.on('OnDataProgress', this._onProgress.bind(this)); + } + PDFWorkerStream.prototype = { + _onReceiveData: function PDFWorkerStream_onReceiveData(args) { + if (args.begin === undefined) { + if (this._fullRequestReader) { + this._fullRequestReader._enqueue(args.chunk); + } else { + this._queuedChunks.push(args.chunk); + } + } else { + var found = this._rangeReaders.some(function (rangeReader) { + if (rangeReader._begin !== args.begin) { + return false; + } + rangeReader._enqueue(args.chunk); + return true; + }); + assert(found); + } + }, + _onProgress: function PDFWorkerStream_onProgress(evt) { + if (this._rangeReaders.length > 0) { + var firstReader = this._rangeReaders[0]; + if (firstReader.onProgress) { + firstReader.onProgress({ loaded: evt.loaded }); + } + } + }, + _removeRangeReader: function PDFWorkerStream_removeRangeReader(reader) { + var i = this._rangeReaders.indexOf(reader); + if (i >= 0) { + this._rangeReaders.splice(i, 1); + } + }, + getFullReader: function PDFWorkerStream_getFullReader() { + assert(!this._fullRequestReader); + var queuedChunks = this._queuedChunks; + this._queuedChunks = null; + return new PDFWorkerStreamReader(this, queuedChunks); + }, + getRangeReader: function PDFWorkerStream_getRangeReader(begin, end) { + var reader = new PDFWorkerStreamRangeReader(this, begin, end); + this._msgHandler.send('RequestDataRange', { + begin: begin, + end: end + }); + this._rangeReaders.push(reader); + return reader; + }, + cancelAllRequests: function PDFWorkerStream_cancelAllRequests(reason) { + if (this._fullRequestReader) { + this._fullRequestReader.cancel(reason); + } + var readers = this._rangeReaders.slice(0); + readers.forEach(function (rangeReader) { + rangeReader.cancel(reason); + }); + } + }; + function PDFWorkerStreamReader(stream, queuedChunks) { + this._stream = stream; + this._done = false; + this._queuedChunks = queuedChunks || []; + this._requests = []; + this._headersReady = Promise.resolve(); + stream._fullRequestReader = this; + this.onProgress = null; + } + PDFWorkerStreamReader.prototype = { + _enqueue: function PDFWorkerStreamReader_enqueue(chunk) { + if (this._done) { + return; + } + if (this._requests.length > 0) { + var requestCapability = this._requests.shift(); + requestCapability.resolve({ + value: chunk, + done: false + }); + return; + } + this._queuedChunks.push(chunk); + }, + get headersReady() { + return this._headersReady; + }, + get isRangeSupported() { + return this._stream._isRangeSupported; + }, + get isStreamingSupported() { + return this._stream._isStreamingSupported; + }, + get contentLength() { + return this._stream._contentLength; + }, + read: function PDFWorkerStreamReader_read() { + if (this._queuedChunks.length > 0) { + var chunk = this._queuedChunks.shift(); + return Promise.resolve({ + value: chunk, + done: false + }); + } + if (this._done) { + return Promise.resolve({ + value: undefined, + done: true + }); + } + var requestCapability = createPromiseCapability(); + this._requests.push(requestCapability); + return requestCapability.promise; + }, + cancel: function PDFWorkerStreamReader_cancel(reason) { + this._done = true; + this._requests.forEach(function (requestCapability) { + requestCapability.resolve({ + value: undefined, + done: true + }); + }); + this._requests = []; + } + }; + function PDFWorkerStreamRangeReader(stream, begin, end) { + this._stream = stream; + this._begin = begin; + this._end = end; + this._queuedChunk = null; + this._requests = []; + this._done = false; + this.onProgress = null; + } + PDFWorkerStreamRangeReader.prototype = { + _enqueue: function PDFWorkerStreamRangeReader_enqueue(chunk) { + if (this._done) { + return; + } + if (this._requests.length === 0) { + this._queuedChunk = chunk; + } else { + var requestsCapability = this._requests.shift(); + requestsCapability.resolve({ + value: chunk, + done: false + }); + this._requests.forEach(function (requestCapability) { + requestCapability.resolve({ + value: undefined, + done: true + }); + }); + this._requests = []; + } + this._done = true; + this._stream._removeRangeReader(this); + }, + get isStreamingSupported() { + return false; + }, + read: function PDFWorkerStreamRangeReader_read() { + if (this._queuedChunk) { + return Promise.resolve({ + value: this._queuedChunk, + done: false + }); + } + if (this._done) { + return Promise.resolve({ + value: undefined, + done: true + }); + } + var requestCapability = createPromiseCapability(); + this._requests.push(requestCapability); + return requestCapability.promise; + }, + cancel: function PDFWorkerStreamRangeReader_cancel(reason) { + this._done = true; + this._requests.forEach(function (requestCapability) { + requestCapability.resolve({ + value: undefined, + done: true + }); + }); + this._requests = []; + this._stream._removeRangeReader(this); + } + }; + return PDFWorkerStream; +}(); +var PDFNetworkStream; +function setPDFNetworkStreamClass(cls) { + PDFNetworkStream = cls; +} +var WorkerMessageHandler = { + setup: function wphSetup(handler, port) { + var testMessageProcessed = false; + handler.on('test', function wphSetupTest(data) { + if (testMessageProcessed) { + return; + } + testMessageProcessed = true; + if (!(data instanceof Uint8Array)) { + handler.send('test', 'main', false); + return; + } + var supportTransfers = data[0] === 255; + handler.postMessageTransfers = supportTransfers; + var xhr = new XMLHttpRequest(); + var responseExists = 'response' in xhr; + try { + xhr.responseType; + } catch (e) { + responseExists = false; + } + if (!responseExists) { + handler.send('test', false); + return; + } + handler.send('test', { + supportTypedArray: true, + supportTransfers: supportTransfers + }); + }); + handler.on('configure', function wphConfigure(data) { + setVerbosityLevel(data.verbosity); + }); + handler.on('GetDocRequest', function wphSetupDoc(data) { + return WorkerMessageHandler.createDocumentHandler(data, port); + }); + }, + createDocumentHandler: function wphCreateDocumentHandler(docParams, port) { + var pdfManager; + var terminated = false; + var cancelXHRs = null; + var WorkerTasks = []; + var docId = docParams.docId; + var docBaseUrl = docParams.docBaseUrl; + var workerHandlerName = docParams.docId + '_worker'; + var handler = new MessageHandler(workerHandlerName, docId, port); + handler.postMessageTransfers = docParams.postMessageTransfers; + function ensureNotTerminated() { + if (terminated) { + throw new Error('Worker was terminated'); + } + } + function startWorkerTask(task) { + WorkerTasks.push(task); + } + function finishWorkerTask(task) { + task.finish(); + var i = WorkerTasks.indexOf(task); + WorkerTasks.splice(i, 1); + } + function loadDocument(recoveryMode) { + var loadDocumentCapability = createPromiseCapability(); + var parseSuccess = function parseSuccess() { + var numPagesPromise = pdfManager.ensureDoc('numPages'); + var fingerprintPromise = pdfManager.ensureDoc('fingerprint'); + var encryptedPromise = pdfManager.ensureXRef('encrypt'); + Promise.all([ + numPagesPromise, + fingerprintPromise, + encryptedPromise + ]).then(function onDocReady(results) { + var doc = { + numPages: results[0], + fingerprint: results[1], + encrypted: !!results[2] + }; + loadDocumentCapability.resolve(doc); + }, parseFailure); + }; + var parseFailure = function parseFailure(e) { + loadDocumentCapability.reject(e); + }; + pdfManager.ensureDoc('checkHeader', []).then(function () { + pdfManager.ensureDoc('parseStartXRef', []).then(function () { + pdfManager.ensureDoc('parse', [recoveryMode]).then(parseSuccess, parseFailure); + }, parseFailure); + }, parseFailure); + return loadDocumentCapability.promise; + } + function getPdfManager(data, evaluatorOptions) { + var pdfManagerCapability = createPromiseCapability(); + var pdfManager; + var source = data.source; + if (source.data) { + try { + pdfManager = new LocalPdfManager(docId, source.data, source.password, evaluatorOptions, docBaseUrl); + pdfManagerCapability.resolve(pdfManager); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + return pdfManagerCapability.promise; + } + var pdfStream; + try { + if (source.chunkedViewerLoading) { + pdfStream = new PDFWorkerStream(source, handler); + } else { + assert(PDFNetworkStream, 'pdfjs/core/network module is not loaded'); + pdfStream = new PDFNetworkStream(data); + } + } catch (ex) { + pdfManagerCapability.reject(ex); + return pdfManagerCapability.promise; + } + var fullRequest = pdfStream.getFullReader(); + fullRequest.headersReady.then(function () { + if (!fullRequest.isStreamingSupported || !fullRequest.isRangeSupported) { + fullRequest.onProgress = function (evt) { + handler.send('DocProgress', { + loaded: evt.loaded, + total: evt.total + }); + }; + } + if (!fullRequest.isRangeSupported) { + return; + } + var disableAutoFetch = source.disableAutoFetch || fullRequest.isStreamingSupported; + pdfManager = new NetworkPdfManager(docId, pdfStream, { + msgHandler: handler, + url: source.url, + password: source.password, + length: fullRequest.contentLength, + disableAutoFetch: disableAutoFetch, + rangeChunkSize: source.rangeChunkSize + }, evaluatorOptions, docBaseUrl); + pdfManagerCapability.resolve(pdfManager); + cancelXHRs = null; + }).catch(function (reason) { + pdfManagerCapability.reject(reason); + cancelXHRs = null; + }); + var cachedChunks = [], loaded = 0; + var flushChunks = function () { + var pdfFile = arraysToBytes(cachedChunks); + if (source.length && pdfFile.length !== source.length) { + warn('reported HTTP length is different from actual'); + } + try { + pdfManager = new LocalPdfManager(docId, pdfFile, source.password, evaluatorOptions, docBaseUrl); + pdfManagerCapability.resolve(pdfManager); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + cachedChunks = []; + }; + var readPromise = new Promise(function (resolve, reject) { + var readChunk = function (chunk) { + try { + ensureNotTerminated(); + if (chunk.done) { + if (!pdfManager) { + flushChunks(); + } + cancelXHRs = null; + return; + } + var data = chunk.value; + loaded += arrayByteLength(data); + if (!fullRequest.isStreamingSupported) { + handler.send('DocProgress', { + loaded: loaded, + total: Math.max(loaded, fullRequest.contentLength || 0) + }); + } + if (pdfManager) { + pdfManager.sendProgressiveData(data); + } else { + cachedChunks.push(data); + } + fullRequest.read().then(readChunk, reject); + } catch (e) { + reject(e); + } + }; + fullRequest.read().then(readChunk, reject); + }); + readPromise.catch(function (e) { + pdfManagerCapability.reject(e); + cancelXHRs = null; + }); + cancelXHRs = function () { + pdfStream.cancelAllRequests('abort'); + }; + return pdfManagerCapability.promise; + } + function setupDoc(data) { + function onSuccess(doc) { + ensureNotTerminated(); + handler.send('GetDoc', { pdfInfo: doc }); + } + function onFailure(e) { + if (e instanceof PasswordException) { + var task = new WorkerTask('PasswordException: response ' + e.code); + startWorkerTask(task); + handler.sendWithPromise('PasswordRequest', e).then(function (data) { + finishWorkerTask(task); + pdfManager.updatePassword(data.password); + pdfManagerReady(); + }).catch(function (ex) { + finishWorkerTask(task); + handler.send('PasswordException', ex); + }.bind(null, e)); + } else if (e instanceof InvalidPDFException) { + handler.send('InvalidPDF', e); + } else if (e instanceof MissingPDFException) { + handler.send('MissingPDF', e); + } else if (e instanceof UnexpectedResponseException) { + handler.send('UnexpectedResponse', e); + } else { + handler.send('UnknownError', new UnknownErrorException(e.message, e.toString())); + } + } + function pdfManagerReady() { + ensureNotTerminated(); + loadDocument(false).then(onSuccess, function loadFailure(ex) { + ensureNotTerminated(); + if (!(ex instanceof XRefParseException)) { + onFailure(ex); + return; + } + pdfManager.requestLoadedStream(); + pdfManager.onLoadedStream().then(function () { + ensureNotTerminated(); + loadDocument(true).then(onSuccess, onFailure); + }); + }, onFailure); + } + ensureNotTerminated(); + var evaluatorOptions = { + forceDataSchema: data.disableCreateObjectURL, + maxImageSize: data.maxImageSize === undefined ? -1 : data.maxImageSize, + disableFontFace: data.disableFontFace, + disableNativeImageDecoder: data.disableNativeImageDecoder + }; + getPdfManager(data, evaluatorOptions).then(function (newPdfManager) { + if (terminated) { + newPdfManager.terminate(); + throw new Error('Worker was terminated'); + } + pdfManager = newPdfManager; + handler.send('PDFManagerReady', null); + pdfManager.onLoadedStream().then(function (stream) { + handler.send('DataLoaded', { length: stream.bytes.byteLength }); + }); + }).then(pdfManagerReady, onFailure); + } + handler.on('GetPage', function wphSetupGetPage(data) { + return pdfManager.getPage(data.pageIndex).then(function (page) { + var rotatePromise = pdfManager.ensure(page, 'rotate'); + var refPromise = pdfManager.ensure(page, 'ref'); + var userUnitPromise = pdfManager.ensure(page, 'userUnit'); + var viewPromise = pdfManager.ensure(page, 'view'); + return Promise.all([ + rotatePromise, + refPromise, + userUnitPromise, + viewPromise + ]).then(function (results) { + return { + rotate: results[0], + ref: results[1], + userUnit: results[2], + view: results[3] + }; + }); + }); + }); + handler.on('GetPageIndex', function wphSetupGetPageIndex(data) { + var ref = new Ref(data.ref.num, data.ref.gen); + var catalog = pdfManager.pdfDocument.catalog; + return catalog.getPageIndex(ref); + }); + handler.on('GetDestinations', function wphSetupGetDestinations(data) { + return pdfManager.ensureCatalog('destinations'); + }); + handler.on('GetDestination', function wphSetupGetDestination(data) { + return pdfManager.ensureCatalog('getDestination', [data.id]); + }); + handler.on('GetPageLabels', function wphSetupGetPageLabels(data) { + return pdfManager.ensureCatalog('pageLabels'); + }); + handler.on('GetAttachments', function wphSetupGetAttachments(data) { + return pdfManager.ensureCatalog('attachments'); + }); + handler.on('GetJavaScript', function wphSetupGetJavaScript(data) { + return pdfManager.ensureCatalog('javaScript'); + }); + handler.on('GetOutline', function wphSetupGetOutline(data) { + return pdfManager.ensureCatalog('documentOutline'); + }); + handler.on('GetMetadata', function wphSetupGetMetadata(data) { + return Promise.all([ + pdfManager.ensureDoc('documentInfo'), + pdfManager.ensureCatalog('metadata') + ]); + }); + handler.on('GetData', function wphSetupGetData(data) { + pdfManager.requestLoadedStream(); + return pdfManager.onLoadedStream().then(function (stream) { + return stream.bytes; + }); + }); + handler.on('GetStats', function wphSetupGetStats(data) { + return pdfManager.pdfDocument.xref.stats; + }); + handler.on('GetAnnotations', function wphSetupGetAnnotations(data) { + return pdfManager.getPage(data.pageIndex).then(function (page) { + return pdfManager.ensure(page, 'getAnnotationsData', [data.intent]); + }); + }); + handler.on('RenderPageRequest', function wphSetupRenderPage(data) { + var pageIndex = data.pageIndex; + pdfManager.getPage(pageIndex).then(function (page) { + var task = new WorkerTask('RenderPageRequest: page ' + pageIndex); + startWorkerTask(task); + var pageNum = pageIndex + 1; + var start = Date.now(); + page.getOperatorList(handler, task, data.intent, data.renderInteractiveForms).then(function (operatorList) { + finishWorkerTask(task); + info('page=' + pageNum + ' - getOperatorList: time=' + (Date.now() - start) + 'ms, len=' + operatorList.totalLength); + }, function (e) { + finishWorkerTask(task); + if (task.terminated) { + return; + } + handler.send('UnsupportedFeature', { featureId: UNSUPPORTED_FEATURES.unknown }); + var minimumStackMessage = 'worker.js: while trying to getPage() and getOperatorList()'; + var wrappedException; + if (typeof e === 'string') { + wrappedException = { + message: e, + stack: minimumStackMessage + }; + } else if (typeof e === 'object') { + wrappedException = { + message: e.message || e.toString(), + stack: e.stack || minimumStackMessage + }; + } else { + wrappedException = { + message: 'Unknown exception type: ' + typeof e, + stack: minimumStackMessage + }; + } + handler.send('PageError', { + pageNum: pageNum, + error: wrappedException, + intent: data.intent + }); + }); + }); + }, this); + handler.on('GetTextContent', function wphExtractText(data) { + var pageIndex = data.pageIndex; + var normalizeWhitespace = data.normalizeWhitespace; + var combineTextItems = data.combineTextItems; + return pdfManager.getPage(pageIndex).then(function (page) { + var task = new WorkerTask('GetTextContent: page ' + pageIndex); + startWorkerTask(task); + var pageNum = pageIndex + 1; + var start = Date.now(); + return page.extractTextContent(task, normalizeWhitespace, combineTextItems).then(function (textContent) { + finishWorkerTask(task); + info('text indexing: page=' + pageNum + ' - time=' + (Date.now() - start) + 'ms'); + return textContent; + }, function (reason) { + finishWorkerTask(task); + if (task.terminated) { + return; + } + throw reason; + }); + }); + }); + handler.on('Cleanup', function wphCleanup(data) { + return pdfManager.cleanup(); + }); + handler.on('Terminate', function wphTerminate(data) { + terminated = true; + if (pdfManager) { + pdfManager.terminate(); + pdfManager = null; + } + if (cancelXHRs) { + cancelXHRs(); + } + var waitOn = []; + WorkerTasks.forEach(function (task) { + waitOn.push(task.finished); + task.terminate(); + }); + return Promise.all(waitOn).then(function () { + handler.destroy(); + handler = null; + }); + }); + handler.on('Ready', function wphReady(data) { + setupDoc(docParams); + docParams = null; + }); + return workerHandlerName; + } +}; +function initializeWorker() { + var handler = new MessageHandler('worker', 'main', self); + WorkerMessageHandler.setup(handler, self); + handler.send('ready', null); +} +if (typeof window === 'undefined' && !isNodeJS()) { + initializeWorker(); +} +exports.setPDFNetworkStreamClass = setPDFNetworkStreamClass; +exports.WorkerTask = WorkerTask; +exports.WorkerMessageHandler = WorkerMessageHandler; + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + +var g; +g = function () { + return this; +}(); +try { + g = g || Function("return this")() || (1, eval)("this"); +} catch (e) { + if (typeof window === "object") + g = window; +} +module.exports = g; + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var ArithmeticDecoder = function ArithmeticDecoderClosure() { + var QeTable = [ + { + qe: 0x5601, + nmps: 1, + nlps: 1, + switchFlag: 1 + }, + { + qe: 0x3401, + nmps: 2, + nlps: 6, + switchFlag: 0 + }, + { + qe: 0x1801, + nmps: 3, + nlps: 9, + switchFlag: 0 + }, + { + qe: 0x0AC1, + nmps: 4, + nlps: 12, + switchFlag: 0 + }, + { + qe: 0x0521, + nmps: 5, + nlps: 29, + switchFlag: 0 + }, + { + qe: 0x0221, + nmps: 38, + nlps: 33, + switchFlag: 0 + }, + { + qe: 0x5601, + nmps: 7, + nlps: 6, + switchFlag: 1 + }, + { + qe: 0x5401, + nmps: 8, + nlps: 14, + switchFlag: 0 + }, + { + qe: 0x4801, + nmps: 9, + nlps: 14, + switchFlag: 0 + }, + { + qe: 0x3801, + nmps: 10, + nlps: 14, + switchFlag: 0 + }, + { + qe: 0x3001, + nmps: 11, + nlps: 17, + switchFlag: 0 + }, + { + qe: 0x2401, + nmps: 12, + nlps: 18, + switchFlag: 0 + }, + { + qe: 0x1C01, + nmps: 13, + nlps: 20, + switchFlag: 0 + }, + { + qe: 0x1601, + nmps: 29, + nlps: 21, + switchFlag: 0 + }, + { + qe: 0x5601, + nmps: 15, + nlps: 14, + switchFlag: 1 + }, + { + qe: 0x5401, + nmps: 16, + nlps: 14, + switchFlag: 0 + }, + { + qe: 0x5101, + nmps: 17, + nlps: 15, + switchFlag: 0 + }, + { + qe: 0x4801, + nmps: 18, + nlps: 16, + switchFlag: 0 + }, + { + qe: 0x3801, + nmps: 19, + nlps: 17, + switchFlag: 0 + }, + { + qe: 0x3401, + nmps: 20, + nlps: 18, + switchFlag: 0 + }, + { + qe: 0x3001, + nmps: 21, + nlps: 19, + switchFlag: 0 + }, + { + qe: 0x2801, + nmps: 22, + nlps: 19, + switchFlag: 0 + }, + { + qe: 0x2401, + nmps: 23, + nlps: 20, + switchFlag: 0 + }, + { + qe: 0x2201, + nmps: 24, + nlps: 21, + switchFlag: 0 + }, + { + qe: 0x1C01, + nmps: 25, + nlps: 22, + switchFlag: 0 + }, + { + qe: 0x1801, + nmps: 26, + nlps: 23, + switchFlag: 0 + }, + { + qe: 0x1601, + nmps: 27, + nlps: 24, + switchFlag: 0 + }, + { + qe: 0x1401, + nmps: 28, + nlps: 25, + switchFlag: 0 + }, + { + qe: 0x1201, + nmps: 29, + nlps: 26, + switchFlag: 0 + }, + { + qe: 0x1101, + nmps: 30, + nlps: 27, + switchFlag: 0 + }, + { + qe: 0x0AC1, + nmps: 31, + nlps: 28, + switchFlag: 0 + }, + { + qe: 0x09C1, + nmps: 32, + nlps: 29, + switchFlag: 0 + }, + { + qe: 0x08A1, + nmps: 33, + nlps: 30, + switchFlag: 0 + }, + { + qe: 0x0521, + nmps: 34, + nlps: 31, + switchFlag: 0 + }, + { + qe: 0x0441, + nmps: 35, + nlps: 32, + switchFlag: 0 + }, + { + qe: 0x02A1, + nmps: 36, + nlps: 33, + switchFlag: 0 + }, + { + qe: 0x0221, + nmps: 37, + nlps: 34, + switchFlag: 0 + }, + { + qe: 0x0141, + nmps: 38, + nlps: 35, + switchFlag: 0 + }, + { + qe: 0x0111, + nmps: 39, + nlps: 36, + switchFlag: 0 + }, + { + qe: 0x0085, + nmps: 40, + nlps: 37, + switchFlag: 0 + }, + { + qe: 0x0049, + nmps: 41, + nlps: 38, + switchFlag: 0 + }, + { + qe: 0x0025, + nmps: 42, + nlps: 39, + switchFlag: 0 + }, + { + qe: 0x0015, + nmps: 43, + nlps: 40, + switchFlag: 0 + }, + { + qe: 0x0009, + nmps: 44, + nlps: 41, + switchFlag: 0 + }, + { + qe: 0x0005, + nmps: 45, + nlps: 42, + switchFlag: 0 + }, + { + qe: 0x0001, + nmps: 45, + nlps: 43, + switchFlag: 0 + }, + { + qe: 0x5601, + nmps: 46, + nlps: 46, + switchFlag: 0 + } + ]; + function ArithmeticDecoder(data, start, end) { + this.data = data; + this.bp = start; + this.dataEnd = end; + this.chigh = data[start]; + this.clow = 0; + this.byteIn(); + this.chigh = this.chigh << 7 & 0xFFFF | this.clow >> 9 & 0x7F; + this.clow = this.clow << 7 & 0xFFFF; + this.ct -= 7; + this.a = 0x8000; + } + ArithmeticDecoder.prototype = { + byteIn: function ArithmeticDecoder_byteIn() { + var data = this.data; + var bp = this.bp; + if (data[bp] === 0xFF) { + var b1 = data[bp + 1]; + if (b1 > 0x8F) { + this.clow += 0xFF00; + this.ct = 8; + } else { + bp++; + this.clow += data[bp] << 9; + this.ct = 7; + this.bp = bp; + } + } else { + bp++; + this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xFF00; + this.ct = 8; + this.bp = bp; + } + if (this.clow > 0xFFFF) { + this.chigh += this.clow >> 16; + this.clow &= 0xFFFF; + } + }, + readBit: function ArithmeticDecoder_readBit(contexts, pos) { + var cx_index = contexts[pos] >> 1, cx_mps = contexts[pos] & 1; + var qeTableIcx = QeTable[cx_index]; + var qeIcx = qeTableIcx.qe; + var d; + var a = this.a - qeIcx; + if (this.chigh < qeIcx) { + if (a < qeIcx) { + a = qeIcx; + d = cx_mps; + cx_index = qeTableIcx.nmps; + } else { + a = qeIcx; + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } + } else { + this.chigh -= qeIcx; + if ((a & 0x8000) !== 0) { + this.a = a; + return cx_mps; + } + if (a < qeIcx) { + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } else { + d = cx_mps; + cx_index = qeTableIcx.nmps; + } + } + do { + if (this.ct === 0) { + this.byteIn(); + } + a <<= 1; + this.chigh = this.chigh << 1 & 0xFFFF | this.clow >> 15 & 1; + this.clow = this.clow << 1 & 0xFFFF; + this.ct--; + } while ((a & 0x8000) === 0); + this.a = a; + contexts[pos] = cx_index << 1 | cx_mps; + return d; + } + }; + return ArithmeticDecoder; +}(); +exports.ArithmeticDecoder = ArithmeticDecoder; + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var coreCharsets = __w_pdfjs_require__(22); +var coreEncodings = __w_pdfjs_require__(4); +var error = sharedUtil.error; +var info = sharedUtil.info; +var bytesToString = sharedUtil.bytesToString; +var warn = sharedUtil.warn; +var isArray = sharedUtil.isArray; +var Util = sharedUtil.Util; +var stringToBytes = sharedUtil.stringToBytes; +var assert = sharedUtil.assert; +var ISOAdobeCharset = coreCharsets.ISOAdobeCharset; +var ExpertCharset = coreCharsets.ExpertCharset; +var ExpertSubsetCharset = coreCharsets.ExpertSubsetCharset; +var StandardEncoding = coreEncodings.StandardEncoding; +var ExpertEncoding = coreEncodings.ExpertEncoding; +var MAX_SUBR_NESTING = 10; +var CFFStandardStrings = [ + '.notdef', + 'space', + 'exclam', + 'quotedbl', + 'numbersign', + 'dollar', + 'percent', + 'ampersand', + 'quoteright', + 'parenleft', + 'parenright', + 'asterisk', + 'plus', + 'comma', + 'hyphen', + 'period', + 'slash', + 'zero', + 'one', + 'two', + 'three', + 'four', + 'five', + 'six', + 'seven', + 'eight', + 'nine', + 'colon', + 'semicolon', + 'less', + 'equal', + 'greater', + 'question', + 'at', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + 'bracketleft', + 'backslash', + 'bracketright', + 'asciicircum', + 'underscore', + 'quoteleft', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'braceleft', + 'bar', + 'braceright', + 'asciitilde', + 'exclamdown', + 'cent', + 'sterling', + 'fraction', + 'yen', + 'florin', + 'section', + 'currency', + 'quotesingle', + 'quotedblleft', + 'guillemotleft', + 'guilsinglleft', + 'guilsinglright', + 'fi', + 'fl', + 'endash', + 'dagger', + 'daggerdbl', + 'periodcentered', + 'paragraph', + 'bullet', + 'quotesinglbase', + 'quotedblbase', + 'quotedblright', + 'guillemotright', + 'ellipsis', + 'perthousand', + 'questiondown', + 'grave', + 'acute', + 'circumflex', + 'tilde', + 'macron', + 'breve', + 'dotaccent', + 'dieresis', + 'ring', + 'cedilla', + 'hungarumlaut', + 'ogonek', + 'caron', + 'emdash', + 'AE', + 'ordfeminine', + 'Lslash', + 'Oslash', + 'OE', + 'ordmasculine', + 'ae', + 'dotlessi', + 'lslash', + 'oslash', + 'oe', + 'germandbls', + 'onesuperior', + 'logicalnot', + 'mu', + 'trademark', + 'Eth', + 'onehalf', + 'plusminus', + 'Thorn', + 'onequarter', + 'divide', + 'brokenbar', + 'degree', + 'thorn', + 'threequarters', + 'twosuperior', + 'registered', + 'minus', + 'eth', + 'multiply', + 'threesuperior', + 'copyright', + 'Aacute', + 'Acircumflex', + 'Adieresis', + 'Agrave', + 'Aring', + 'Atilde', + 'Ccedilla', + 'Eacute', + 'Ecircumflex', + 'Edieresis', + 'Egrave', + 'Iacute', + 'Icircumflex', + 'Idieresis', + 'Igrave', + 'Ntilde', + 'Oacute', + 'Ocircumflex', + 'Odieresis', + 'Ograve', + 'Otilde', + 'Scaron', + 'Uacute', + 'Ucircumflex', + 'Udieresis', + 'Ugrave', + 'Yacute', + 'Ydieresis', + 'Zcaron', + 'aacute', + 'acircumflex', + 'adieresis', + 'agrave', + 'aring', + 'atilde', + 'ccedilla', + 'eacute', + 'ecircumflex', + 'edieresis', + 'egrave', + 'iacute', + 'icircumflex', + 'idieresis', + 'igrave', + 'ntilde', + 'oacute', + 'ocircumflex', + 'odieresis', + 'ograve', + 'otilde', + 'scaron', + 'uacute', + 'ucircumflex', + 'udieresis', + 'ugrave', + 'yacute', + 'ydieresis', + 'zcaron', + 'exclamsmall', + 'Hungarumlautsmall', + 'dollaroldstyle', + 'dollarsuperior', + 'ampersandsmall', + 'Acutesmall', + 'parenleftsuperior', + 'parenrightsuperior', + 'twodotenleader', + 'onedotenleader', + 'zerooldstyle', + 'oneoldstyle', + 'twooldstyle', + 'threeoldstyle', + 'fouroldstyle', + 'fiveoldstyle', + 'sixoldstyle', + 'sevenoldstyle', + 'eightoldstyle', + 'nineoldstyle', + 'commasuperior', + 'threequartersemdash', + 'periodsuperior', + 'questionsmall', + 'asuperior', + 'bsuperior', + 'centsuperior', + 'dsuperior', + 'esuperior', + 'isuperior', + 'lsuperior', + 'msuperior', + 'nsuperior', + 'osuperior', + 'rsuperior', + 'ssuperior', + 'tsuperior', + 'ff', + 'ffi', + 'ffl', + 'parenleftinferior', + 'parenrightinferior', + 'Circumflexsmall', + 'hyphensuperior', + 'Gravesmall', + 'Asmall', + 'Bsmall', + 'Csmall', + 'Dsmall', + 'Esmall', + 'Fsmall', + 'Gsmall', + 'Hsmall', + 'Ismall', + 'Jsmall', + 'Ksmall', + 'Lsmall', + 'Msmall', + 'Nsmall', + 'Osmall', + 'Psmall', + 'Qsmall', + 'Rsmall', + 'Ssmall', + 'Tsmall', + 'Usmall', + 'Vsmall', + 'Wsmall', + 'Xsmall', + 'Ysmall', + 'Zsmall', + 'colonmonetary', + 'onefitted', + 'rupiah', + 'Tildesmall', + 'exclamdownsmall', + 'centoldstyle', + 'Lslashsmall', + 'Scaronsmall', + 'Zcaronsmall', + 'Dieresissmall', + 'Brevesmall', + 'Caronsmall', + 'Dotaccentsmall', + 'Macronsmall', + 'figuredash', + 'hypheninferior', + 'Ogoneksmall', + 'Ringsmall', + 'Cedillasmall', + 'questiondownsmall', + 'oneeighth', + 'threeeighths', + 'fiveeighths', + 'seveneighths', + 'onethird', + 'twothirds', + 'zerosuperior', + 'foursuperior', + 'fivesuperior', + 'sixsuperior', + 'sevensuperior', + 'eightsuperior', + 'ninesuperior', + 'zeroinferior', + 'oneinferior', + 'twoinferior', + 'threeinferior', + 'fourinferior', + 'fiveinferior', + 'sixinferior', + 'seveninferior', + 'eightinferior', + 'nineinferior', + 'centinferior', + 'dollarinferior', + 'periodinferior', + 'commainferior', + 'Agravesmall', + 'Aacutesmall', + 'Acircumflexsmall', + 'Atildesmall', + 'Adieresissmall', + 'Aringsmall', + 'AEsmall', + 'Ccedillasmall', + 'Egravesmall', + 'Eacutesmall', + 'Ecircumflexsmall', + 'Edieresissmall', + 'Igravesmall', + 'Iacutesmall', + 'Icircumflexsmall', + 'Idieresissmall', + 'Ethsmall', + 'Ntildesmall', + 'Ogravesmall', + 'Oacutesmall', + 'Ocircumflexsmall', + 'Otildesmall', + 'Odieresissmall', + 'OEsmall', + 'Oslashsmall', + 'Ugravesmall', + 'Uacutesmall', + 'Ucircumflexsmall', + 'Udieresissmall', + 'Yacutesmall', + 'Thornsmall', + 'Ydieresissmall', + '001.000', + '001.001', + '001.002', + '001.003', + 'Black', + 'Bold', + 'Book', + 'Light', + 'Medium', + 'Regular', + 'Roman', + 'Semibold' +]; +var CFFParser = function CFFParserClosure() { + var CharstringValidationData = [ + null, + { + id: 'hstem', + min: 2, + stackClearing: true, + stem: true + }, + null, + { + id: 'vstem', + min: 2, + stackClearing: true, + stem: true + }, + { + id: 'vmoveto', + min: 1, + stackClearing: true + }, + { + id: 'rlineto', + min: 2, + resetStack: true + }, + { + id: 'hlineto', + min: 1, + resetStack: true + }, + { + id: 'vlineto', + min: 1, + resetStack: true + }, + { + id: 'rrcurveto', + min: 6, + resetStack: true + }, + null, + { + id: 'callsubr', + min: 1, + undefStack: true + }, + { + id: 'return', + min: 0, + undefStack: true + }, + null, + null, + { + id: 'endchar', + min: 0, + stackClearing: true + }, + null, + null, + null, + { + id: 'hstemhm', + min: 2, + stackClearing: true, + stem: true + }, + { + id: 'hintmask', + min: 0, + stackClearing: true + }, + { + id: 'cntrmask', + min: 0, + stackClearing: true + }, + { + id: 'rmoveto', + min: 2, + stackClearing: true + }, + { + id: 'hmoveto', + min: 1, + stackClearing: true + }, + { + id: 'vstemhm', + min: 2, + stackClearing: true, + stem: true + }, + { + id: 'rcurveline', + min: 8, + resetStack: true + }, + { + id: 'rlinecurve', + min: 8, + resetStack: true + }, + { + id: 'vvcurveto', + min: 4, + resetStack: true + }, + { + id: 'hhcurveto', + min: 4, + resetStack: true + }, + null, + { + id: 'callgsubr', + min: 1, + undefStack: true + }, + { + id: 'vhcurveto', + min: 4, + resetStack: true + }, + { + id: 'hvcurveto', + min: 4, + resetStack: true + } + ]; + var CharstringValidationData12 = [ + null, + null, + null, + { + id: 'and', + min: 2, + stackDelta: -1 + }, + { + id: 'or', + min: 2, + stackDelta: -1 + }, + { + id: 'not', + min: 1, + stackDelta: 0 + }, + null, + null, + null, + { + id: 'abs', + min: 1, + stackDelta: 0 + }, + { + id: 'add', + min: 2, + stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] + stack[index - 1]; + } + }, + { + id: 'sub', + min: 2, + stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] - stack[index - 1]; + } + }, + { + id: 'div', + min: 2, + stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] / stack[index - 1]; + } + }, + null, + { + id: 'neg', + min: 1, + stackDelta: 0, + stackFn: function stack_div(stack, index) { + stack[index - 1] = -stack[index - 1]; + } + }, + { + id: 'eq', + min: 2, + stackDelta: -1 + }, + null, + null, + { + id: 'drop', + min: 1, + stackDelta: -1 + }, + null, + { + id: 'put', + min: 2, + stackDelta: -2 + }, + { + id: 'get', + min: 1, + stackDelta: 0 + }, + { + id: 'ifelse', + min: 4, + stackDelta: -3 + }, + { + id: 'random', + min: 0, + stackDelta: 1 + }, + { + id: 'mul', + min: 2, + stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] * stack[index - 1]; + } + }, + null, + { + id: 'sqrt', + min: 1, + stackDelta: 0 + }, + { + id: 'dup', + min: 1, + stackDelta: 1 + }, + { + id: 'exch', + min: 2, + stackDelta: 0 + }, + { + id: 'index', + min: 2, + stackDelta: 0 + }, + { + id: 'roll', + min: 3, + stackDelta: -2 + }, + null, + null, + null, + { + id: 'hflex', + min: 7, + resetStack: true + }, + { + id: 'flex', + min: 13, + resetStack: true + }, + { + id: 'hflex1', + min: 9, + resetStack: true + }, + { + id: 'flex1', + min: 11, + resetStack: true + } + ]; + function CFFParser(file, properties, seacAnalysisEnabled) { + this.bytes = file.getBytes(); + this.properties = properties; + this.seacAnalysisEnabled = !!seacAnalysisEnabled; + } + CFFParser.prototype = { + parse: function CFFParser_parse() { + var properties = this.properties; + var cff = new CFF(); + this.cff = cff; + var header = this.parseHeader(); + var nameIndex = this.parseIndex(header.endPos); + var topDictIndex = this.parseIndex(nameIndex.endPos); + var stringIndex = this.parseIndex(topDictIndex.endPos); + var globalSubrIndex = this.parseIndex(stringIndex.endPos); + var topDictParsed = this.parseDict(topDictIndex.obj.get(0)); + var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings); + cff.header = header.obj; + cff.names = this.parseNameIndex(nameIndex.obj); + cff.strings = this.parseStringIndex(stringIndex.obj); + cff.topDict = topDict; + cff.globalSubrIndex = globalSubrIndex.obj; + this.parsePrivateDict(cff.topDict); + cff.isCIDFont = topDict.hasName('ROS'); + var charStringOffset = topDict.getByName('CharStrings'); + var charStringIndex = this.parseIndex(charStringOffset).obj; + var fontMatrix = topDict.getByName('FontMatrix'); + if (fontMatrix) { + properties.fontMatrix = fontMatrix; + } + var fontBBox = topDict.getByName('FontBBox'); + if (fontBBox) { + properties.ascent = Math.max(fontBBox[3], fontBBox[1]); + properties.descent = Math.min(fontBBox[1], fontBBox[3]); + properties.ascentScaled = true; + } + var charset, encoding; + if (cff.isCIDFont) { + var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj; + for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) { + var dictRaw = fdArrayIndex.get(i); + var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings); + this.parsePrivateDict(fontDict); + cff.fdArray.push(fontDict); + } + encoding = null; + charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, true); + cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'), charStringIndex.count); + } else { + charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, false); + encoding = this.parseEncoding(topDict.getByName('Encoding'), properties, cff.strings, charset.charset); + } + cff.charset = charset; + cff.encoding = encoding; + var charStringsAndSeacs = this.parseCharStrings(charStringIndex, topDict.privateDict.subrsIndex, globalSubrIndex.obj, cff.fdSelect, cff.fdArray); + cff.charStrings = charStringsAndSeacs.charStrings; + cff.seacs = charStringsAndSeacs.seacs; + cff.widths = charStringsAndSeacs.widths; + return cff; + }, + parseHeader: function CFFParser_parseHeader() { + var bytes = this.bytes; + var bytesLength = bytes.length; + var offset = 0; + while (offset < bytesLength && bytes[offset] !== 1) { + ++offset; + } + if (offset >= bytesLength) { + error('Invalid CFF header'); + } else if (offset !== 0) { + info('cff data is shifted'); + bytes = bytes.subarray(offset); + this.bytes = bytes; + } + var major = bytes[0]; + var minor = bytes[1]; + var hdrSize = bytes[2]; + var offSize = bytes[3]; + var header = new CFFHeader(major, minor, hdrSize, offSize); + return { + obj: header, + endPos: hdrSize + }; + }, + parseDict: function CFFParser_parseDict(dict) { + var pos = 0; + function parseOperand() { + var value = dict[pos++]; + if (value === 30) { + return parseFloatOperand(); + } else if (value === 28) { + value = dict[pos++]; + value = (value << 24 | dict[pos++] << 16) >> 16; + return value; + } else if (value === 29) { + value = dict[pos++]; + value = value << 8 | dict[pos++]; + value = value << 8 | dict[pos++]; + value = value << 8 | dict[pos++]; + return value; + } else if (value >= 32 && value <= 246) { + return value - 139; + } else if (value >= 247 && value <= 250) { + return (value - 247) * 256 + dict[pos++] + 108; + } else if (value >= 251 && value <= 254) { + return -((value - 251) * 256) - dict[pos++] - 108; + } + warn('CFFParser_parseDict: "' + value + '" is a reserved command.'); + return NaN; + } + function parseFloatOperand() { + var str = ''; + var eof = 15; + var lookup = [ + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '.', + 'E', + 'E-', + null, + '-' + ]; + var length = dict.length; + while (pos < length) { + var b = dict[pos++]; + var b1 = b >> 4; + var b2 = b & 15; + if (b1 === eof) { + break; + } + str += lookup[b1]; + if (b2 === eof) { + break; + } + str += lookup[b2]; + } + return parseFloat(str); + } + var operands = []; + var entries = []; + pos = 0; + var end = dict.length; + while (pos < end) { + var b = dict[pos]; + if (b <= 21) { + if (b === 12) { + b = b << 8 | dict[++pos]; + } + entries.push([ + b, + operands + ]); + operands = []; + ++pos; + } else { + operands.push(parseOperand()); + } + } + return entries; + }, + parseIndex: function CFFParser_parseIndex(pos) { + var cffIndex = new CFFIndex(); + var bytes = this.bytes; + var count = bytes[pos++] << 8 | bytes[pos++]; + var offsets = []; + var end = pos; + var i, ii; + if (count !== 0) { + var offsetSize = bytes[pos++]; + var startPos = pos + (count + 1) * offsetSize - 1; + for (i = 0, ii = count + 1; i < ii; ++i) { + var offset = 0; + for (var j = 0; j < offsetSize; ++j) { + offset <<= 8; + offset += bytes[pos++]; + } + offsets.push(startPos + offset); + } + end = offsets[count]; + } + for (i = 0, ii = offsets.length - 1; i < ii; ++i) { + var offsetStart = offsets[i]; + var offsetEnd = offsets[i + 1]; + cffIndex.add(bytes.subarray(offsetStart, offsetEnd)); + } + return { + obj: cffIndex, + endPos: end + }; + }, + parseNameIndex: function CFFParser_parseNameIndex(index) { + var names = []; + for (var i = 0, ii = index.count; i < ii; ++i) { + var name = index.get(i); + var length = Math.min(name.length, 127); + var data = []; + for (var j = 0; j < length; ++j) { + var c = name[j]; + if (j === 0 && c === 0) { + data[j] = c; + continue; + } + if (c < 33 || c > 126 || c === 91 || c === 93 || c === 40 || c === 41 || c === 123 || c === 125 || c === 60 || c === 62 || c === 47 || c === 37 || c === 35) { + data[j] = 95; + continue; + } + data[j] = c; + } + names.push(bytesToString(data)); + } + return names; + }, + parseStringIndex: function CFFParser_parseStringIndex(index) { + var strings = new CFFStrings(); + for (var i = 0, ii = index.count; i < ii; ++i) { + var data = index.get(i); + strings.add(bytesToString(data)); + } + return strings; + }, + createDict: function CFFParser_createDict(Type, dict, strings) { + var cffDict = new Type(strings); + for (var i = 0, ii = dict.length; i < ii; ++i) { + var pair = dict[i]; + var key = pair[0]; + var value = pair[1]; + cffDict.setByKey(key, value); + } + return cffDict; + }, + parseCharString: function CFFParser_parseCharString(state, data, localSubrIndex, globalSubrIndex) { + if (state.callDepth > MAX_SUBR_NESTING) { + return false; + } + var stackSize = state.stackSize; + var stack = state.stack; + var length = data.length; + for (var j = 0; j < length;) { + var value = data[j++]; + var validationCommand = null; + if (value === 12) { + var q = data[j++]; + if (q === 0) { + data[j - 2] = 139; + data[j - 1] = 22; + stackSize = 0; + } else { + validationCommand = CharstringValidationData12[q]; + } + } else if (value === 28) { + stack[stackSize] = (data[j] << 24 | data[j + 1] << 16) >> 16; + j += 2; + stackSize++; + } else if (value === 14) { + if (stackSize >= 4) { + stackSize -= 4; + if (this.seacAnalysisEnabled) { + state.seac = stack.slice(stackSize, stackSize + 4); + return false; + } + } + validationCommand = CharstringValidationData[value]; + } else if (value >= 32 && value <= 246) { + stack[stackSize] = value - 139; + stackSize++; + } else if (value >= 247 && value <= 254) { + stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108; + j++; + stackSize++; + } else if (value === 255) { + stack[stackSize] = (data[j] << 24 | data[j + 1] << 16 | data[j + 2] << 8 | data[j + 3]) / 65536; + j += 4; + stackSize++; + } else if (value === 19 || value === 20) { + state.hints += stackSize >> 1; + j += state.hints + 7 >> 3; + stackSize %= 2; + validationCommand = CharstringValidationData[value]; + } else if (value === 10 || value === 29) { + var subrsIndex; + if (value === 10) { + subrsIndex = localSubrIndex; + } else { + subrsIndex = globalSubrIndex; + } + if (!subrsIndex) { + validationCommand = CharstringValidationData[value]; + warn('Missing subrsIndex for ' + validationCommand.id); + return false; + } + var bias = 32768; + if (subrsIndex.count < 1240) { + bias = 107; + } else if (subrsIndex.count < 33900) { + bias = 1131; + } + var subrNumber = stack[--stackSize] + bias; + if (subrNumber < 0 || subrNumber >= subrsIndex.count) { + validationCommand = CharstringValidationData[value]; + warn('Out of bounds subrIndex for ' + validationCommand.id); + return false; + } + state.stackSize = stackSize; + state.callDepth++; + var valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex); + if (!valid) { + return false; + } + state.callDepth--; + stackSize = state.stackSize; + continue; + } else if (value === 11) { + state.stackSize = stackSize; + return true; + } else { + validationCommand = CharstringValidationData[value]; + } + if (validationCommand) { + if (validationCommand.stem) { + state.hints += stackSize >> 1; + } + if ('min' in validationCommand) { + if (!state.undefStack && stackSize < validationCommand.min) { + warn('Not enough parameters for ' + validationCommand.id + '; actual: ' + stackSize + ', expected: ' + validationCommand.min); + return false; + } + } + if (state.firstStackClearing && validationCommand.stackClearing) { + state.firstStackClearing = false; + stackSize -= validationCommand.min; + if (stackSize >= 2 && validationCommand.stem) { + stackSize %= 2; + } else if (stackSize > 1) { + warn('Found too many parameters for stack-clearing command'); + } + if (stackSize > 0 && stack[stackSize - 1] >= 0) { + state.width = stack[stackSize - 1]; + } + } + if ('stackDelta' in validationCommand) { + if ('stackFn' in validationCommand) { + validationCommand.stackFn(stack, stackSize); + } + stackSize += validationCommand.stackDelta; + } else if (validationCommand.stackClearing) { + stackSize = 0; + } else if (validationCommand.resetStack) { + stackSize = 0; + state.undefStack = false; + } else if (validationCommand.undefStack) { + stackSize = 0; + state.undefStack = true; + state.firstStackClearing = false; + } + } + } + state.stackSize = stackSize; + return true; + }, + parseCharStrings: function CFFParser_parseCharStrings(charStrings, localSubrIndex, globalSubrIndex, fdSelect, fdArray) { + var seacs = []; + var widths = []; + var count = charStrings.count; + for (var i = 0; i < count; i++) { + var charstring = charStrings.get(i); + var state = { + callDepth: 0, + stackSize: 0, + stack: [], + undefStack: true, + hints: 0, + firstStackClearing: true, + seac: null, + width: null + }; + var valid = true; + var localSubrToUse = null; + if (fdSelect && fdArray.length) { + var fdIndex = fdSelect.getFDIndex(i); + if (fdIndex === -1) { + warn('Glyph index is not in fd select.'); + valid = false; + } + if (fdIndex >= fdArray.length) { + warn('Invalid fd index for glyph index.'); + valid = false; + } + if (valid) { + localSubrToUse = fdArray[fdIndex].privateDict.subrsIndex; + } + } else if (localSubrIndex) { + localSubrToUse = localSubrIndex; + } + if (valid) { + valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex); + } + if (state.width !== null) { + widths[i] = state.width; + } + if (state.seac !== null) { + seacs[i] = state.seac; + } + if (!valid) { + charStrings.set(i, new Uint8Array([14])); + } + } + return { + charStrings: charStrings, + seacs: seacs, + widths: widths + }; + }, + emptyPrivateDictionary: function CFFParser_emptyPrivateDictionary(parentDict) { + var privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings); + parentDict.setByKey(18, [ + 0, + 0 + ]); + parentDict.privateDict = privateDict; + }, + parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) { + if (!parentDict.hasName('Private')) { + this.emptyPrivateDictionary(parentDict); + return; + } + var privateOffset = parentDict.getByName('Private'); + if (!isArray(privateOffset) || privateOffset.length !== 2) { + parentDict.removeByName('Private'); + return; + } + var size = privateOffset[0]; + var offset = privateOffset[1]; + if (size === 0 || offset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + var privateDictEnd = offset + size; + var dictData = this.bytes.subarray(offset, privateDictEnd); + var dict = this.parseDict(dictData); + var privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings); + parentDict.privateDict = privateDict; + if (!privateDict.getByName('Subrs')) { + return; + } + var subrsOffset = privateDict.getByName('Subrs'); + var relativeOffset = offset + subrsOffset; + if (subrsOffset === 0 || relativeOffset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + var subrsIndex = this.parseIndex(relativeOffset); + privateDict.subrsIndex = subrsIndex.obj; + }, + parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) { + if (pos === 0) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, ISOAdobeCharset); + } else if (pos === 1) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, ExpertCharset); + } else if (pos === 2) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, ExpertSubsetCharset); + } + var bytes = this.bytes; + var start = pos; + var format = bytes[pos++]; + var charset = ['.notdef']; + var id, count, i; + length -= 1; + switch (format) { + case 0: + for (i = 0; i < length; i++) { + id = bytes[pos++] << 8 | bytes[pos++]; + charset.push(cid ? id : strings.get(id)); + } + break; + case 1: + while (charset.length <= length) { + id = bytes[pos++] << 8 | bytes[pos++]; + count = bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + case 2: + while (charset.length <= length) { + id = bytes[pos++] << 8 | bytes[pos++]; + count = bytes[pos++] << 8 | bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + default: + error('Unknown charset format'); + } + var end = pos; + var raw = bytes.subarray(start, end); + return new CFFCharset(false, format, charset, raw); + }, + parseEncoding: function CFFParser_parseEncoding(pos, properties, strings, charset) { + var encoding = Object.create(null); + var bytes = this.bytes; + var predefined = false; + var format, i, ii; + var raw = null; + function readSupplement() { + var supplementsCount = bytes[pos++]; + for (i = 0; i < supplementsCount; i++) { + var code = bytes[pos++]; + var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff); + encoding[code] = charset.indexOf(strings.get(sid)); + } + } + if (pos === 0 || pos === 1) { + predefined = true; + format = pos; + var baseEncoding = pos ? ExpertEncoding : StandardEncoding; + for (i = 0, ii = charset.length; i < ii; i++) { + var index = baseEncoding.indexOf(charset[i]); + if (index !== -1) { + encoding[index] = i; + } + } + } else { + var dataStart = pos; + format = bytes[pos++]; + switch (format & 0x7f) { + case 0: + var glyphsCount = bytes[pos++]; + for (i = 1; i <= glyphsCount; i++) { + encoding[bytes[pos++]] = i; + } + break; + case 1: + var rangesCount = bytes[pos++]; + var gid = 1; + for (i = 0; i < rangesCount; i++) { + var start = bytes[pos++]; + var left = bytes[pos++]; + for (var j = start; j <= start + left; j++) { + encoding[j] = gid++; + } + } + break; + default: + error('Unknown encoding format: ' + format + ' in CFF'); + break; + } + var dataEnd = pos; + if (format & 0x80) { + bytes[dataStart] &= 0x7f; + readSupplement(); + } + raw = bytes.subarray(dataStart, dataEnd); + } + format = format & 0x7f; + return new CFFEncoding(predefined, format, encoding, raw); + }, + parseFDSelect: function CFFParser_parseFDSelect(pos, length) { + var start = pos; + var bytes = this.bytes; + var format = bytes[pos++]; + var fdSelect = [], rawBytes; + var i, invalidFirstGID = false; + switch (format) { + case 0: + for (i = 0; i < length; ++i) { + var id = bytes[pos++]; + fdSelect.push(id); + } + rawBytes = bytes.subarray(start, pos); + break; + case 3: + var rangesCount = bytes[pos++] << 8 | bytes[pos++]; + for (i = 0; i < rangesCount; ++i) { + var first = bytes[pos++] << 8 | bytes[pos++]; + if (i === 0 && first !== 0) { + warn('parseFDSelect: The first range must have a first GID of 0' + ' -- trying to recover.'); + invalidFirstGID = true; + first = 0; + } + var fdIndex = bytes[pos++]; + var next = bytes[pos] << 8 | bytes[pos + 1]; + for (var j = first; j < next; ++j) { + fdSelect.push(fdIndex); + } + } + pos += 2; + rawBytes = bytes.subarray(start, pos); + if (invalidFirstGID) { + rawBytes[3] = rawBytes[4] = 0; + } + break; + default: + error('parseFDSelect: Unknown format "' + format + '".'); + break; + } + assert(fdSelect.length === length, 'parseFDSelect: Invalid font data.'); + return new CFFFDSelect(fdSelect, rawBytes); + } + }; + return CFFParser; +}(); +var CFF = function CFFClosure() { + function CFF() { + this.header = null; + this.names = []; + this.topDict = null; + this.strings = new CFFStrings(); + this.globalSubrIndex = null; + this.encoding = null; + this.charset = null; + this.charStrings = null; + this.fdArray = []; + this.fdSelect = null; + this.isCIDFont = false; + } + return CFF; +}(); +var CFFHeader = function CFFHeaderClosure() { + function CFFHeader(major, minor, hdrSize, offSize) { + this.major = major; + this.minor = minor; + this.hdrSize = hdrSize; + this.offSize = offSize; + } + return CFFHeader; +}(); +var CFFStrings = function CFFStringsClosure() { + function CFFStrings() { + this.strings = []; + } + CFFStrings.prototype = { + get: function CFFStrings_get(index) { + if (index >= 0 && index <= 390) { + return CFFStandardStrings[index]; + } + if (index - 391 <= this.strings.length) { + return this.strings[index - 391]; + } + return CFFStandardStrings[0]; + }, + add: function CFFStrings_add(value) { + this.strings.push(value); + }, + get count() { + return this.strings.length; + } + }; + return CFFStrings; +}(); +var CFFIndex = function CFFIndexClosure() { + function CFFIndex() { + this.objects = []; + this.length = 0; + } + CFFIndex.prototype = { + add: function CFFIndex_add(data) { + this.length += data.length; + this.objects.push(data); + }, + set: function CFFIndex_set(index, data) { + this.length += data.length - this.objects[index].length; + this.objects[index] = data; + }, + get: function CFFIndex_get(index) { + return this.objects[index]; + }, + get count() { + return this.objects.length; + } + }; + return CFFIndex; +}(); +var CFFDict = function CFFDictClosure() { + function CFFDict(tables, strings) { + this.keyToNameMap = tables.keyToNameMap; + this.nameToKeyMap = tables.nameToKeyMap; + this.defaults = tables.defaults; + this.types = tables.types; + this.opcodes = tables.opcodes; + this.order = tables.order; + this.strings = strings; + this.values = Object.create(null); + } + CFFDict.prototype = { + setByKey: function CFFDict_setByKey(key, value) { + if (!(key in this.keyToNameMap)) { + return false; + } + var valueLength = value.length; + if (valueLength === 0) { + return true; + } + for (var i = 0; i < valueLength; i++) { + if (isNaN(value[i])) { + warn('Invalid CFFDict value: "' + value + '" for key "' + key + '".'); + return true; + } + } + var type = this.types[key]; + if (type === 'num' || type === 'sid' || type === 'offset') { + value = value[0]; + } + this.values[key] = value; + return true; + }, + setByName: function CFFDict_setByName(name, value) { + if (!(name in this.nameToKeyMap)) { + error('Invalid dictionary name "' + name + '"'); + } + this.values[this.nameToKeyMap[name]] = value; + }, + hasName: function CFFDict_hasName(name) { + return this.nameToKeyMap[name] in this.values; + }, + getByName: function CFFDict_getByName(name) { + if (!(name in this.nameToKeyMap)) { + error('Invalid dictionary name "' + name + '"'); + } + var key = this.nameToKeyMap[name]; + if (!(key in this.values)) { + return this.defaults[key]; + } + return this.values[key]; + }, + removeByName: function CFFDict_removeByName(name) { + delete this.values[this.nameToKeyMap[name]]; + } + }; + CFFDict.createTables = function CFFDict_createTables(layout) { + var tables = { + keyToNameMap: {}, + nameToKeyMap: {}, + defaults: {}, + types: {}, + opcodes: {}, + order: [] + }; + for (var i = 0, ii = layout.length; i < ii; ++i) { + var entry = layout[i]; + var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0]; + tables.keyToNameMap[key] = entry[1]; + tables.nameToKeyMap[entry[1]] = key; + tables.types[key] = entry[2]; + tables.defaults[key] = entry[3]; + tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]]; + tables.order.push(key); + } + return tables; + }; + return CFFDict; +}(); +var CFFTopDict = function CFFTopDictClosure() { + var layout = [ + [ + [ + 12, + 30 + ], + 'ROS', + [ + 'sid', + 'sid', + 'num' + ], + null + ], + [ + [ + 12, + 20 + ], + 'SyntheticBase', + 'num', + null + ], + [ + 0, + 'version', + 'sid', + null + ], + [ + 1, + 'Notice', + 'sid', + null + ], + [ + [ + 12, + 0 + ], + 'Copyright', + 'sid', + null + ], + [ + 2, + 'FullName', + 'sid', + null + ], + [ + 3, + 'FamilyName', + 'sid', + null + ], + [ + 4, + 'Weight', + 'sid', + null + ], + [ + [ + 12, + 1 + ], + 'isFixedPitch', + 'num', + 0 + ], + [ + [ + 12, + 2 + ], + 'ItalicAngle', + 'num', + 0 + ], + [ + [ + 12, + 3 + ], + 'UnderlinePosition', + 'num', + -100 + ], + [ + [ + 12, + 4 + ], + 'UnderlineThickness', + 'num', + 50 + ], + [ + [ + 12, + 5 + ], + 'PaintType', + 'num', + 0 + ], + [ + [ + 12, + 6 + ], + 'CharstringType', + 'num', + 2 + ], + [ + [ + 12, + 7 + ], + 'FontMatrix', + [ + 'num', + 'num', + 'num', + 'num', + 'num', + 'num' + ], + [ + 0.001, + 0, + 0, + 0.001, + 0, + 0 + ] + ], + [ + 13, + 'UniqueID', + 'num', + null + ], + [ + 5, + 'FontBBox', + [ + 'num', + 'num', + 'num', + 'num' + ], + [ + 0, + 0, + 0, + 0 + ] + ], + [ + [ + 12, + 8 + ], + 'StrokeWidth', + 'num', + 0 + ], + [ + 14, + 'XUID', + 'array', + null + ], + [ + 15, + 'charset', + 'offset', + 0 + ], + [ + 16, + 'Encoding', + 'offset', + 0 + ], + [ + 17, + 'CharStrings', + 'offset', + 0 + ], + [ + 18, + 'Private', + [ + 'offset', + 'offset' + ], + null + ], + [ + [ + 12, + 21 + ], + 'PostScript', + 'sid', + null + ], + [ + [ + 12, + 22 + ], + 'BaseFontName', + 'sid', + null + ], + [ + [ + 12, + 23 + ], + 'BaseFontBlend', + 'delta', + null + ], + [ + [ + 12, + 31 + ], + 'CIDFontVersion', + 'num', + 0 + ], + [ + [ + 12, + 32 + ], + 'CIDFontRevision', + 'num', + 0 + ], + [ + [ + 12, + 33 + ], + 'CIDFontType', + 'num', + 0 + ], + [ + [ + 12, + 34 + ], + 'CIDCount', + 'num', + 8720 + ], + [ + [ + 12, + 35 + ], + 'UIDBase', + 'num', + null + ], + [ + [ + 12, + 37 + ], + 'FDSelect', + 'offset', + null + ], + [ + [ + 12, + 36 + ], + 'FDArray', + 'offset', + null + ], + [ + [ + 12, + 38 + ], + 'FontName', + 'sid', + null + ] + ]; + var tables = null; + function CFFTopDict(strings) { + if (tables === null) { + tables = CFFDict.createTables(layout); + } + CFFDict.call(this, tables, strings); + this.privateDict = null; + } + CFFTopDict.prototype = Object.create(CFFDict.prototype); + return CFFTopDict; +}(); +var CFFPrivateDict = function CFFPrivateDictClosure() { + var layout = [ + [ + 6, + 'BlueValues', + 'delta', + null + ], + [ + 7, + 'OtherBlues', + 'delta', + null + ], + [ + 8, + 'FamilyBlues', + 'delta', + null + ], + [ + 9, + 'FamilyOtherBlues', + 'delta', + null + ], + [ + [ + 12, + 9 + ], + 'BlueScale', + 'num', + 0.039625 + ], + [ + [ + 12, + 10 + ], + 'BlueShift', + 'num', + 7 + ], + [ + [ + 12, + 11 + ], + 'BlueFuzz', + 'num', + 1 + ], + [ + 10, + 'StdHW', + 'num', + null + ], + [ + 11, + 'StdVW', + 'num', + null + ], + [ + [ + 12, + 12 + ], + 'StemSnapH', + 'delta', + null + ], + [ + [ + 12, + 13 + ], + 'StemSnapV', + 'delta', + null + ], + [ + [ + 12, + 14 + ], + 'ForceBold', + 'num', + 0 + ], + [ + [ + 12, + 17 + ], + 'LanguageGroup', + 'num', + 0 + ], + [ + [ + 12, + 18 + ], + 'ExpansionFactor', + 'num', + 0.06 + ], + [ + [ + 12, + 19 + ], + 'initialRandomSeed', + 'num', + 0 + ], + [ + 20, + 'defaultWidthX', + 'num', + 0 + ], + [ + 21, + 'nominalWidthX', + 'num', + 0 + ], + [ + 19, + 'Subrs', + 'offset', + null + ] + ]; + var tables = null; + function CFFPrivateDict(strings) { + if (tables === null) { + tables = CFFDict.createTables(layout); + } + CFFDict.call(this, tables, strings); + this.subrsIndex = null; + } + CFFPrivateDict.prototype = Object.create(CFFDict.prototype); + return CFFPrivateDict; +}(); +var CFFCharsetPredefinedTypes = { + ISO_ADOBE: 0, + EXPERT: 1, + EXPERT_SUBSET: 2 +}; +var CFFCharset = function CFFCharsetClosure() { + function CFFCharset(predefined, format, charset, raw) { + this.predefined = predefined; + this.format = format; + this.charset = charset; + this.raw = raw; + } + return CFFCharset; +}(); +var CFFEncoding = function CFFEncodingClosure() { + function CFFEncoding(predefined, format, encoding, raw) { + this.predefined = predefined; + this.format = format; + this.encoding = encoding; + this.raw = raw; + } + return CFFEncoding; +}(); +var CFFFDSelect = function CFFFDSelectClosure() { + function CFFFDSelect(fdSelect, raw) { + this.fdSelect = fdSelect; + this.raw = raw; + } + CFFFDSelect.prototype = { + getFDIndex: function CFFFDSelect_get(glyphIndex) { + if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) { + return -1; + } + return this.fdSelect[glyphIndex]; + } + }; + return CFFFDSelect; +}(); +var CFFOffsetTracker = function CFFOffsetTrackerClosure() { + function CFFOffsetTracker() { + this.offsets = Object.create(null); + } + CFFOffsetTracker.prototype = { + isTracking: function CFFOffsetTracker_isTracking(key) { + return key in this.offsets; + }, + track: function CFFOffsetTracker_track(key, location) { + if (key in this.offsets) { + error('Already tracking location of ' + key); + } + this.offsets[key] = location; + }, + offset: function CFFOffsetTracker_offset(value) { + for (var key in this.offsets) { + this.offsets[key] += value; + } + }, + setEntryLocation: function CFFOffsetTracker_setEntryLocation(key, values, output) { + if (!(key in this.offsets)) { + error('Not tracking location of ' + key); + } + var data = output.data; + var dataOffset = this.offsets[key]; + var size = 5; + for (var i = 0, ii = values.length; i < ii; ++i) { + var offset0 = i * size + dataOffset; + var offset1 = offset0 + 1; + var offset2 = offset0 + 2; + var offset3 = offset0 + 3; + var offset4 = offset0 + 4; + if (data[offset0] !== 0x1d || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) { + error('writing to an offset that is not empty'); + } + var value = values[i]; + data[offset0] = 0x1d; + data[offset1] = value >> 24 & 0xFF; + data[offset2] = value >> 16 & 0xFF; + data[offset3] = value >> 8 & 0xFF; + data[offset4] = value & 0xFF; + } + } + }; + return CFFOffsetTracker; +}(); +var CFFCompiler = function CFFCompilerClosure() { + function CFFCompiler(cff) { + this.cff = cff; + } + CFFCompiler.prototype = { + compile: function CFFCompiler_compile() { + var cff = this.cff; + var output = { + data: [], + length: 0, + add: function CFFCompiler_add(data) { + this.data = this.data.concat(data); + this.length = this.data.length; + } + }; + var header = this.compileHeader(cff.header); + output.add(header); + var nameIndex = this.compileNameIndex(cff.names); + output.add(nameIndex); + if (cff.isCIDFont) { + if (cff.topDict.hasName('FontMatrix')) { + var base = cff.topDict.getByName('FontMatrix'); + cff.topDict.removeByName('FontMatrix'); + for (var i = 0, ii = cff.fdArray.length; i < ii; i++) { + var subDict = cff.fdArray[i]; + var matrix = base.slice(0); + if (subDict.hasName('FontMatrix')) { + matrix = Util.transform(matrix, subDict.getByName('FontMatrix')); + } + subDict.setByName('FontMatrix', matrix); + } + } + } + var compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont); + output.add(compiled.output); + var topDictTracker = compiled.trackers[0]; + var stringIndex = this.compileStringIndex(cff.strings.strings); + output.add(stringIndex); + var globalSubrIndex = this.compileIndex(cff.globalSubrIndex); + output.add(globalSubrIndex); + if (cff.encoding && cff.topDict.hasName('Encoding')) { + if (cff.encoding.predefined) { + topDictTracker.setEntryLocation('Encoding', [cff.encoding.format], output); + } else { + var encoding = this.compileEncoding(cff.encoding); + topDictTracker.setEntryLocation('Encoding', [output.length], output); + output.add(encoding); + } + } + if (cff.charset && cff.topDict.hasName('charset')) { + if (cff.charset.predefined) { + topDictTracker.setEntryLocation('charset', [cff.charset.format], output); + } else { + var charset = this.compileCharset(cff.charset); + topDictTracker.setEntryLocation('charset', [output.length], output); + output.add(charset); + } + } + var charStrings = this.compileCharStrings(cff.charStrings); + topDictTracker.setEntryLocation('CharStrings', [output.length], output); + output.add(charStrings); + if (cff.isCIDFont) { + topDictTracker.setEntryLocation('FDSelect', [output.length], output); + var fdSelect = this.compileFDSelect(cff.fdSelect.raw); + output.add(fdSelect); + compiled = this.compileTopDicts(cff.fdArray, output.length, true); + topDictTracker.setEntryLocation('FDArray', [output.length], output); + output.add(compiled.output); + var fontDictTrackers = compiled.trackers; + this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output); + } + this.compilePrivateDicts([cff.topDict], [topDictTracker], output); + output.add([0]); + return output.data; + }, + encodeNumber: function CFFCompiler_encodeNumber(value) { + if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) { + return this.encodeInteger(value); + } + return this.encodeFloat(value); + }, + encodeFloat: function CFFCompiler_encodeFloat(num) { + var value = num.toString(); + var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value); + if (m) { + var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length)); + value = (Math.round(num * epsilon) / epsilon).toString(); + } + var nibbles = ''; + var i, ii; + for (i = 0, ii = value.length; i < ii; ++i) { + var a = value[i]; + if (a === 'e') { + nibbles += value[++i] === '-' ? 'c' : 'b'; + } else if (a === '.') { + nibbles += 'a'; + } else if (a === '-') { + nibbles += 'e'; + } else { + nibbles += a; + } + } + nibbles += nibbles.length & 1 ? 'f' : 'ff'; + var out = [30]; + for (i = 0, ii = nibbles.length; i < ii; i += 2) { + out.push(parseInt(nibbles.substr(i, 2), 16)); + } + return out; + }, + encodeInteger: function CFFCompiler_encodeInteger(value) { + var code; + if (value >= -107 && value <= 107) { + code = [value + 139]; + } else if (value >= 108 && value <= 1131) { + value = value - 108; + code = [ + (value >> 8) + 247, + value & 0xFF + ]; + } else if (value >= -1131 && value <= -108) { + value = -value - 108; + code = [ + (value >> 8) + 251, + value & 0xFF + ]; + } else if (value >= -32768 && value <= 32767) { + code = [ + 0x1c, + value >> 8 & 0xFF, + value & 0xFF + ]; + } else { + code = [ + 0x1d, + value >> 24 & 0xFF, + value >> 16 & 0xFF, + value >> 8 & 0xFF, + value & 0xFF + ]; + } + return code; + }, + compileHeader: function CFFCompiler_compileHeader(header) { + return [ + header.major, + header.minor, + header.hdrSize, + header.offSize + ]; + }, + compileNameIndex: function CFFCompiler_compileNameIndex(names) { + var nameIndex = new CFFIndex(); + for (var i = 0, ii = names.length; i < ii; ++i) { + nameIndex.add(stringToBytes(names[i])); + } + return this.compileIndex(nameIndex); + }, + compileTopDicts: function CFFCompiler_compileTopDicts(dicts, length, removeCidKeys) { + var fontDictTrackers = []; + var fdArrayIndex = new CFFIndex(); + for (var i = 0, ii = dicts.length; i < ii; ++i) { + var fontDict = dicts[i]; + if (removeCidKeys) { + fontDict.removeByName('CIDFontVersion'); + fontDict.removeByName('CIDFontRevision'); + fontDict.removeByName('CIDFontType'); + fontDict.removeByName('CIDCount'); + fontDict.removeByName('UIDBase'); + } + var fontDictTracker = new CFFOffsetTracker(); + var fontDictData = this.compileDict(fontDict, fontDictTracker); + fontDictTrackers.push(fontDictTracker); + fdArrayIndex.add(fontDictData); + fontDictTracker.offset(length); + } + fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers); + return { + trackers: fontDictTrackers, + output: fdArrayIndex + }; + }, + compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts, trackers, output) { + for (var i = 0, ii = dicts.length; i < ii; ++i) { + var fontDict = dicts[i]; + assert(fontDict.privateDict && fontDict.hasName('Private'), 'There must be an private dictionary.'); + var privateDict = fontDict.privateDict; + var privateDictTracker = new CFFOffsetTracker(); + var privateDictData = this.compileDict(privateDict, privateDictTracker); + var outputLength = output.length; + privateDictTracker.offset(outputLength); + if (!privateDictData.length) { + outputLength = 0; + } + trackers[i].setEntryLocation('Private', [ + privateDictData.length, + outputLength + ], output); + output.add(privateDictData); + if (privateDict.subrsIndex && privateDict.hasName('Subrs')) { + var subrs = this.compileIndex(privateDict.subrsIndex); + privateDictTracker.setEntryLocation('Subrs', [privateDictData.length], output); + output.add(subrs); + } + } + }, + compileDict: function CFFCompiler_compileDict(dict, offsetTracker) { + var out = []; + var order = dict.order; + for (var i = 0; i < order.length; ++i) { + var key = order[i]; + if (!(key in dict.values)) { + continue; + } + var values = dict.values[key]; + var types = dict.types[key]; + if (!isArray(types)) { + types = [types]; + } + if (!isArray(values)) { + values = [values]; + } + if (values.length === 0) { + continue; + } + for (var j = 0, jj = types.length; j < jj; ++j) { + var type = types[j]; + var value = values[j]; + switch (type) { + case 'num': + case 'sid': + out = out.concat(this.encodeNumber(value)); + break; + case 'offset': + var name = dict.keyToNameMap[key]; + if (!offsetTracker.isTracking(name)) { + offsetTracker.track(name, out.length); + } + out = out.concat([ + 0x1d, + 0, + 0, + 0, + 0 + ]); + break; + case 'array': + case 'delta': + out = out.concat(this.encodeNumber(value)); + for (var k = 1, kk = values.length; k < kk; ++k) { + out = out.concat(this.encodeNumber(values[k])); + } + break; + default: + error('Unknown data type of ' + type); + break; + } + } + out = out.concat(dict.opcodes[key]); + } + return out; + }, + compileStringIndex: function CFFCompiler_compileStringIndex(strings) { + var stringIndex = new CFFIndex(); + for (var i = 0, ii = strings.length; i < ii; ++i) { + stringIndex.add(stringToBytes(strings[i])); + } + return this.compileIndex(stringIndex); + }, + compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() { + var globalSubrIndex = this.cff.globalSubrIndex; + this.out.writeByteArray(this.compileIndex(globalSubrIndex)); + }, + compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) { + return this.compileIndex(charStrings); + }, + compileCharset: function CFFCompiler_compileCharset(charset) { + return this.compileTypedArray(charset.raw); + }, + compileEncoding: function CFFCompiler_compileEncoding(encoding) { + return this.compileTypedArray(encoding.raw); + }, + compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) { + return this.compileTypedArray(fdSelect); + }, + compileTypedArray: function CFFCompiler_compileTypedArray(data) { + var out = []; + for (var i = 0, ii = data.length; i < ii; ++i) { + out[i] = data[i]; + } + return out; + }, + compileIndex: function CFFCompiler_compileIndex(index, trackers) { + trackers = trackers || []; + var objects = index.objects; + var count = objects.length; + if (count === 0) { + return [ + 0, + 0, + 0 + ]; + } + var data = [ + count >> 8 & 0xFF, + count & 0xff + ]; + var lastOffset = 1, i; + for (i = 0; i < count; ++i) { + lastOffset += objects[i].length; + } + var offsetSize; + if (lastOffset < 0x100) { + offsetSize = 1; + } else if (lastOffset < 0x10000) { + offsetSize = 2; + } else if (lastOffset < 0x1000000) { + offsetSize = 3; + } else { + offsetSize = 4; + } + data.push(offsetSize); + var relativeOffset = 1; + for (i = 0; i < count + 1; i++) { + if (offsetSize === 1) { + data.push(relativeOffset & 0xFF); + } else if (offsetSize === 2) { + data.push(relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF); + } else if (offsetSize === 3) { + data.push(relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF); + } else { + data.push(relativeOffset >>> 24 & 0xFF, relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF); + } + if (objects[i]) { + relativeOffset += objects[i].length; + } + } + for (i = 0; i < count; i++) { + if (trackers[i]) { + trackers[i].offset(data.length); + } + for (var j = 0, jj = objects[i].length; j < jj; j++) { + data.push(objects[i][j]); + } + } + return data; + } + }; + return CFFCompiler; +}(); +exports.CFFStandardStrings = CFFStandardStrings; +exports.CFFParser = CFFParser; +exports.CFF = CFF; +exports.CFFHeader = CFFHeader; +exports.CFFStrings = CFFStrings; +exports.CFFIndex = CFFIndex; +exports.CFFCharset = CFFCharset; +exports.CFFTopDict = CFFTopDict; +exports.CFFPrivateDict = CFFPrivateDict; +exports.CFFCompiler = CFFCompiler; + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var MissingDataException = sharedUtil.MissingDataException; +var arrayByteLength = sharedUtil.arrayByteLength; +var arraysToBytes = sharedUtil.arraysToBytes; +var assert = sharedUtil.assert; +var createPromiseCapability = sharedUtil.createPromiseCapability; +var isInt = sharedUtil.isInt; +var isEmptyObj = sharedUtil.isEmptyObj; +var ChunkedStream = function ChunkedStreamClosure() { + function ChunkedStream(length, chunkSize, manager) { + this.bytes = new Uint8Array(length); + this.start = 0; + this.pos = 0; + this.end = length; + this.chunkSize = chunkSize; + this.loadedChunks = []; + this.numChunksLoaded = 0; + this.numChunks = Math.ceil(length / chunkSize); + this.manager = manager; + this.progressiveDataLength = 0; + this.lastSuccessfulEnsureByteChunk = -1; + } + ChunkedStream.prototype = { + getMissingChunks: function ChunkedStream_getMissingChunks() { + var chunks = []; + for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) { + if (!this.loadedChunks[chunk]) { + chunks.push(chunk); + } + } + return chunks; + }, + getBaseStreams: function ChunkedStream_getBaseStreams() { + return [this]; + }, + allChunksLoaded: function ChunkedStream_allChunksLoaded() { + return this.numChunksLoaded === this.numChunks; + }, + onReceiveData: function ChunkedStream_onReceiveData(begin, chunk) { + var end = begin + chunk.byteLength; + assert(begin % this.chunkSize === 0, 'Bad begin offset: ' + begin); + var length = this.bytes.length; + assert(end % this.chunkSize === 0 || end === length, 'Bad end offset: ' + end); + this.bytes.set(new Uint8Array(chunk), begin); + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(begin / chunkSize); + var endChunk = Math.floor((end - 1) / chunkSize) + 1; + var curChunk; + for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + if (!this.loadedChunks[curChunk]) { + this.loadedChunks[curChunk] = true; + ++this.numChunksLoaded; + } + } + }, + onReceiveProgressiveData: function ChunkedStream_onReceiveProgressiveData(data) { + var position = this.progressiveDataLength; + var beginChunk = Math.floor(position / this.chunkSize); + this.bytes.set(new Uint8Array(data), position); + position += data.byteLength; + this.progressiveDataLength = position; + var endChunk = position >= this.end ? this.numChunks : Math.floor(position / this.chunkSize); + var curChunk; + for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + if (!this.loadedChunks[curChunk]) { + this.loadedChunks[curChunk] = true; + ++this.numChunksLoaded; + } + } + }, + ensureByte: function ChunkedStream_ensureByte(pos) { + var chunk = Math.floor(pos / this.chunkSize); + if (chunk === this.lastSuccessfulEnsureByteChunk) { + return; + } + if (!this.loadedChunks[chunk]) { + throw new MissingDataException(pos, pos + 1); + } + this.lastSuccessfulEnsureByteChunk = chunk; + }, + ensureRange: function ChunkedStream_ensureRange(begin, end) { + if (begin >= end) { + return; + } + if (end <= this.progressiveDataLength) { + return; + } + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(begin / chunkSize); + var endChunk = Math.floor((end - 1) / chunkSize) + 1; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!this.loadedChunks[chunk]) { + throw new MissingDataException(begin, end); + } + } + }, + nextEmptyChunk: function ChunkedStream_nextEmptyChunk(beginChunk) { + var chunk, numChunks = this.numChunks; + for (var i = 0; i < numChunks; ++i) { + chunk = (beginChunk + i) % numChunks; + if (!this.loadedChunks[chunk]) { + return chunk; + } + } + return null; + }, + hasChunk: function ChunkedStream_hasChunk(chunk) { + return !!this.loadedChunks[chunk]; + }, + get length() { + return this.end - this.start; + }, + get isEmpty() { + return this.length === 0; + }, + getByte: function ChunkedStream_getByte() { + var pos = this.pos; + if (pos >= this.end) { + return -1; + } + this.ensureByte(pos); + return this.bytes[this.pos++]; + }, + getUint16: function ChunkedStream_getUint16() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }, + getInt32: function ChunkedStream_getInt32() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }, + getBytes: function ChunkedStream_getBytes(length) { + var bytes = this.bytes; + var pos = this.pos; + var strEnd = this.end; + if (!length) { + this.ensureRange(pos, strEnd); + return bytes.subarray(pos, strEnd); + } + var end = pos + length; + if (end > strEnd) { + end = strEnd; + } + this.ensureRange(pos, end); + this.pos = end; + return bytes.subarray(pos, end); + }, + peekByte: function ChunkedStream_peekByte() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }, + peekBytes: function ChunkedStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + getByteRange: function ChunkedStream_getBytes(begin, end) { + this.ensureRange(begin, end); + return this.bytes.subarray(begin, end); + }, + skip: function ChunkedStream_skip(n) { + if (!n) { + n = 1; + } + this.pos += n; + }, + reset: function ChunkedStream_reset() { + this.pos = this.start; + }, + moveStart: function ChunkedStream_moveStart() { + this.start = this.pos; + }, + makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) { + this.ensureRange(start, start + length); + function ChunkedStreamSubstream() { + } + ChunkedStreamSubstream.prototype = Object.create(this); + ChunkedStreamSubstream.prototype.getMissingChunks = function () { + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(this.start / chunkSize); + var endChunk = Math.floor((this.end - 1) / chunkSize) + 1; + var missingChunks = []; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!this.loadedChunks[chunk]) { + missingChunks.push(chunk); + } + } + return missingChunks; + }; + var subStream = new ChunkedStreamSubstream(); + subStream.pos = subStream.start = start; + subStream.end = start + length || this.end; + subStream.dict = dict; + return subStream; + } + }; + return ChunkedStream; +}(); +var ChunkedStreamManager = function ChunkedStreamManagerClosure() { + function ChunkedStreamManager(pdfNetworkStream, args) { + var chunkSize = args.rangeChunkSize; + var length = args.length; + this.stream = new ChunkedStream(length, chunkSize, this); + this.length = length; + this.chunkSize = chunkSize; + this.pdfNetworkStream = pdfNetworkStream; + this.url = args.url; + this.disableAutoFetch = args.disableAutoFetch; + this.msgHandler = args.msgHandler; + this.currRequestId = 0; + this.chunksNeededByRequest = Object.create(null); + this.requestsByChunk = Object.create(null); + this.promisesByRequest = Object.create(null); + this.progressiveDataLength = 0; + this.aborted = false; + this._loadedStreamCapability = createPromiseCapability(); + } + ChunkedStreamManager.prototype = { + onLoadedStream: function ChunkedStreamManager_getLoadedStream() { + return this._loadedStreamCapability.promise; + }, + sendRequest: function ChunkedStreamManager_sendRequest(begin, end) { + var rangeReader = this.pdfNetworkStream.getRangeReader(begin, end); + if (!rangeReader.isStreamingSupported) { + rangeReader.onProgress = this.onProgress.bind(this); + } + var chunks = [], loaded = 0; + var manager = this; + var promise = new Promise(function (resolve, reject) { + var readChunk = function (chunk) { + try { + if (!chunk.done) { + var data = chunk.value; + chunks.push(data); + loaded += arrayByteLength(data); + if (rangeReader.isStreamingSupported) { + manager.onProgress({ loaded: loaded }); + } + rangeReader.read().then(readChunk, reject); + return; + } + var chunkData = arraysToBytes(chunks); + chunks = null; + resolve(chunkData); + } catch (e) { + reject(e); + } + }; + rangeReader.read().then(readChunk, reject); + }); + promise.then(function (data) { + if (this.aborted) { + return; + } + this.onReceiveData({ + chunk: data, + begin: begin + }); + }.bind(this)); + }, + requestAllChunks: function ChunkedStreamManager_requestAllChunks() { + var missingChunks = this.stream.getMissingChunks(); + this._requestChunks(missingChunks); + return this._loadedStreamCapability.promise; + }, + _requestChunks: function ChunkedStreamManager_requestChunks(chunks) { + var requestId = this.currRequestId++; + var i, ii; + var chunksNeeded = Object.create(null); + this.chunksNeededByRequest[requestId] = chunksNeeded; + for (i = 0, ii = chunks.length; i < ii; i++) { + if (!this.stream.hasChunk(chunks[i])) { + chunksNeeded[chunks[i]] = true; + } + } + if (isEmptyObj(chunksNeeded)) { + return Promise.resolve(); + } + var capability = createPromiseCapability(); + this.promisesByRequest[requestId] = capability; + var chunksToRequest = []; + for (var chunk in chunksNeeded) { + chunk = chunk | 0; + if (!(chunk in this.requestsByChunk)) { + this.requestsByChunk[chunk] = []; + chunksToRequest.push(chunk); + } + this.requestsByChunk[chunk].push(requestId); + } + if (!chunksToRequest.length) { + return capability.promise; + } + var groupedChunksToRequest = this.groupChunks(chunksToRequest); + for (i = 0; i < groupedChunksToRequest.length; ++i) { + var groupedChunk = groupedChunksToRequest[i]; + var begin = groupedChunk.beginChunk * this.chunkSize; + var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length); + this.sendRequest(begin, end); + } + return capability.promise; + }, + getStream: function ChunkedStreamManager_getStream() { + return this.stream; + }, + requestRange: function ChunkedStreamManager_requestRange(begin, end) { + end = Math.min(end, this.length); + var beginChunk = this.getBeginChunk(begin); + var endChunk = this.getEndChunk(end); + var chunks = []; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + chunks.push(chunk); + } + return this._requestChunks(chunks); + }, + requestRanges: function ChunkedStreamManager_requestRanges(ranges) { + ranges = ranges || []; + var chunksToRequest = []; + for (var i = 0; i < ranges.length; i++) { + var beginChunk = this.getBeginChunk(ranges[i].begin); + var endChunk = this.getEndChunk(ranges[i].end); + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (chunksToRequest.indexOf(chunk) < 0) { + chunksToRequest.push(chunk); + } + } + } + chunksToRequest.sort(function (a, b) { + return a - b; + }); + return this._requestChunks(chunksToRequest); + }, + groupChunks: function ChunkedStreamManager_groupChunks(chunks) { + var groupedChunks = []; + var beginChunk = -1; + var prevChunk = -1; + for (var i = 0; i < chunks.length; ++i) { + var chunk = chunks[i]; + if (beginChunk < 0) { + beginChunk = chunk; + } + if (prevChunk >= 0 && prevChunk + 1 !== chunk) { + groupedChunks.push({ + beginChunk: beginChunk, + endChunk: prevChunk + 1 + }); + beginChunk = chunk; + } + if (i + 1 === chunks.length) { + groupedChunks.push({ + beginChunk: beginChunk, + endChunk: chunk + 1 + }); + } + prevChunk = chunk; + } + return groupedChunks; + }, + onProgress: function ChunkedStreamManager_onProgress(args) { + var bytesLoaded = this.stream.numChunksLoaded * this.chunkSize + args.loaded; + this.msgHandler.send('DocProgress', { + loaded: bytesLoaded, + total: this.length + }); + }, + onReceiveData: function ChunkedStreamManager_onReceiveData(args) { + var chunk = args.chunk; + var isProgressive = args.begin === undefined; + var begin = isProgressive ? this.progressiveDataLength : args.begin; + var end = begin + chunk.byteLength; + var beginChunk = Math.floor(begin / this.chunkSize); + var endChunk = end < this.length ? Math.floor(end / this.chunkSize) : Math.ceil(end / this.chunkSize); + if (isProgressive) { + this.stream.onReceiveProgressiveData(chunk); + this.progressiveDataLength = end; + } else { + this.stream.onReceiveData(begin, chunk); + } + if (this.stream.allChunksLoaded()) { + this._loadedStreamCapability.resolve(this.stream); + } + var loadedRequests = []; + var i, requestId; + for (chunk = beginChunk; chunk < endChunk; ++chunk) { + var requestIds = this.requestsByChunk[chunk] || []; + delete this.requestsByChunk[chunk]; + for (i = 0; i < requestIds.length; ++i) { + requestId = requestIds[i]; + var chunksNeeded = this.chunksNeededByRequest[requestId]; + if (chunk in chunksNeeded) { + delete chunksNeeded[chunk]; + } + if (!isEmptyObj(chunksNeeded)) { + continue; + } + loadedRequests.push(requestId); + } + } + if (!this.disableAutoFetch && isEmptyObj(this.requestsByChunk)) { + var nextEmptyChunk; + if (this.stream.numChunksLoaded === 1) { + var lastChunk = this.stream.numChunks - 1; + if (!this.stream.hasChunk(lastChunk)) { + nextEmptyChunk = lastChunk; + } + } else { + nextEmptyChunk = this.stream.nextEmptyChunk(endChunk); + } + if (isInt(nextEmptyChunk)) { + this._requestChunks([nextEmptyChunk]); + } + } + for (i = 0; i < loadedRequests.length; ++i) { + requestId = loadedRequests[i]; + var capability = this.promisesByRequest[requestId]; + delete this.promisesByRequest[requestId]; + capability.resolve(); + } + this.msgHandler.send('DocProgress', { + loaded: this.stream.numChunksLoaded * this.chunkSize, + total: this.length + }); + }, + onError: function ChunkedStreamManager_onError(err) { + this._loadedStreamCapability.reject(err); + }, + getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) { + var chunk = Math.floor(begin / this.chunkSize); + return chunk; + }, + getEndChunk: function ChunkedStreamManager_getEndChunk(end) { + var chunk = Math.floor((end - 1) / this.chunkSize) + 1; + return chunk; + }, + abort: function ChunkedStreamManager_abort() { + this.aborted = true; + if (this.pdfNetworkStream) { + this.pdfNetworkStream.cancelAllRequests('abort'); + } + for (var requestId in this.promisesByRequest) { + var capability = this.promisesByRequest[requestId]; + capability.reject(new Error('Request was aborted')); + } + } + }; + return ChunkedStreamManager; +}(); +exports.ChunkedStream = ChunkedStream; +exports.ChunkedStreamManager = ChunkedStreamManager; + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreStream = __w_pdfjs_require__(2); +var PasswordException = sharedUtil.PasswordException; +var PasswordResponses = sharedUtil.PasswordResponses; +var bytesToString = sharedUtil.bytesToString; +var warn = sharedUtil.warn; +var error = sharedUtil.error; +var assert = sharedUtil.assert; +var isInt = sharedUtil.isInt; +var stringToBytes = sharedUtil.stringToBytes; +var utf8StringToString = sharedUtil.utf8StringToString; +var Name = corePrimitives.Name; +var isName = corePrimitives.isName; +var isDict = corePrimitives.isDict; +var DecryptStream = coreStream.DecryptStream; +var ARCFourCipher = function ARCFourCipherClosure() { + function ARCFourCipher(key) { + this.a = 0; + this.b = 0; + var s = new Uint8Array(256); + var i, j = 0, tmp, keyLength = key.length; + for (i = 0; i < 256; ++i) { + s[i] = i; + } + for (i = 0; i < 256; ++i) { + tmp = s[i]; + j = j + tmp + key[i % keyLength] & 0xFF; + s[i] = s[j]; + s[j] = tmp; + } + this.s = s; + } + ARCFourCipher.prototype = { + encryptBlock: function ARCFourCipher_encryptBlock(data) { + var i, n = data.length, tmp, tmp2; + var a = this.a, b = this.b, s = this.s; + var output = new Uint8Array(n); + for (i = 0; i < n; ++i) { + a = a + 1 & 0xFF; + tmp = s[a]; + b = b + tmp & 0xFF; + tmp2 = s[b]; + s[a] = tmp2; + s[b] = tmp; + output[i] = data[i] ^ s[tmp + tmp2 & 0xFF]; + } + this.a = a; + this.b = b; + return output; + } + }; + ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock; + return ARCFourCipher; +}(); +var calculateMD5 = function calculateMD5Closure() { + var r = new Uint8Array([ + 7, + 12, + 17, + 22, + 7, + 12, + 17, + 22, + 7, + 12, + 17, + 22, + 7, + 12, + 17, + 22, + 5, + 9, + 14, + 20, + 5, + 9, + 14, + 20, + 5, + 9, + 14, + 20, + 5, + 9, + 14, + 20, + 4, + 11, + 16, + 23, + 4, + 11, + 16, + 23, + 4, + 11, + 16, + 23, + 4, + 11, + 16, + 23, + 6, + 10, + 15, + 21, + 6, + 10, + 15, + 21, + 6, + 10, + 15, + 21, + 6, + 10, + 15, + 21 + ]); + var k = new Int32Array([ + -680876936, + -389564586, + 606105819, + -1044525330, + -176418897, + 1200080426, + -1473231341, + -45705983, + 1770035416, + -1958414417, + -42063, + -1990404162, + 1804603682, + -40341101, + -1502002290, + 1236535329, + -165796510, + -1069501632, + 643717713, + -373897302, + -701558691, + 38016083, + -660478335, + -405537848, + 568446438, + -1019803690, + -187363961, + 1163531501, + -1444681467, + -51403784, + 1735328473, + -1926607734, + -378558, + -2022574463, + 1839030562, + -35309556, + -1530992060, + 1272893353, + -155497632, + -1094730640, + 681279174, + -358537222, + -722521979, + 76029189, + -640364487, + -421815835, + 530742520, + -995338651, + -198630844, + 1126891415, + -1416354905, + -57434055, + 1700485571, + -1894986606, + -1051523, + -2054922799, + 1873313359, + -30611744, + -1560198380, + 1309151649, + -145523070, + -1120210379, + 718787259, + -343485551 + ]); + function hash(data, offset, length) { + var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878; + var paddedLength = length + 72 & ~63; + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + n = paddedLength - 8; + while (i < n) { + padded[i++] = 0; + } + padded[i++] = length << 3 & 0xFF; + padded[i++] = length >> 5 & 0xFF; + padded[i++] = length >> 13 & 0xFF; + padded[i++] = length >> 21 & 0xFF; + padded[i++] = length >>> 29 & 0xFF; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + var w = new Int32Array(16); + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j, i += 4) { + w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24; + } + var a = h0, b = h1, c = h2, d = h3, f, g; + for (j = 0; j < 64; ++j) { + if (j < 16) { + f = b & c | ~b & d; + g = j; + } else if (j < 32) { + f = d & b | ~d & c; + g = 5 * j + 1 & 15; + } else if (j < 48) { + f = b ^ c ^ d; + g = 3 * j + 5 & 15; + } else { + f = c ^ (b | ~d); + g = 7 * j & 15; + } + var tmp = d, rotateArg = a + f + k[j] + w[g] | 0, rotate = r[j]; + d = c; + c = b; + b = b + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0; + a = tmp; + } + h0 = h0 + a | 0; + h1 = h1 + b | 0; + h2 = h2 + c | 0; + h3 = h3 + d | 0; + } + return new Uint8Array([ + h0 & 0xFF, + h0 >> 8 & 0xFF, + h0 >> 16 & 0xFF, + h0 >>> 24 & 0xFF, + h1 & 0xFF, + h1 >> 8 & 0xFF, + h1 >> 16 & 0xFF, + h1 >>> 24 & 0xFF, + h2 & 0xFF, + h2 >> 8 & 0xFF, + h2 >> 16 & 0xFF, + h2 >>> 24 & 0xFF, + h3 & 0xFF, + h3 >> 8 & 0xFF, + h3 >> 16 & 0xFF, + h3 >>> 24 & 0xFF + ]); + } + return hash; +}(); +var Word64 = function Word64Closure() { + function Word64(highInteger, lowInteger) { + this.high = highInteger | 0; + this.low = lowInteger | 0; + } + Word64.prototype = { + and: function Word64_and(word) { + this.high &= word.high; + this.low &= word.low; + }, + xor: function Word64_xor(word) { + this.high ^= word.high; + this.low ^= word.low; + }, + or: function Word64_or(word) { + this.high |= word.high; + this.low |= word.low; + }, + shiftRight: function Word64_shiftRight(places) { + if (places >= 32) { + this.low = this.high >>> places - 32 | 0; + this.high = 0; + } else { + this.low = this.low >>> places | this.high << 32 - places; + this.high = this.high >>> places | 0; + } + }, + shiftLeft: function Word64_shiftLeft(places) { + if (places >= 32) { + this.high = this.low << places - 32; + this.low = 0; + } else { + this.high = this.high << places | this.low >>> 32 - places; + this.low = this.low << places; + } + }, + rotateRight: function Word64_rotateRight(places) { + var low, high; + if (places & 32) { + high = this.low; + low = this.high; + } else { + low = this.low; + high = this.high; + } + places &= 31; + this.low = low >>> places | high << 32 - places; + this.high = high >>> places | low << 32 - places; + }, + not: function Word64_not() { + this.high = ~this.high; + this.low = ~this.low; + }, + add: function Word64_add(word) { + var lowAdd = (this.low >>> 0) + (word.low >>> 0); + var highAdd = (this.high >>> 0) + (word.high >>> 0); + if (lowAdd > 0xFFFFFFFF) { + highAdd += 1; + } + this.low = lowAdd | 0; + this.high = highAdd | 0; + }, + copyTo: function Word64_copyTo(bytes, offset) { + bytes[offset] = this.high >>> 24 & 0xFF; + bytes[offset + 1] = this.high >> 16 & 0xFF; + bytes[offset + 2] = this.high >> 8 & 0xFF; + bytes[offset + 3] = this.high & 0xFF; + bytes[offset + 4] = this.low >>> 24 & 0xFF; + bytes[offset + 5] = this.low >> 16 & 0xFF; + bytes[offset + 6] = this.low >> 8 & 0xFF; + bytes[offset + 7] = this.low & 0xFF; + }, + assign: function Word64_assign(word) { + this.high = word.high; + this.low = word.low; + } + }; + return Word64; +}(); +var calculateSHA256 = function calculateSHA256Closure() { + function rotr(x, n) { + return x >>> n | x << 32 - n; + } + function ch(x, y, z) { + return x & y ^ ~x & z; + } + function maj(x, y, z) { + return x & y ^ x & z ^ y & z; + } + function sigma(x) { + return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); + } + function sigmaPrime(x) { + return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); + } + function littleSigma(x) { + return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3; + } + function littleSigmaPrime(x) { + return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10; + } + var k = [ + 0x428a2f98, + 0x71374491, + 0xb5c0fbcf, + 0xe9b5dba5, + 0x3956c25b, + 0x59f111f1, + 0x923f82a4, + 0xab1c5ed5, + 0xd807aa98, + 0x12835b01, + 0x243185be, + 0x550c7dc3, + 0x72be5d74, + 0x80deb1fe, + 0x9bdc06a7, + 0xc19bf174, + 0xe49b69c1, + 0xefbe4786, + 0x0fc19dc6, + 0x240ca1cc, + 0x2de92c6f, + 0x4a7484aa, + 0x5cb0a9dc, + 0x76f988da, + 0x983e5152, + 0xa831c66d, + 0xb00327c8, + 0xbf597fc7, + 0xc6e00bf3, + 0xd5a79147, + 0x06ca6351, + 0x14292967, + 0x27b70a85, + 0x2e1b2138, + 0x4d2c6dfc, + 0x53380d13, + 0x650a7354, + 0x766a0abb, + 0x81c2c92e, + 0x92722c85, + 0xa2bfe8a1, + 0xa81a664b, + 0xc24b8b70, + 0xc76c51a3, + 0xd192e819, + 0xd6990624, + 0xf40e3585, + 0x106aa070, + 0x19a4c116, + 0x1e376c08, + 0x2748774c, + 0x34b0bcb5, + 0x391c0cb3, + 0x4ed8aa4a, + 0x5b9cca4f, + 0x682e6ff3, + 0x748f82ee, + 0x78a5636f, + 0x84c87814, + 0x8cc70208, + 0x90befffa, + 0xa4506ceb, + 0xbef9a3f7, + 0xc67178f2 + ]; + function hash(data, offset, length) { + var h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, h3 = 0xa54ff53a, h4 = 0x510e527f, h5 = 0x9b05688c, h6 = 0x1f83d9ab, h7 = 0x5be0cd19; + var paddedLength = Math.ceil((length + 9) / 64) * 64; + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + n = paddedLength - 8; + while (i < n) { + padded[i++] = 0; + } + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = length >>> 29 & 0xFF; + padded[i++] = length >> 21 & 0xFF; + padded[i++] = length >> 13 & 0xFF; + padded[i++] = length >> 5 & 0xFF; + padded[i++] = length << 3 & 0xFF; + var w = new Uint32Array(64); + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j) { + w[j] = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3]; + i += 4; + } + for (j = 16; j < 64; ++j) { + w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + littleSigma(w[j - 15]) + w[j - 16] | 0; + } + var a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7, t1, t2; + for (j = 0; j < 64; ++j) { + t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j]; + t2 = sigma(a) + maj(a, b, c); + h = g; + g = f; + f = e; + e = d + t1 | 0; + d = c; + c = b; + b = a; + a = t1 + t2 | 0; + } + h0 = h0 + a | 0; + h1 = h1 + b | 0; + h2 = h2 + c | 0; + h3 = h3 + d | 0; + h4 = h4 + e | 0; + h5 = h5 + f | 0; + h6 = h6 + g | 0; + h7 = h7 + h | 0; + } + return new Uint8Array([ + h0 >> 24 & 0xFF, + h0 >> 16 & 0xFF, + h0 >> 8 & 0xFF, + h0 & 0xFF, + h1 >> 24 & 0xFF, + h1 >> 16 & 0xFF, + h1 >> 8 & 0xFF, + h1 & 0xFF, + h2 >> 24 & 0xFF, + h2 >> 16 & 0xFF, + h2 >> 8 & 0xFF, + h2 & 0xFF, + h3 >> 24 & 0xFF, + h3 >> 16 & 0xFF, + h3 >> 8 & 0xFF, + h3 & 0xFF, + h4 >> 24 & 0xFF, + h4 >> 16 & 0xFF, + h4 >> 8 & 0xFF, + h4 & 0xFF, + h5 >> 24 & 0xFF, + h5 >> 16 & 0xFF, + h5 >> 8 & 0xFF, + h5 & 0xFF, + h6 >> 24 & 0xFF, + h6 >> 16 & 0xFF, + h6 >> 8 & 0xFF, + h6 & 0xFF, + h7 >> 24 & 0xFF, + h7 >> 16 & 0xFF, + h7 >> 8 & 0xFF, + h7 & 0xFF + ]); + } + return hash; +}(); +var calculateSHA512 = function calculateSHA512Closure() { + function ch(result, x, y, z, tmp) { + result.assign(x); + result.and(y); + tmp.assign(x); + tmp.not(); + tmp.and(z); + result.xor(tmp); + } + function maj(result, x, y, z, tmp) { + result.assign(x); + result.and(y); + tmp.assign(x); + tmp.and(z); + result.xor(tmp); + tmp.assign(y); + tmp.and(z); + result.xor(tmp); + } + function sigma(result, x, tmp) { + result.assign(x); + result.rotateRight(28); + tmp.assign(x); + tmp.rotateRight(34); + result.xor(tmp); + tmp.assign(x); + tmp.rotateRight(39); + result.xor(tmp); + } + function sigmaPrime(result, x, tmp) { + result.assign(x); + result.rotateRight(14); + tmp.assign(x); + tmp.rotateRight(18); + result.xor(tmp); + tmp.assign(x); + tmp.rotateRight(41); + result.xor(tmp); + } + function littleSigma(result, x, tmp) { + result.assign(x); + result.rotateRight(1); + tmp.assign(x); + tmp.rotateRight(8); + result.xor(tmp); + tmp.assign(x); + tmp.shiftRight(7); + result.xor(tmp); + } + function littleSigmaPrime(result, x, tmp) { + result.assign(x); + result.rotateRight(19); + tmp.assign(x); + tmp.rotateRight(61); + result.xor(tmp); + tmp.assign(x); + tmp.shiftRight(6); + result.xor(tmp); + } + var k = [ + new Word64(0x428a2f98, 0xd728ae22), + new Word64(0x71374491, 0x23ef65cd), + new Word64(0xb5c0fbcf, 0xec4d3b2f), + new Word64(0xe9b5dba5, 0x8189dbbc), + new Word64(0x3956c25b, 0xf348b538), + new Word64(0x59f111f1, 0xb605d019), + new Word64(0x923f82a4, 0xaf194f9b), + new Word64(0xab1c5ed5, 0xda6d8118), + new Word64(0xd807aa98, 0xa3030242), + new Word64(0x12835b01, 0x45706fbe), + new Word64(0x243185be, 0x4ee4b28c), + new Word64(0x550c7dc3, 0xd5ffb4e2), + new Word64(0x72be5d74, 0xf27b896f), + new Word64(0x80deb1fe, 0x3b1696b1), + new Word64(0x9bdc06a7, 0x25c71235), + new Word64(0xc19bf174, 0xcf692694), + new Word64(0xe49b69c1, 0x9ef14ad2), + new Word64(0xefbe4786, 0x384f25e3), + new Word64(0x0fc19dc6, 0x8b8cd5b5), + new Word64(0x240ca1cc, 0x77ac9c65), + new Word64(0x2de92c6f, 0x592b0275), + new Word64(0x4a7484aa, 0x6ea6e483), + new Word64(0x5cb0a9dc, 0xbd41fbd4), + new Word64(0x76f988da, 0x831153b5), + new Word64(0x983e5152, 0xee66dfab), + new Word64(0xa831c66d, 0x2db43210), + new Word64(0xb00327c8, 0x98fb213f), + new Word64(0xbf597fc7, 0xbeef0ee4), + new Word64(0xc6e00bf3, 0x3da88fc2), + new Word64(0xd5a79147, 0x930aa725), + new Word64(0x06ca6351, 0xe003826f), + new Word64(0x14292967, 0x0a0e6e70), + new Word64(0x27b70a85, 0x46d22ffc), + new Word64(0x2e1b2138, 0x5c26c926), + new Word64(0x4d2c6dfc, 0x5ac42aed), + new Word64(0x53380d13, 0x9d95b3df), + new Word64(0x650a7354, 0x8baf63de), + new Word64(0x766a0abb, 0x3c77b2a8), + new Word64(0x81c2c92e, 0x47edaee6), + new Word64(0x92722c85, 0x1482353b), + new Word64(0xa2bfe8a1, 0x4cf10364), + new Word64(0xa81a664b, 0xbc423001), + new Word64(0xc24b8b70, 0xd0f89791), + new Word64(0xc76c51a3, 0x0654be30), + new Word64(0xd192e819, 0xd6ef5218), + new Word64(0xd6990624, 0x5565a910), + new Word64(0xf40e3585, 0x5771202a), + new Word64(0x106aa070, 0x32bbd1b8), + new Word64(0x19a4c116, 0xb8d2d0c8), + new Word64(0x1e376c08, 0x5141ab53), + new Word64(0x2748774c, 0xdf8eeb99), + new Word64(0x34b0bcb5, 0xe19b48a8), + new Word64(0x391c0cb3, 0xc5c95a63), + new Word64(0x4ed8aa4a, 0xe3418acb), + new Word64(0x5b9cca4f, 0x7763e373), + new Word64(0x682e6ff3, 0xd6b2b8a3), + new Word64(0x748f82ee, 0x5defb2fc), + new Word64(0x78a5636f, 0x43172f60), + new Word64(0x84c87814, 0xa1f0ab72), + new Word64(0x8cc70208, 0x1a6439ec), + new Word64(0x90befffa, 0x23631e28), + new Word64(0xa4506ceb, 0xde82bde9), + new Word64(0xbef9a3f7, 0xb2c67915), + new Word64(0xc67178f2, 0xe372532b), + new Word64(0xca273ece, 0xea26619c), + new Word64(0xd186b8c7, 0x21c0c207), + new Word64(0xeada7dd6, 0xcde0eb1e), + new Word64(0xf57d4f7f, 0xee6ed178), + new Word64(0x06f067aa, 0x72176fba), + new Word64(0x0a637dc5, 0xa2c898a6), + new Word64(0x113f9804, 0xbef90dae), + new Word64(0x1b710b35, 0x131c471b), + new Word64(0x28db77f5, 0x23047d84), + new Word64(0x32caab7b, 0x40c72493), + new Word64(0x3c9ebe0a, 0x15c9bebc), + new Word64(0x431d67c4, 0x9c100d4c), + new Word64(0x4cc5d4be, 0xcb3e42b6), + new Word64(0x597f299c, 0xfc657e2a), + new Word64(0x5fcb6fab, 0x3ad6faec), + new Word64(0x6c44198c, 0x4a475817) + ]; + function hash(data, offset, length, mode384) { + mode384 = !!mode384; + var h0, h1, h2, h3, h4, h5, h6, h7; + if (!mode384) { + h0 = new Word64(0x6a09e667, 0xf3bcc908); + h1 = new Word64(0xbb67ae85, 0x84caa73b); + h2 = new Word64(0x3c6ef372, 0xfe94f82b); + h3 = new Word64(0xa54ff53a, 0x5f1d36f1); + h4 = new Word64(0x510e527f, 0xade682d1); + h5 = new Word64(0x9b05688c, 0x2b3e6c1f); + h6 = new Word64(0x1f83d9ab, 0xfb41bd6b); + h7 = new Word64(0x5be0cd19, 0x137e2179); + } else { + h0 = new Word64(0xcbbb9d5d, 0xc1059ed8); + h1 = new Word64(0x629a292a, 0x367cd507); + h2 = new Word64(0x9159015a, 0x3070dd17); + h3 = new Word64(0x152fecd8, 0xf70e5939); + h4 = new Word64(0x67332667, 0xffc00b31); + h5 = new Word64(0x8eb44a87, 0x68581511); + h6 = new Word64(0xdb0c2e0d, 0x64f98fa7); + h7 = new Word64(0x47b5481d, 0xbefa4fa4); + } + var paddedLength = Math.ceil((length + 17) / 128) * 128; + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + n = paddedLength - 16; + while (i < n) { + padded[i++] = 0; + } + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = length >>> 29 & 0xFF; + padded[i++] = length >> 21 & 0xFF; + padded[i++] = length >> 13 & 0xFF; + padded[i++] = length >> 5 & 0xFF; + padded[i++] = length << 3 & 0xFF; + var w = new Array(80); + for (i = 0; i < 80; i++) { + w[i] = new Word64(0, 0); + } + var a = new Word64(0, 0), b = new Word64(0, 0), c = new Word64(0, 0); + var d = new Word64(0, 0), e = new Word64(0, 0), f = new Word64(0, 0); + var g = new Word64(0, 0), h = new Word64(0, 0); + var t1 = new Word64(0, 0), t2 = new Word64(0, 0); + var tmp1 = new Word64(0, 0), tmp2 = new Word64(0, 0), tmp3; + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j) { + w[j].high = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3]; + w[j].low = padded[i + 4] << 24 | padded[i + 5] << 16 | padded[i + 6] << 8 | padded[i + 7]; + i += 8; + } + for (j = 16; j < 80; ++j) { + tmp3 = w[j]; + littleSigmaPrime(tmp3, w[j - 2], tmp2); + tmp3.add(w[j - 7]); + littleSigma(tmp1, w[j - 15], tmp2); + tmp3.add(tmp1); + tmp3.add(w[j - 16]); + } + a.assign(h0); + b.assign(h1); + c.assign(h2); + d.assign(h3); + e.assign(h4); + f.assign(h5); + g.assign(h6); + h.assign(h7); + for (j = 0; j < 80; ++j) { + t1.assign(h); + sigmaPrime(tmp1, e, tmp2); + t1.add(tmp1); + ch(tmp1, e, f, g, tmp2); + t1.add(tmp1); + t1.add(k[j]); + t1.add(w[j]); + sigma(t2, a, tmp2); + maj(tmp1, a, b, c, tmp2); + t2.add(tmp1); + tmp3 = h; + h = g; + g = f; + f = e; + d.add(t1); + e = d; + d = c; + c = b; + b = a; + tmp3.assign(t1); + tmp3.add(t2); + a = tmp3; + } + h0.add(a); + h1.add(b); + h2.add(c); + h3.add(d); + h4.add(e); + h5.add(f); + h6.add(g); + h7.add(h); + } + var result; + if (!mode384) { + result = new Uint8Array(64); + h0.copyTo(result, 0); + h1.copyTo(result, 8); + h2.copyTo(result, 16); + h3.copyTo(result, 24); + h4.copyTo(result, 32); + h5.copyTo(result, 40); + h6.copyTo(result, 48); + h7.copyTo(result, 56); + } else { + result = new Uint8Array(48); + h0.copyTo(result, 0); + h1.copyTo(result, 8); + h2.copyTo(result, 16); + h3.copyTo(result, 24); + h4.copyTo(result, 32); + h5.copyTo(result, 40); + } + return result; + } + return hash; +}(); +var calculateSHA384 = function calculateSHA384Closure() { + function hash(data, offset, length) { + return calculateSHA512(data, offset, length, true); + } + return hash; +}(); +var NullCipher = function NullCipherClosure() { + function NullCipher() { + } + NullCipher.prototype = { + decryptBlock: function NullCipher_decryptBlock(data) { + return data; + } + }; + return NullCipher; +}(); +var AES128Cipher = function AES128CipherClosure() { + var rcon = new Uint8Array([ + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d + ]); + var s = new Uint8Array([ + 0x63, + 0x7c, + 0x77, + 0x7b, + 0xf2, + 0x6b, + 0x6f, + 0xc5, + 0x30, + 0x01, + 0x67, + 0x2b, + 0xfe, + 0xd7, + 0xab, + 0x76, + 0xca, + 0x82, + 0xc9, + 0x7d, + 0xfa, + 0x59, + 0x47, + 0xf0, + 0xad, + 0xd4, + 0xa2, + 0xaf, + 0x9c, + 0xa4, + 0x72, + 0xc0, + 0xb7, + 0xfd, + 0x93, + 0x26, + 0x36, + 0x3f, + 0xf7, + 0xcc, + 0x34, + 0xa5, + 0xe5, + 0xf1, + 0x71, + 0xd8, + 0x31, + 0x15, + 0x04, + 0xc7, + 0x23, + 0xc3, + 0x18, + 0x96, + 0x05, + 0x9a, + 0x07, + 0x12, + 0x80, + 0xe2, + 0xeb, + 0x27, + 0xb2, + 0x75, + 0x09, + 0x83, + 0x2c, + 0x1a, + 0x1b, + 0x6e, + 0x5a, + 0xa0, + 0x52, + 0x3b, + 0xd6, + 0xb3, + 0x29, + 0xe3, + 0x2f, + 0x84, + 0x53, + 0xd1, + 0x00, + 0xed, + 0x20, + 0xfc, + 0xb1, + 0x5b, + 0x6a, + 0xcb, + 0xbe, + 0x39, + 0x4a, + 0x4c, + 0x58, + 0xcf, + 0xd0, + 0xef, + 0xaa, + 0xfb, + 0x43, + 0x4d, + 0x33, + 0x85, + 0x45, + 0xf9, + 0x02, + 0x7f, + 0x50, + 0x3c, + 0x9f, + 0xa8, + 0x51, + 0xa3, + 0x40, + 0x8f, + 0x92, + 0x9d, + 0x38, + 0xf5, + 0xbc, + 0xb6, + 0xda, + 0x21, + 0x10, + 0xff, + 0xf3, + 0xd2, + 0xcd, + 0x0c, + 0x13, + 0xec, + 0x5f, + 0x97, + 0x44, + 0x17, + 0xc4, + 0xa7, + 0x7e, + 0x3d, + 0x64, + 0x5d, + 0x19, + 0x73, + 0x60, + 0x81, + 0x4f, + 0xdc, + 0x22, + 0x2a, + 0x90, + 0x88, + 0x46, + 0xee, + 0xb8, + 0x14, + 0xde, + 0x5e, + 0x0b, + 0xdb, + 0xe0, + 0x32, + 0x3a, + 0x0a, + 0x49, + 0x06, + 0x24, + 0x5c, + 0xc2, + 0xd3, + 0xac, + 0x62, + 0x91, + 0x95, + 0xe4, + 0x79, + 0xe7, + 0xc8, + 0x37, + 0x6d, + 0x8d, + 0xd5, + 0x4e, + 0xa9, + 0x6c, + 0x56, + 0xf4, + 0xea, + 0x65, + 0x7a, + 0xae, + 0x08, + 0xba, + 0x78, + 0x25, + 0x2e, + 0x1c, + 0xa6, + 0xb4, + 0xc6, + 0xe8, + 0xdd, + 0x74, + 0x1f, + 0x4b, + 0xbd, + 0x8b, + 0x8a, + 0x70, + 0x3e, + 0xb5, + 0x66, + 0x48, + 0x03, + 0xf6, + 0x0e, + 0x61, + 0x35, + 0x57, + 0xb9, + 0x86, + 0xc1, + 0x1d, + 0x9e, + 0xe1, + 0xf8, + 0x98, + 0x11, + 0x69, + 0xd9, + 0x8e, + 0x94, + 0x9b, + 0x1e, + 0x87, + 0xe9, + 0xce, + 0x55, + 0x28, + 0xdf, + 0x8c, + 0xa1, + 0x89, + 0x0d, + 0xbf, + 0xe6, + 0x42, + 0x68, + 0x41, + 0x99, + 0x2d, + 0x0f, + 0xb0, + 0x54, + 0xbb, + 0x16 + ]); + var inv_s = new Uint8Array([ + 0x52, + 0x09, + 0x6a, + 0xd5, + 0x30, + 0x36, + 0xa5, + 0x38, + 0xbf, + 0x40, + 0xa3, + 0x9e, + 0x81, + 0xf3, + 0xd7, + 0xfb, + 0x7c, + 0xe3, + 0x39, + 0x82, + 0x9b, + 0x2f, + 0xff, + 0x87, + 0x34, + 0x8e, + 0x43, + 0x44, + 0xc4, + 0xde, + 0xe9, + 0xcb, + 0x54, + 0x7b, + 0x94, + 0x32, + 0xa6, + 0xc2, + 0x23, + 0x3d, + 0xee, + 0x4c, + 0x95, + 0x0b, + 0x42, + 0xfa, + 0xc3, + 0x4e, + 0x08, + 0x2e, + 0xa1, + 0x66, + 0x28, + 0xd9, + 0x24, + 0xb2, + 0x76, + 0x5b, + 0xa2, + 0x49, + 0x6d, + 0x8b, + 0xd1, + 0x25, + 0x72, + 0xf8, + 0xf6, + 0x64, + 0x86, + 0x68, + 0x98, + 0x16, + 0xd4, + 0xa4, + 0x5c, + 0xcc, + 0x5d, + 0x65, + 0xb6, + 0x92, + 0x6c, + 0x70, + 0x48, + 0x50, + 0xfd, + 0xed, + 0xb9, + 0xda, + 0x5e, + 0x15, + 0x46, + 0x57, + 0xa7, + 0x8d, + 0x9d, + 0x84, + 0x90, + 0xd8, + 0xab, + 0x00, + 0x8c, + 0xbc, + 0xd3, + 0x0a, + 0xf7, + 0xe4, + 0x58, + 0x05, + 0xb8, + 0xb3, + 0x45, + 0x06, + 0xd0, + 0x2c, + 0x1e, + 0x8f, + 0xca, + 0x3f, + 0x0f, + 0x02, + 0xc1, + 0xaf, + 0xbd, + 0x03, + 0x01, + 0x13, + 0x8a, + 0x6b, + 0x3a, + 0x91, + 0x11, + 0x41, + 0x4f, + 0x67, + 0xdc, + 0xea, + 0x97, + 0xf2, + 0xcf, + 0xce, + 0xf0, + 0xb4, + 0xe6, + 0x73, + 0x96, + 0xac, + 0x74, + 0x22, + 0xe7, + 0xad, + 0x35, + 0x85, + 0xe2, + 0xf9, + 0x37, + 0xe8, + 0x1c, + 0x75, + 0xdf, + 0x6e, + 0x47, + 0xf1, + 0x1a, + 0x71, + 0x1d, + 0x29, + 0xc5, + 0x89, + 0x6f, + 0xb7, + 0x62, + 0x0e, + 0xaa, + 0x18, + 0xbe, + 0x1b, + 0xfc, + 0x56, + 0x3e, + 0x4b, + 0xc6, + 0xd2, + 0x79, + 0x20, + 0x9a, + 0xdb, + 0xc0, + 0xfe, + 0x78, + 0xcd, + 0x5a, + 0xf4, + 0x1f, + 0xdd, + 0xa8, + 0x33, + 0x88, + 0x07, + 0xc7, + 0x31, + 0xb1, + 0x12, + 0x10, + 0x59, + 0x27, + 0x80, + 0xec, + 0x5f, + 0x60, + 0x51, + 0x7f, + 0xa9, + 0x19, + 0xb5, + 0x4a, + 0x0d, + 0x2d, + 0xe5, + 0x7a, + 0x9f, + 0x93, + 0xc9, + 0x9c, + 0xef, + 0xa0, + 0xe0, + 0x3b, + 0x4d, + 0xae, + 0x2a, + 0xf5, + 0xb0, + 0xc8, + 0xeb, + 0xbb, + 0x3c, + 0x83, + 0x53, + 0x99, + 0x61, + 0x17, + 0x2b, + 0x04, + 0x7e, + 0xba, + 0x77, + 0xd6, + 0x26, + 0xe1, + 0x69, + 0x14, + 0x63, + 0x55, + 0x21, + 0x0c, + 0x7d + ]); + var mixCol = new Uint8Array(256); + for (var i = 0; i < 256; i++) { + if (i < 128) { + mixCol[i] = i << 1; + } else { + mixCol[i] = i << 1 ^ 0x1b; + } + } + var mix = new Uint32Array([ + 0x00000000, + 0x0e090d0b, + 0x1c121a16, + 0x121b171d, + 0x3824342c, + 0x362d3927, + 0x24362e3a, + 0x2a3f2331, + 0x70486858, + 0x7e416553, + 0x6c5a724e, + 0x62537f45, + 0x486c5c74, + 0x4665517f, + 0x547e4662, + 0x5a774b69, + 0xe090d0b0, + 0xee99ddbb, + 0xfc82caa6, + 0xf28bc7ad, + 0xd8b4e49c, + 0xd6bde997, + 0xc4a6fe8a, + 0xcaaff381, + 0x90d8b8e8, + 0x9ed1b5e3, + 0x8ccaa2fe, + 0x82c3aff5, + 0xa8fc8cc4, + 0xa6f581cf, + 0xb4ee96d2, + 0xbae79bd9, + 0xdb3bbb7b, + 0xd532b670, + 0xc729a16d, + 0xc920ac66, + 0xe31f8f57, + 0xed16825c, + 0xff0d9541, + 0xf104984a, + 0xab73d323, + 0xa57ade28, + 0xb761c935, + 0xb968c43e, + 0x9357e70f, + 0x9d5eea04, + 0x8f45fd19, + 0x814cf012, + 0x3bab6bcb, + 0x35a266c0, + 0x27b971dd, + 0x29b07cd6, + 0x038f5fe7, + 0x0d8652ec, + 0x1f9d45f1, + 0x119448fa, + 0x4be30393, + 0x45ea0e98, + 0x57f11985, + 0x59f8148e, + 0x73c737bf, + 0x7dce3ab4, + 0x6fd52da9, + 0x61dc20a2, + 0xad766df6, + 0xa37f60fd, + 0xb16477e0, + 0xbf6d7aeb, + 0x955259da, + 0x9b5b54d1, + 0x894043cc, + 0x87494ec7, + 0xdd3e05ae, + 0xd33708a5, + 0xc12c1fb8, + 0xcf2512b3, + 0xe51a3182, + 0xeb133c89, + 0xf9082b94, + 0xf701269f, + 0x4de6bd46, + 0x43efb04d, + 0x51f4a750, + 0x5ffdaa5b, + 0x75c2896a, + 0x7bcb8461, + 0x69d0937c, + 0x67d99e77, + 0x3daed51e, + 0x33a7d815, + 0x21bccf08, + 0x2fb5c203, + 0x058ae132, + 0x0b83ec39, + 0x1998fb24, + 0x1791f62f, + 0x764dd68d, + 0x7844db86, + 0x6a5fcc9b, + 0x6456c190, + 0x4e69e2a1, + 0x4060efaa, + 0x527bf8b7, + 0x5c72f5bc, + 0x0605bed5, + 0x080cb3de, + 0x1a17a4c3, + 0x141ea9c8, + 0x3e218af9, + 0x302887f2, + 0x223390ef, + 0x2c3a9de4, + 0x96dd063d, + 0x98d40b36, + 0x8acf1c2b, + 0x84c61120, + 0xaef93211, + 0xa0f03f1a, + 0xb2eb2807, + 0xbce2250c, + 0xe6956e65, + 0xe89c636e, + 0xfa877473, + 0xf48e7978, + 0xdeb15a49, + 0xd0b85742, + 0xc2a3405f, + 0xccaa4d54, + 0x41ecdaf7, + 0x4fe5d7fc, + 0x5dfec0e1, + 0x53f7cdea, + 0x79c8eedb, + 0x77c1e3d0, + 0x65daf4cd, + 0x6bd3f9c6, + 0x31a4b2af, + 0x3fadbfa4, + 0x2db6a8b9, + 0x23bfa5b2, + 0x09808683, + 0x07898b88, + 0x15929c95, + 0x1b9b919e, + 0xa17c0a47, + 0xaf75074c, + 0xbd6e1051, + 0xb3671d5a, + 0x99583e6b, + 0x97513360, + 0x854a247d, + 0x8b432976, + 0xd134621f, + 0xdf3d6f14, + 0xcd267809, + 0xc32f7502, + 0xe9105633, + 0xe7195b38, + 0xf5024c25, + 0xfb0b412e, + 0x9ad7618c, + 0x94de6c87, + 0x86c57b9a, + 0x88cc7691, + 0xa2f355a0, + 0xacfa58ab, + 0xbee14fb6, + 0xb0e842bd, + 0xea9f09d4, + 0xe49604df, + 0xf68d13c2, + 0xf8841ec9, + 0xd2bb3df8, + 0xdcb230f3, + 0xcea927ee, + 0xc0a02ae5, + 0x7a47b13c, + 0x744ebc37, + 0x6655ab2a, + 0x685ca621, + 0x42638510, + 0x4c6a881b, + 0x5e719f06, + 0x5078920d, + 0x0a0fd964, + 0x0406d46f, + 0x161dc372, + 0x1814ce79, + 0x322bed48, + 0x3c22e043, + 0x2e39f75e, + 0x2030fa55, + 0xec9ab701, + 0xe293ba0a, + 0xf088ad17, + 0xfe81a01c, + 0xd4be832d, + 0xdab78e26, + 0xc8ac993b, + 0xc6a59430, + 0x9cd2df59, + 0x92dbd252, + 0x80c0c54f, + 0x8ec9c844, + 0xa4f6eb75, + 0xaaffe67e, + 0xb8e4f163, + 0xb6edfc68, + 0x0c0a67b1, + 0x02036aba, + 0x10187da7, + 0x1e1170ac, + 0x342e539d, + 0x3a275e96, + 0x283c498b, + 0x26354480, + 0x7c420fe9, + 0x724b02e2, + 0x605015ff, + 0x6e5918f4, + 0x44663bc5, + 0x4a6f36ce, + 0x587421d3, + 0x567d2cd8, + 0x37a10c7a, + 0x39a80171, + 0x2bb3166c, + 0x25ba1b67, + 0x0f853856, + 0x018c355d, + 0x13972240, + 0x1d9e2f4b, + 0x47e96422, + 0x49e06929, + 0x5bfb7e34, + 0x55f2733f, + 0x7fcd500e, + 0x71c45d05, + 0x63df4a18, + 0x6dd64713, + 0xd731dcca, + 0xd938d1c1, + 0xcb23c6dc, + 0xc52acbd7, + 0xef15e8e6, + 0xe11ce5ed, + 0xf307f2f0, + 0xfd0efffb, + 0xa779b492, + 0xa970b999, + 0xbb6bae84, + 0xb562a38f, + 0x9f5d80be, + 0x91548db5, + 0x834f9aa8, + 0x8d4697a3 + ]); + function expandKey128(cipherKey) { + var b = 176, result = new Uint8Array(b); + result.set(cipherKey); + for (var j = 16, i = 1; j < b; ++i) { + var t1 = result[j - 3], t2 = result[j - 2], t3 = result[j - 1], t4 = result[j - 4]; + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + t1 = t1 ^ rcon[i]; + for (var n = 0; n < 4; ++n) { + result[j] = t1 ^= result[j - 16]; + j++; + result[j] = t2 ^= result[j - 16]; + j++; + result[j] = t3 ^= result[j - 16]; + j++; + result[j] = t4 ^= result[j - 16]; + j++; + } + } + return result; + } + function decrypt128(input, key) { + var state = new Uint8Array(16); + state.set(input); + var i, j, k; + var t, u, v; + for (j = 0, k = 160; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (i = 9; i >= 1; --i) { + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (j = 0; j < 16; ++j) { + state[j] = inv_s[state[j]]; + } + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (j = 0; j < 16; j += 4) { + var s0 = mix[state[j]], s1 = mix[state[j + 1]], s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; + t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8; + state[j] = t >>> 24 & 0xFF; + state[j + 1] = t >> 16 & 0xFF; + state[j + 2] = t >> 8 & 0xFF; + state[j + 3] = t & 0xFF; + } + } + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (j = 0; j < 16; ++j) { + state[j] = inv_s[state[j]]; + state[j] ^= key[j]; + } + return state; + } + function encrypt128(input, key) { + var t, u, v, k; + var state = new Uint8Array(16); + state.set(input); + for (j = 0; j < 16; ++j) { + state[j] ^= key[j]; + } + for (i = 1; i < 10; i++) { + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + for (var j = 0; j < 16; j += 4) { + var s0 = state[j + 0], s1 = state[j + 1]; + var s2 = state[j + 2], s3 = state[j + 3]; + t = s0 ^ s1 ^ s2 ^ s3; + state[j + 0] ^= t ^ mixCol[s0 ^ s1]; + state[j + 1] ^= t ^ mixCol[s1 ^ s2]; + state[j + 2] ^= t ^ mixCol[s2 ^ s3]; + state[j + 3] ^= t ^ mixCol[s3 ^ s0]; + } + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + } + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + for (j = 0, k = 160; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + return state; + } + function AES128Cipher(key) { + this.key = expandKey128(key); + this.buffer = new Uint8Array(16); + this.bufferPosition = 0; + } + function decryptBlock2(data, finalize) { + var i, j, ii, sourceLength = data.length, buffer = this.buffer, bufferLength = this.bufferPosition, result = [], iv = this.iv; + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + var plain = decrypt128(buffer, this.key); + for (j = 0; j < 16; ++j) { + plain[j] ^= iv[j]; + } + iv = buffer; + result.push(plain); + buffer = new Uint8Array(16); + bufferLength = 0; + } + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + var outputLength = 16 * result.length; + if (finalize) { + var lastBlock = result[result.length - 1]; + var psLen = lastBlock[15]; + if (psLen <= 16) { + for (i = 15, ii = 16 - psLen; i >= ii; --i) { + if (lastBlock[i] !== psLen) { + psLen = 0; + break; + } + } + outputLength -= psLen; + result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); + } + } + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + AES128Cipher.prototype = { + decryptBlock: function AES128Cipher_decryptBlock(data, finalize) { + var i, sourceLength = data.length; + var buffer = this.buffer, bufferLength = this.bufferPosition; + for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) { + buffer[bufferLength] = data[i]; + } + if (bufferLength < 16) { + this.bufferLength = bufferLength; + return new Uint8Array([]); + } + this.iv = buffer; + this.buffer = new Uint8Array(16); + this.bufferLength = 0; + this.decryptBlock = decryptBlock2; + return this.decryptBlock(data.subarray(16), finalize); + }, + encrypt: function AES128Cipher_encrypt(data, iv) { + var i, j, ii, sourceLength = data.length, buffer = this.buffer, bufferLength = this.bufferPosition, result = []; + if (!iv) { + iv = new Uint8Array(16); + } + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + for (j = 0; j < 16; ++j) { + buffer[j] ^= iv[j]; + } + var cipher = encrypt128(buffer, this.key); + iv = cipher; + result.push(cipher); + buffer = new Uint8Array(16); + bufferLength = 0; + } + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + var outputLength = 16 * result.length; + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + }; + return AES128Cipher; +}(); +var AES256Cipher = function AES256CipherClosure() { + var s = new Uint8Array([ + 0x63, + 0x7c, + 0x77, + 0x7b, + 0xf2, + 0x6b, + 0x6f, + 0xc5, + 0x30, + 0x01, + 0x67, + 0x2b, + 0xfe, + 0xd7, + 0xab, + 0x76, + 0xca, + 0x82, + 0xc9, + 0x7d, + 0xfa, + 0x59, + 0x47, + 0xf0, + 0xad, + 0xd4, + 0xa2, + 0xaf, + 0x9c, + 0xa4, + 0x72, + 0xc0, + 0xb7, + 0xfd, + 0x93, + 0x26, + 0x36, + 0x3f, + 0xf7, + 0xcc, + 0x34, + 0xa5, + 0xe5, + 0xf1, + 0x71, + 0xd8, + 0x31, + 0x15, + 0x04, + 0xc7, + 0x23, + 0xc3, + 0x18, + 0x96, + 0x05, + 0x9a, + 0x07, + 0x12, + 0x80, + 0xe2, + 0xeb, + 0x27, + 0xb2, + 0x75, + 0x09, + 0x83, + 0x2c, + 0x1a, + 0x1b, + 0x6e, + 0x5a, + 0xa0, + 0x52, + 0x3b, + 0xd6, + 0xb3, + 0x29, + 0xe3, + 0x2f, + 0x84, + 0x53, + 0xd1, + 0x00, + 0xed, + 0x20, + 0xfc, + 0xb1, + 0x5b, + 0x6a, + 0xcb, + 0xbe, + 0x39, + 0x4a, + 0x4c, + 0x58, + 0xcf, + 0xd0, + 0xef, + 0xaa, + 0xfb, + 0x43, + 0x4d, + 0x33, + 0x85, + 0x45, + 0xf9, + 0x02, + 0x7f, + 0x50, + 0x3c, + 0x9f, + 0xa8, + 0x51, + 0xa3, + 0x40, + 0x8f, + 0x92, + 0x9d, + 0x38, + 0xf5, + 0xbc, + 0xb6, + 0xda, + 0x21, + 0x10, + 0xff, + 0xf3, + 0xd2, + 0xcd, + 0x0c, + 0x13, + 0xec, + 0x5f, + 0x97, + 0x44, + 0x17, + 0xc4, + 0xa7, + 0x7e, + 0x3d, + 0x64, + 0x5d, + 0x19, + 0x73, + 0x60, + 0x81, + 0x4f, + 0xdc, + 0x22, + 0x2a, + 0x90, + 0x88, + 0x46, + 0xee, + 0xb8, + 0x14, + 0xde, + 0x5e, + 0x0b, + 0xdb, + 0xe0, + 0x32, + 0x3a, + 0x0a, + 0x49, + 0x06, + 0x24, + 0x5c, + 0xc2, + 0xd3, + 0xac, + 0x62, + 0x91, + 0x95, + 0xe4, + 0x79, + 0xe7, + 0xc8, + 0x37, + 0x6d, + 0x8d, + 0xd5, + 0x4e, + 0xa9, + 0x6c, + 0x56, + 0xf4, + 0xea, + 0x65, + 0x7a, + 0xae, + 0x08, + 0xba, + 0x78, + 0x25, + 0x2e, + 0x1c, + 0xa6, + 0xb4, + 0xc6, + 0xe8, + 0xdd, + 0x74, + 0x1f, + 0x4b, + 0xbd, + 0x8b, + 0x8a, + 0x70, + 0x3e, + 0xb5, + 0x66, + 0x48, + 0x03, + 0xf6, + 0x0e, + 0x61, + 0x35, + 0x57, + 0xb9, + 0x86, + 0xc1, + 0x1d, + 0x9e, + 0xe1, + 0xf8, + 0x98, + 0x11, + 0x69, + 0xd9, + 0x8e, + 0x94, + 0x9b, + 0x1e, + 0x87, + 0xe9, + 0xce, + 0x55, + 0x28, + 0xdf, + 0x8c, + 0xa1, + 0x89, + 0x0d, + 0xbf, + 0xe6, + 0x42, + 0x68, + 0x41, + 0x99, + 0x2d, + 0x0f, + 0xb0, + 0x54, + 0xbb, + 0x16 + ]); + var inv_s = new Uint8Array([ + 0x52, + 0x09, + 0x6a, + 0xd5, + 0x30, + 0x36, + 0xa5, + 0x38, + 0xbf, + 0x40, + 0xa3, + 0x9e, + 0x81, + 0xf3, + 0xd7, + 0xfb, + 0x7c, + 0xe3, + 0x39, + 0x82, + 0x9b, + 0x2f, + 0xff, + 0x87, + 0x34, + 0x8e, + 0x43, + 0x44, + 0xc4, + 0xde, + 0xe9, + 0xcb, + 0x54, + 0x7b, + 0x94, + 0x32, + 0xa6, + 0xc2, + 0x23, + 0x3d, + 0xee, + 0x4c, + 0x95, + 0x0b, + 0x42, + 0xfa, + 0xc3, + 0x4e, + 0x08, + 0x2e, + 0xa1, + 0x66, + 0x28, + 0xd9, + 0x24, + 0xb2, + 0x76, + 0x5b, + 0xa2, + 0x49, + 0x6d, + 0x8b, + 0xd1, + 0x25, + 0x72, + 0xf8, + 0xf6, + 0x64, + 0x86, + 0x68, + 0x98, + 0x16, + 0xd4, + 0xa4, + 0x5c, + 0xcc, + 0x5d, + 0x65, + 0xb6, + 0x92, + 0x6c, + 0x70, + 0x48, + 0x50, + 0xfd, + 0xed, + 0xb9, + 0xda, + 0x5e, + 0x15, + 0x46, + 0x57, + 0xa7, + 0x8d, + 0x9d, + 0x84, + 0x90, + 0xd8, + 0xab, + 0x00, + 0x8c, + 0xbc, + 0xd3, + 0x0a, + 0xf7, + 0xe4, + 0x58, + 0x05, + 0xb8, + 0xb3, + 0x45, + 0x06, + 0xd0, + 0x2c, + 0x1e, + 0x8f, + 0xca, + 0x3f, + 0x0f, + 0x02, + 0xc1, + 0xaf, + 0xbd, + 0x03, + 0x01, + 0x13, + 0x8a, + 0x6b, + 0x3a, + 0x91, + 0x11, + 0x41, + 0x4f, + 0x67, + 0xdc, + 0xea, + 0x97, + 0xf2, + 0xcf, + 0xce, + 0xf0, + 0xb4, + 0xe6, + 0x73, + 0x96, + 0xac, + 0x74, + 0x22, + 0xe7, + 0xad, + 0x35, + 0x85, + 0xe2, + 0xf9, + 0x37, + 0xe8, + 0x1c, + 0x75, + 0xdf, + 0x6e, + 0x47, + 0xf1, + 0x1a, + 0x71, + 0x1d, + 0x29, + 0xc5, + 0x89, + 0x6f, + 0xb7, + 0x62, + 0x0e, + 0xaa, + 0x18, + 0xbe, + 0x1b, + 0xfc, + 0x56, + 0x3e, + 0x4b, + 0xc6, + 0xd2, + 0x79, + 0x20, + 0x9a, + 0xdb, + 0xc0, + 0xfe, + 0x78, + 0xcd, + 0x5a, + 0xf4, + 0x1f, + 0xdd, + 0xa8, + 0x33, + 0x88, + 0x07, + 0xc7, + 0x31, + 0xb1, + 0x12, + 0x10, + 0x59, + 0x27, + 0x80, + 0xec, + 0x5f, + 0x60, + 0x51, + 0x7f, + 0xa9, + 0x19, + 0xb5, + 0x4a, + 0x0d, + 0x2d, + 0xe5, + 0x7a, + 0x9f, + 0x93, + 0xc9, + 0x9c, + 0xef, + 0xa0, + 0xe0, + 0x3b, + 0x4d, + 0xae, + 0x2a, + 0xf5, + 0xb0, + 0xc8, + 0xeb, + 0xbb, + 0x3c, + 0x83, + 0x53, + 0x99, + 0x61, + 0x17, + 0x2b, + 0x04, + 0x7e, + 0xba, + 0x77, + 0xd6, + 0x26, + 0xe1, + 0x69, + 0x14, + 0x63, + 0x55, + 0x21, + 0x0c, + 0x7d + ]); + var mixCol = new Uint8Array(256); + for (var i = 0; i < 256; i++) { + if (i < 128) { + mixCol[i] = i << 1; + } else { + mixCol[i] = i << 1 ^ 0x1b; + } + } + var mix = new Uint32Array([ + 0x00000000, + 0x0e090d0b, + 0x1c121a16, + 0x121b171d, + 0x3824342c, + 0x362d3927, + 0x24362e3a, + 0x2a3f2331, + 0x70486858, + 0x7e416553, + 0x6c5a724e, + 0x62537f45, + 0x486c5c74, + 0x4665517f, + 0x547e4662, + 0x5a774b69, + 0xe090d0b0, + 0xee99ddbb, + 0xfc82caa6, + 0xf28bc7ad, + 0xd8b4e49c, + 0xd6bde997, + 0xc4a6fe8a, + 0xcaaff381, + 0x90d8b8e8, + 0x9ed1b5e3, + 0x8ccaa2fe, + 0x82c3aff5, + 0xa8fc8cc4, + 0xa6f581cf, + 0xb4ee96d2, + 0xbae79bd9, + 0xdb3bbb7b, + 0xd532b670, + 0xc729a16d, + 0xc920ac66, + 0xe31f8f57, + 0xed16825c, + 0xff0d9541, + 0xf104984a, + 0xab73d323, + 0xa57ade28, + 0xb761c935, + 0xb968c43e, + 0x9357e70f, + 0x9d5eea04, + 0x8f45fd19, + 0x814cf012, + 0x3bab6bcb, + 0x35a266c0, + 0x27b971dd, + 0x29b07cd6, + 0x038f5fe7, + 0x0d8652ec, + 0x1f9d45f1, + 0x119448fa, + 0x4be30393, + 0x45ea0e98, + 0x57f11985, + 0x59f8148e, + 0x73c737bf, + 0x7dce3ab4, + 0x6fd52da9, + 0x61dc20a2, + 0xad766df6, + 0xa37f60fd, + 0xb16477e0, + 0xbf6d7aeb, + 0x955259da, + 0x9b5b54d1, + 0x894043cc, + 0x87494ec7, + 0xdd3e05ae, + 0xd33708a5, + 0xc12c1fb8, + 0xcf2512b3, + 0xe51a3182, + 0xeb133c89, + 0xf9082b94, + 0xf701269f, + 0x4de6bd46, + 0x43efb04d, + 0x51f4a750, + 0x5ffdaa5b, + 0x75c2896a, + 0x7bcb8461, + 0x69d0937c, + 0x67d99e77, + 0x3daed51e, + 0x33a7d815, + 0x21bccf08, + 0x2fb5c203, + 0x058ae132, + 0x0b83ec39, + 0x1998fb24, + 0x1791f62f, + 0x764dd68d, + 0x7844db86, + 0x6a5fcc9b, + 0x6456c190, + 0x4e69e2a1, + 0x4060efaa, + 0x527bf8b7, + 0x5c72f5bc, + 0x0605bed5, + 0x080cb3de, + 0x1a17a4c3, + 0x141ea9c8, + 0x3e218af9, + 0x302887f2, + 0x223390ef, + 0x2c3a9de4, + 0x96dd063d, + 0x98d40b36, + 0x8acf1c2b, + 0x84c61120, + 0xaef93211, + 0xa0f03f1a, + 0xb2eb2807, + 0xbce2250c, + 0xe6956e65, + 0xe89c636e, + 0xfa877473, + 0xf48e7978, + 0xdeb15a49, + 0xd0b85742, + 0xc2a3405f, + 0xccaa4d54, + 0x41ecdaf7, + 0x4fe5d7fc, + 0x5dfec0e1, + 0x53f7cdea, + 0x79c8eedb, + 0x77c1e3d0, + 0x65daf4cd, + 0x6bd3f9c6, + 0x31a4b2af, + 0x3fadbfa4, + 0x2db6a8b9, + 0x23bfa5b2, + 0x09808683, + 0x07898b88, + 0x15929c95, + 0x1b9b919e, + 0xa17c0a47, + 0xaf75074c, + 0xbd6e1051, + 0xb3671d5a, + 0x99583e6b, + 0x97513360, + 0x854a247d, + 0x8b432976, + 0xd134621f, + 0xdf3d6f14, + 0xcd267809, + 0xc32f7502, + 0xe9105633, + 0xe7195b38, + 0xf5024c25, + 0xfb0b412e, + 0x9ad7618c, + 0x94de6c87, + 0x86c57b9a, + 0x88cc7691, + 0xa2f355a0, + 0xacfa58ab, + 0xbee14fb6, + 0xb0e842bd, + 0xea9f09d4, + 0xe49604df, + 0xf68d13c2, + 0xf8841ec9, + 0xd2bb3df8, + 0xdcb230f3, + 0xcea927ee, + 0xc0a02ae5, + 0x7a47b13c, + 0x744ebc37, + 0x6655ab2a, + 0x685ca621, + 0x42638510, + 0x4c6a881b, + 0x5e719f06, + 0x5078920d, + 0x0a0fd964, + 0x0406d46f, + 0x161dc372, + 0x1814ce79, + 0x322bed48, + 0x3c22e043, + 0x2e39f75e, + 0x2030fa55, + 0xec9ab701, + 0xe293ba0a, + 0xf088ad17, + 0xfe81a01c, + 0xd4be832d, + 0xdab78e26, + 0xc8ac993b, + 0xc6a59430, + 0x9cd2df59, + 0x92dbd252, + 0x80c0c54f, + 0x8ec9c844, + 0xa4f6eb75, + 0xaaffe67e, + 0xb8e4f163, + 0xb6edfc68, + 0x0c0a67b1, + 0x02036aba, + 0x10187da7, + 0x1e1170ac, + 0x342e539d, + 0x3a275e96, + 0x283c498b, + 0x26354480, + 0x7c420fe9, + 0x724b02e2, + 0x605015ff, + 0x6e5918f4, + 0x44663bc5, + 0x4a6f36ce, + 0x587421d3, + 0x567d2cd8, + 0x37a10c7a, + 0x39a80171, + 0x2bb3166c, + 0x25ba1b67, + 0x0f853856, + 0x018c355d, + 0x13972240, + 0x1d9e2f4b, + 0x47e96422, + 0x49e06929, + 0x5bfb7e34, + 0x55f2733f, + 0x7fcd500e, + 0x71c45d05, + 0x63df4a18, + 0x6dd64713, + 0xd731dcca, + 0xd938d1c1, + 0xcb23c6dc, + 0xc52acbd7, + 0xef15e8e6, + 0xe11ce5ed, + 0xf307f2f0, + 0xfd0efffb, + 0xa779b492, + 0xa970b999, + 0xbb6bae84, + 0xb562a38f, + 0x9f5d80be, + 0x91548db5, + 0x834f9aa8, + 0x8d4697a3 + ]); + function expandKey256(cipherKey) { + var b = 240, result = new Uint8Array(b); + var r = 1; + result.set(cipherKey); + for (var j = 32, i = 1; j < b; ++i) { + if (j % 32 === 16) { + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + } else if (j % 32 === 0) { + var t1 = result[j - 3], t2 = result[j - 2], t3 = result[j - 1], t4 = result[j - 4]; + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + t1 = t1 ^ r; + if ((r <<= 1) >= 256) { + r = (r ^ 0x1b) & 0xFF; + } + } + for (var n = 0; n < 4; ++n) { + result[j] = t1 ^= result[j - 32]; + j++; + result[j] = t2 ^= result[j - 32]; + j++; + result[j] = t3 ^= result[j - 32]; + j++; + result[j] = t4 ^= result[j - 32]; + j++; + } + } + return result; + } + function decrypt256(input, key) { + var state = new Uint8Array(16); + state.set(input); + var i, j, k; + var t, u, v; + for (j = 0, k = 224; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (i = 13; i >= 1; --i) { + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (j = 0; j < 16; ++j) { + state[j] = inv_s[state[j]]; + } + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (j = 0; j < 16; j += 4) { + var s0 = mix[state[j]], s1 = mix[state[j + 1]], s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; + t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8; + state[j] = t >>> 24 & 0xFF; + state[j + 1] = t >> 16 & 0xFF; + state[j + 2] = t >> 8 & 0xFF; + state[j + 3] = t & 0xFF; + } + } + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (j = 0; j < 16; ++j) { + state[j] = inv_s[state[j]]; + state[j] ^= key[j]; + } + return state; + } + function encrypt256(input, key) { + var t, u, v, k; + var state = new Uint8Array(16); + state.set(input); + for (j = 0; j < 16; ++j) { + state[j] ^= key[j]; + } + for (i = 1; i < 14; i++) { + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + for (var j = 0; j < 16; j += 4) { + var s0 = state[j + 0], s1 = state[j + 1]; + var s2 = state[j + 2], s3 = state[j + 3]; + t = s0 ^ s1 ^ s2 ^ s3; + state[j + 0] ^= t ^ mixCol[s0 ^ s1]; + state[j + 1] ^= t ^ mixCol[s1 ^ s2]; + state[j + 2] ^= t ^ mixCol[s2 ^ s3]; + state[j + 3] ^= t ^ mixCol[s3 ^ s0]; + } + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + } + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + for (j = 0, k = 224; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + return state; + } + function AES256Cipher(key) { + this.key = expandKey256(key); + this.buffer = new Uint8Array(16); + this.bufferPosition = 0; + } + function decryptBlock2(data, finalize) { + var i, j, ii, sourceLength = data.length, buffer = this.buffer, bufferLength = this.bufferPosition, result = [], iv = this.iv; + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + var plain = decrypt256(buffer, this.key); + for (j = 0; j < 16; ++j) { + plain[j] ^= iv[j]; + } + iv = buffer; + result.push(plain); + buffer = new Uint8Array(16); + bufferLength = 0; + } + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + var outputLength = 16 * result.length; + if (finalize) { + var lastBlock = result[result.length - 1]; + var psLen = lastBlock[15]; + if (psLen <= 16) { + for (i = 15, ii = 16 - psLen; i >= ii; --i) { + if (lastBlock[i] !== psLen) { + psLen = 0; + break; + } + } + outputLength -= psLen; + result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); + } + } + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + AES256Cipher.prototype = { + decryptBlock: function AES256Cipher_decryptBlock(data, finalize, iv) { + var i, sourceLength = data.length; + var buffer = this.buffer, bufferLength = this.bufferPosition; + if (iv) { + this.iv = iv; + } else { + for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) { + buffer[bufferLength] = data[i]; + } + if (bufferLength < 16) { + this.bufferLength = bufferLength; + return new Uint8Array([]); + } + this.iv = buffer; + data = data.subarray(16); + } + this.buffer = new Uint8Array(16); + this.bufferLength = 0; + this.decryptBlock = decryptBlock2; + return this.decryptBlock(data, finalize); + }, + encrypt: function AES256Cipher_encrypt(data, iv) { + var i, j, ii, sourceLength = data.length, buffer = this.buffer, bufferLength = this.bufferPosition, result = []; + if (!iv) { + iv = new Uint8Array(16); + } + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + for (j = 0; j < 16; ++j) { + buffer[j] ^= iv[j]; + } + var cipher = encrypt256(buffer, this.key); + this.iv = cipher; + result.push(cipher); + buffer = new Uint8Array(16); + bufferLength = 0; + } + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + var outputLength = 16 * result.length; + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + }; + return AES256Cipher; +}(); +var PDF17 = function PDF17Closure() { + function compareByteArrays(array1, array2) { + if (array1.length !== array2.length) { + return false; + } + for (var i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + } + function PDF17() { + } + PDF17.prototype = { + checkOwnerPassword: function PDF17_checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerValidationSalt, password.length); + hashData.set(userBytes, password.length + ownerValidationSalt.length); + var result = calculateSHA256(hashData, 0, hashData.length); + return compareByteArrays(result, ownerPassword); + }, + checkUserPassword: function PDF17_checkUserPassword(password, userValidationSalt, userPassword) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userValidationSalt, password.length); + var result = calculateSHA256(hashData, 0, hashData.length); + return compareByteArrays(result, userPassword); + }, + getOwnerKey: function PDF17_getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerKeySalt, password.length); + hashData.set(userBytes, password.length + ownerKeySalt.length); + var key = calculateSHA256(hashData, 0, hashData.length); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16)); + }, + getUserKey: function PDF17_getUserKey(password, userKeySalt, userEncryption) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userKeySalt, password.length); + var key = calculateSHA256(hashData, 0, hashData.length); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(userEncryption, false, new Uint8Array(16)); + } + }; + return PDF17; +}(); +var PDF20 = function PDF20Closure() { + function concatArrays(array1, array2) { + var t = new Uint8Array(array1.length + array2.length); + t.set(array1, 0); + t.set(array2, array1.length); + return t; + } + function calculatePDF20Hash(password, input, userBytes) { + var k = calculateSHA256(input, 0, input.length).subarray(0, 32); + var e = [0]; + var i = 0; + while (i < 64 || e[e.length - 1] > i - 32) { + var arrayLength = password.length + k.length + userBytes.length; + var k1 = new Uint8Array(arrayLength * 64); + var array = concatArrays(password, k); + array = concatArrays(array, userBytes); + for (var j = 0, pos = 0; j < 64; j++, pos += arrayLength) { + k1.set(array, pos); + } + var cipher = new AES128Cipher(k.subarray(0, 16)); + e = cipher.encrypt(k1, k.subarray(16, 32)); + var remainder = 0; + for (var z = 0; z < 16; z++) { + remainder *= 256 % 3; + remainder %= 3; + remainder += (e[z] >>> 0) % 3; + remainder %= 3; + } + if (remainder === 0) { + k = calculateSHA256(e, 0, e.length); + } else if (remainder === 1) { + k = calculateSHA384(e, 0, e.length); + } else if (remainder === 2) { + k = calculateSHA512(e, 0, e.length); + } + i++; + } + return k.subarray(0, 32); + } + function PDF20() { + } + function compareByteArrays(array1, array2) { + if (array1.length !== array2.length) { + return false; + } + for (var i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + } + PDF20.prototype = { + hash: function PDF20_hash(password, concatBytes, userBytes) { + return calculatePDF20Hash(password, concatBytes, userBytes); + }, + checkOwnerPassword: function PDF20_checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerValidationSalt, password.length); + hashData.set(userBytes, password.length + ownerValidationSalt.length); + var result = calculatePDF20Hash(password, hashData, userBytes); + return compareByteArrays(result, ownerPassword); + }, + checkUserPassword: function PDF20_checkUserPassword(password, userValidationSalt, userPassword) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userValidationSalt, password.length); + var result = calculatePDF20Hash(password, hashData, []); + return compareByteArrays(result, userPassword); + }, + getOwnerKey: function PDF20_getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerKeySalt, password.length); + hashData.set(userBytes, password.length + ownerKeySalt.length); + var key = calculatePDF20Hash(password, hashData, userBytes); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16)); + }, + getUserKey: function PDF20_getUserKey(password, userKeySalt, userEncryption) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userKeySalt, password.length); + var key = calculatePDF20Hash(password, hashData, []); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(userEncryption, false, new Uint8Array(16)); + } + }; + return PDF20; +}(); +var CipherTransform = function CipherTransformClosure() { + function CipherTransform(stringCipherConstructor, streamCipherConstructor) { + this.StringCipherConstructor = stringCipherConstructor; + this.StreamCipherConstructor = streamCipherConstructor; + } + CipherTransform.prototype = { + createStream: function CipherTransform_createStream(stream, length) { + var cipher = new this.StreamCipherConstructor(); + return new DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize) { + return cipher.decryptBlock(data, finalize); + }); + }, + decryptString: function CipherTransform_decryptString(s) { + var cipher = new this.StringCipherConstructor(); + var data = stringToBytes(s); + data = cipher.decryptBlock(data, true); + return bytesToString(data); + } + }; + return CipherTransform; +}(); +var CipherTransformFactory = function CipherTransformFactoryClosure() { + var defaultPasswordBytes = new Uint8Array([ + 0x28, + 0xBF, + 0x4E, + 0x5E, + 0x4E, + 0x75, + 0x8A, + 0x41, + 0x64, + 0x00, + 0x4E, + 0x56, + 0xFF, + 0xFA, + 0x01, + 0x08, + 0x2E, + 0x2E, + 0x00, + 0xB6, + 0xD0, + 0x68, + 0x3E, + 0x80, + 0x2F, + 0x0C, + 0xA9, + 0xFE, + 0x64, + 0x53, + 0x69, + 0x7A + ]); + function createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) { + if (password) { + var passwordLength = Math.min(127, password.length); + password = password.subarray(0, passwordLength); + } else { + password = []; + } + var pdfAlgorithm; + if (revision === 6) { + pdfAlgorithm = new PDF20(); + } else { + pdfAlgorithm = new PDF17(); + } + if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) { + return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption); + } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) { + return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption); + } + return null; + } + function prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) { + var hashDataSize = 40 + ownerPassword.length + fileId.length; + var hashData = new Uint8Array(hashDataSize), i = 0, j, n; + if (password) { + n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + } + j = 0; + while (i < 32) { + hashData[i++] = defaultPasswordBytes[j++]; + } + for (j = 0, n = ownerPassword.length; j < n; ++j) { + hashData[i++] = ownerPassword[j]; + } + hashData[i++] = flags & 0xFF; + hashData[i++] = flags >> 8 & 0xFF; + hashData[i++] = flags >> 16 & 0xFF; + hashData[i++] = flags >>> 24 & 0xFF; + for (j = 0, n = fileId.length; j < n; ++j) { + hashData[i++] = fileId[j]; + } + if (revision >= 4 && !encryptMetadata) { + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + } + var hash = calculateMD5(hashData, 0, i); + var keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, keyLengthInBytes); + } + } + var encryptionKey = hash.subarray(0, keyLengthInBytes); + var cipher, checkData; + if (revision >= 3) { + for (i = 0; i < 32; ++i) { + hashData[i] = defaultPasswordBytes[i]; + } + for (j = 0, n = fileId.length; j < n; ++j) { + hashData[i++] = fileId[j]; + } + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i)); + n = encryptionKey.length; + var derivedKey = new Uint8Array(n), k; + for (j = 1; j <= 19; ++j) { + for (k = 0; k < n; ++k) { + derivedKey[k] = encryptionKey[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + checkData = cipher.encryptBlock(checkData); + } + for (j = 0, n = checkData.length; j < n; ++j) { + if (userPassword[j] !== checkData[j]) { + return null; + } + } + } else { + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(defaultPasswordBytes); + for (j = 0, n = checkData.length; j < n; ++j) { + if (userPassword[j] !== checkData[j]) { + return null; + } + } + } + return encryptionKey; + } + function decodeUserPassword(password, ownerPassword, revision, keyLength) { + var hashData = new Uint8Array(32), i = 0, j, n; + n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + j = 0; + while (i < 32) { + hashData[i++] = defaultPasswordBytes[j++]; + } + var hash = calculateMD5(hashData, 0, i); + var keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, hash.length); + } + } + var cipher, userPassword; + if (revision >= 3) { + userPassword = ownerPassword; + var derivedKey = new Uint8Array(keyLengthInBytes), k; + for (j = 19; j >= 0; j--) { + for (k = 0; k < keyLengthInBytes; ++k) { + derivedKey[k] = hash[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + userPassword = cipher.encryptBlock(userPassword); + } + } else { + cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes)); + userPassword = cipher.encryptBlock(ownerPassword); + } + return userPassword; + } + var identityName = Name.get('Identity'); + function CipherTransformFactory(dict, fileId, password) { + var filter = dict.get('Filter'); + if (!isName(filter, 'Standard')) { + error('unknown encryption method'); + } + this.dict = dict; + var algorithm = dict.get('V'); + if (!isInt(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) { + error('unsupported encryption algorithm'); + } + this.algorithm = algorithm; + var keyLength = dict.get('Length'); + if (!keyLength) { + if (algorithm <= 3) { + keyLength = 40; + } else { + var cfDict = dict.get('CF'); + var streamCryptoName = dict.get('StmF'); + if (isDict(cfDict) && isName(streamCryptoName)) { + cfDict.suppressEncryption = true; + var handlerDict = cfDict.get(streamCryptoName.name); + keyLength = handlerDict && handlerDict.get('Length') || 128; + if (keyLength < 40) { + keyLength <<= 3; + } + } + } + } + if (!isInt(keyLength) || keyLength < 40 || keyLength % 8 !== 0) { + error('invalid key length'); + } + var ownerPassword = stringToBytes(dict.get('O')).subarray(0, 32); + var userPassword = stringToBytes(dict.get('U')).subarray(0, 32); + var flags = dict.get('P'); + var revision = dict.get('R'); + var encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get('EncryptMetadata') !== false; + this.encryptMetadata = encryptMetadata; + var fileIdBytes = stringToBytes(fileId); + var passwordBytes; + if (password) { + if (revision === 6) { + try { + password = utf8StringToString(password); + } catch (ex) { + warn('CipherTransformFactory: ' + 'Unable to convert UTF8 encoded password.'); + } + } + passwordBytes = stringToBytes(password); + } + var encryptionKey; + if (algorithm !== 5) { + encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); + } else { + var ownerValidationSalt = stringToBytes(dict.get('O')).subarray(32, 40); + var ownerKeySalt = stringToBytes(dict.get('O')).subarray(40, 48); + var uBytes = stringToBytes(dict.get('U')).subarray(0, 48); + var userValidationSalt = stringToBytes(dict.get('U')).subarray(32, 40); + var userKeySalt = stringToBytes(dict.get('U')).subarray(40, 48); + var ownerEncryption = stringToBytes(dict.get('OE')); + var userEncryption = stringToBytes(dict.get('UE')); + var perms = stringToBytes(dict.get('Perms')); + encryptionKey = createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms); + } + if (!encryptionKey && !password) { + throw new PasswordException('No password given', PasswordResponses.NEED_PASSWORD); + } else if (!encryptionKey && password) { + var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength); + encryptionKey = prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); + } + if (!encryptionKey) { + throw new PasswordException('Incorrect Password', PasswordResponses.INCORRECT_PASSWORD); + } + this.encryptionKey = encryptionKey; + if (algorithm >= 4) { + var cf = dict.get('CF'); + if (isDict(cf)) { + cf.suppressEncryption = true; + } + this.cf = cf; + this.stmf = dict.get('StmF') || identityName; + this.strf = dict.get('StrF') || identityName; + this.eff = dict.get('EFF') || this.stmf; + } + } + function buildObjectKey(num, gen, encryptionKey, isAes) { + var key = new Uint8Array(encryptionKey.length + 9), i, n; + for (i = 0, n = encryptionKey.length; i < n; ++i) { + key[i] = encryptionKey[i]; + } + key[i++] = num & 0xFF; + key[i++] = num >> 8 & 0xFF; + key[i++] = num >> 16 & 0xFF; + key[i++] = gen & 0xFF; + key[i++] = gen >> 8 & 0xFF; + if (isAes) { + key[i++] = 0x73; + key[i++] = 0x41; + key[i++] = 0x6C; + key[i++] = 0x54; + } + var hash = calculateMD5(key, 0, i); + return hash.subarray(0, Math.min(encryptionKey.length + 5, 16)); + } + function buildCipherConstructor(cf, name, num, gen, key) { + assert(isName(name), 'Invalid crypt filter name.'); + var cryptFilter = cf.get(name.name); + var cfm; + if (cryptFilter !== null && cryptFilter !== undefined) { + cfm = cryptFilter.get('CFM'); + } + if (!cfm || cfm.name === 'None') { + return function cipherTransformFactoryBuildCipherConstructorNone() { + return new NullCipher(); + }; + } + if (cfm.name === 'V2') { + return function cipherTransformFactoryBuildCipherConstructorV2() { + return new ARCFourCipher(buildObjectKey(num, gen, key, false)); + }; + } + if (cfm.name === 'AESV2') { + return function cipherTransformFactoryBuildCipherConstructorAESV2() { + return new AES128Cipher(buildObjectKey(num, gen, key, true)); + }; + } + if (cfm.name === 'AESV3') { + return function cipherTransformFactoryBuildCipherConstructorAESV3() { + return new AES256Cipher(key); + }; + } + error('Unknown crypto method'); + } + CipherTransformFactory.prototype = { + createCipherTransform: function CipherTransformFactory_createCipherTransform(num, gen) { + if (this.algorithm === 4 || this.algorithm === 5) { + return new CipherTransform(buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey), buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey)); + } + var key = buildObjectKey(num, gen, this.encryptionKey, false); + var cipherConstructor = function buildCipherCipherConstructor() { + return new ARCFourCipher(key); + }; + return new CipherTransform(cipherConstructor, cipherConstructor); + } + }; + return CipherTransformFactory; +}(); +exports.AES128Cipher = AES128Cipher; +exports.AES256Cipher = AES256Cipher; +exports.ARCFourCipher = ARCFourCipher; +exports.CipherTransformFactory = CipherTransformFactory; +exports.PDF17 = PDF17; +exports.PDF20 = PDF20; +exports.calculateMD5 = calculateMD5; +exports.calculateSHA256 = calculateSHA256; +exports.calculateSHA384 = calculateSHA384; +exports.calculateSHA512 = calculateSHA512; + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreStream = __w_pdfjs_require__(2); +var coreParser = __w_pdfjs_require__(5); +var coreImage = __w_pdfjs_require__(27); +var coreColorSpace = __w_pdfjs_require__(3); +var coreMurmurHash3 = __w_pdfjs_require__(31); +var coreFonts = __w_pdfjs_require__(26); +var coreFunction = __w_pdfjs_require__(6); +var corePattern = __w_pdfjs_require__(32); +var coreCMap = __w_pdfjs_require__(23); +var coreMetrics = __w_pdfjs_require__(30); +var coreBidi = __w_pdfjs_require__(21); +var coreEncodings = __w_pdfjs_require__(4); +var coreStandardFonts = __w_pdfjs_require__(17); +var coreUnicode = __w_pdfjs_require__(18); +var coreGlyphList = __w_pdfjs_require__(7); +var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX; +var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX; +var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES; +var ImageKind = sharedUtil.ImageKind; +var OPS = sharedUtil.OPS; +var TextRenderingMode = sharedUtil.TextRenderingMode; +var CMapCompressionType = sharedUtil.CMapCompressionType; +var Util = sharedUtil.Util; +var assert = sharedUtil.assert; +var createPromiseCapability = sharedUtil.createPromiseCapability; +var error = sharedUtil.error; +var info = sharedUtil.info; +var isArray = sharedUtil.isArray; +var isNum = sharedUtil.isNum; +var isString = sharedUtil.isString; +var getLookupTableFactory = sharedUtil.getLookupTableFactory; +var warn = sharedUtil.warn; +var Dict = corePrimitives.Dict; +var Name = corePrimitives.Name; +var isEOF = corePrimitives.isEOF; +var isCmd = corePrimitives.isCmd; +var isDict = corePrimitives.isDict; +var isName = corePrimitives.isName; +var isRef = corePrimitives.isRef; +var isStream = corePrimitives.isStream; +var DecodeStream = coreStream.DecodeStream; +var JpegStream = coreStream.JpegStream; +var Stream = coreStream.Stream; +var Lexer = coreParser.Lexer; +var Parser = coreParser.Parser; +var PDFImage = coreImage.PDFImage; +var ColorSpace = coreColorSpace.ColorSpace; +var MurmurHash3_64 = coreMurmurHash3.MurmurHash3_64; +var ErrorFont = coreFonts.ErrorFont; +var FontFlags = coreFonts.FontFlags; +var Font = coreFonts.Font; +var IdentityToUnicodeMap = coreFonts.IdentityToUnicodeMap; +var ToUnicodeMap = coreFonts.ToUnicodeMap; +var getFontType = coreFonts.getFontType; +var isPDFFunction = coreFunction.isPDFFunction; +var PDFFunction = coreFunction.PDFFunction; +var Pattern = corePattern.Pattern; +var getTilingPatternIR = corePattern.getTilingPatternIR; +var CMapFactory = coreCMap.CMapFactory; +var IdentityCMap = coreCMap.IdentityCMap; +var getMetrics = coreMetrics.getMetrics; +var bidi = coreBidi.bidi; +var WinAnsiEncoding = coreEncodings.WinAnsiEncoding; +var StandardEncoding = coreEncodings.StandardEncoding; +var MacRomanEncoding = coreEncodings.MacRomanEncoding; +var SymbolSetEncoding = coreEncodings.SymbolSetEncoding; +var ZapfDingbatsEncoding = coreEncodings.ZapfDingbatsEncoding; +var getEncoding = coreEncodings.getEncoding; +var getStdFontMap = coreStandardFonts.getStdFontMap; +var getSerifFonts = coreStandardFonts.getSerifFonts; +var getSymbolsFonts = coreStandardFonts.getSymbolsFonts; +var getNormalizedUnicodes = coreUnicode.getNormalizedUnicodes; +var reverseIfRtl = coreUnicode.reverseIfRtl; +var getUnicodeForGlyph = coreUnicode.getUnicodeForGlyph; +var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode; +var PartialEvaluator = function PartialEvaluatorClosure() { + var DefaultPartialEvaluatorOptions = { + forceDataSchema: false, + maxImageSize: -1, + disableFontFace: false, + disableNativeImageDecoder: false + }; + function NativeImageDecoder(xref, resources, handler, forceDataSchema) { + this.xref = xref; + this.resources = resources; + this.handler = handler; + this.forceDataSchema = forceDataSchema; + } + NativeImageDecoder.prototype = { + canDecode: function (image) { + return image instanceof JpegStream && NativeImageDecoder.isDecodable(image, this.xref, this.resources); + }, + decode: function (image) { + var dict = image.dict; + var colorSpace = dict.get('ColorSpace', 'CS'); + colorSpace = ColorSpace.parse(colorSpace, this.xref, this.resources); + var numComps = colorSpace.numComps; + var decodePromise = this.handler.sendWithPromise('JpegDecode', [ + image.getIR(this.forceDataSchema), + numComps + ]); + return decodePromise.then(function (message) { + var data = message.data; + return new Stream(data, 0, data.length, image.dict); + }); + } + }; + NativeImageDecoder.isSupported = function NativeImageDecoder_isSupported(image, xref, res) { + var dict = image.dict; + if (dict.has('DecodeParms') || dict.has('DP')) { + return false; + } + var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res); + return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') && cs.isDefaultDecode(dict.getArray('Decode', 'D')); + }; + NativeImageDecoder.isDecodable = function NativeImageDecoder_isDecodable(image, xref, res) { + var dict = image.dict; + if (dict.has('DecodeParms') || dict.has('DP')) { + return false; + } + var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res); + return (cs.numComps === 1 || cs.numComps === 3) && cs.isDefaultDecode(dict.getArray('Decode', 'D')); + }; + function PartialEvaluator(pdfManager, xref, handler, pageIndex, idFactory, fontCache, builtInCMapCache, options) { + this.pdfManager = pdfManager; + this.xref = xref; + this.handler = handler; + this.pageIndex = pageIndex; + this.idFactory = idFactory; + this.fontCache = fontCache; + this.builtInCMapCache = builtInCMapCache; + this.options = options || DefaultPartialEvaluatorOptions; + this.fetchBuiltInCMap = function (name) { + var cachedCMap = builtInCMapCache[name]; + if (cachedCMap) { + return Promise.resolve(cachedCMap); + } + return handler.sendWithPromise('FetchBuiltInCMap', { name: name }).then(function (data) { + if (data.compressionType !== CMapCompressionType.NONE) { + builtInCMapCache[name] = data; + } + return data; + }); + }; + } + var TIME_SLOT_DURATION_MS = 20; + var CHECK_TIME_EVERY = 100; + function TimeSlotManager() { + this.reset(); + } + TimeSlotManager.prototype = { + check: function TimeSlotManager_check() { + if (++this.checked < CHECK_TIME_EVERY) { + return false; + } + this.checked = 0; + return this.endTime <= Date.now(); + }, + reset: function TimeSlotManager_reset() { + this.endTime = Date.now() + TIME_SLOT_DURATION_MS; + this.checked = 0; + } + }; + var deferred = Promise.resolve(); + var TILING_PATTERN = 1, SHADING_PATTERN = 2; + PartialEvaluator.prototype = { + hasBlendModes: function PartialEvaluator_hasBlendModes(resources) { + if (!isDict(resources)) { + return false; + } + var processed = Object.create(null); + if (resources.objId) { + processed[resources.objId] = true; + } + var nodes = [resources], xref = this.xref; + while (nodes.length) { + var key, i, ii; + var node = nodes.shift(); + var graphicStates = node.get('ExtGState'); + if (isDict(graphicStates)) { + var graphicStatesKeys = graphicStates.getKeys(); + for (i = 0, ii = graphicStatesKeys.length; i < ii; i++) { + key = graphicStatesKeys[i]; + var graphicState = graphicStates.get(key); + var bm = graphicState.get('BM'); + if (isName(bm) && bm.name !== 'Normal') { + return true; + } + } + } + var xObjects = node.get('XObject'); + if (!isDict(xObjects)) { + continue; + } + var xObjectsKeys = xObjects.getKeys(); + for (i = 0, ii = xObjectsKeys.length; i < ii; i++) { + key = xObjectsKeys[i]; + var xObject = xObjects.getRaw(key); + if (isRef(xObject)) { + if (processed[xObject.toString()]) { + continue; + } + xObject = xref.fetch(xObject); + } + if (!isStream(xObject)) { + continue; + } + if (xObject.dict.objId) { + if (processed[xObject.dict.objId]) { + continue; + } + processed[xObject.dict.objId] = true; + } + var xResources = xObject.dict.get('Resources'); + if (isDict(xResources) && (!xResources.objId || !processed[xResources.objId])) { + nodes.push(xResources); + if (xResources.objId) { + processed[xResources.objId] = true; + } + } + } + } + return false; + }, + buildFormXObject: function PartialEvaluator_buildFormXObject(resources, xobj, smask, operatorList, task, initialState) { + var matrix = xobj.dict.getArray('Matrix'); + var bbox = xobj.dict.getArray('BBox'); + var group = xobj.dict.get('Group'); + if (group) { + var groupOptions = { + matrix: matrix, + bbox: bbox, + smask: smask, + isolated: false, + knockout: false + }; + var groupSubtype = group.get('S'); + var colorSpace; + if (isName(groupSubtype, 'Transparency')) { + groupOptions.isolated = group.get('I') || false; + groupOptions.knockout = group.get('K') || false; + colorSpace = group.has('CS') ? ColorSpace.parse(group.get('CS'), this.xref, resources) : null; + } + if (smask && smask.backdrop) { + colorSpace = colorSpace || ColorSpace.singletons.rgb; + smask.backdrop = colorSpace.getRgb(smask.backdrop, 0); + } + operatorList.addOp(OPS.beginGroup, [groupOptions]); + } + operatorList.addOp(OPS.paintFormXObjectBegin, [ + matrix, + bbox + ]); + return this.getOperatorList(xobj, task, xobj.dict.get('Resources') || resources, operatorList, initialState).then(function () { + operatorList.addOp(OPS.paintFormXObjectEnd, []); + if (group) { + operatorList.addOp(OPS.endGroup, [groupOptions]); + } + }); + }, + buildPaintImageXObject: function PartialEvaluator_buildPaintImageXObject(resources, image, inline, operatorList, cacheKey, imageCache) { + var self = this; + var dict = image.dict; + var w = dict.get('Width', 'W'); + var h = dict.get('Height', 'H'); + if (!(w && isNum(w)) || !(h && isNum(h))) { + warn('Image dimensions are missing, or not numbers.'); + return; + } + var maxImageSize = this.options.maxImageSize; + if (maxImageSize !== -1 && w * h > maxImageSize) { + warn('Image exceeded maximum allowed size and was removed.'); + return; + } + var imageMask = dict.get('ImageMask', 'IM') || false; + var imgData, args; + if (imageMask) { + var width = dict.get('Width', 'W'); + var height = dict.get('Height', 'H'); + var bitStrideLength = width + 7 >> 3; + var imgArray = image.getBytes(bitStrideLength * height); + var decode = dict.getArray('Decode', 'D'); + var inverseDecode = !!decode && decode[0] > 0; + imgData = PDFImage.createMask(imgArray, width, height, image instanceof DecodeStream, inverseDecode); + imgData.cached = true; + args = [imgData]; + operatorList.addOp(OPS.paintImageMaskXObject, args); + if (cacheKey) { + imageCache[cacheKey] = { + fn: OPS.paintImageMaskXObject, + args: args + }; + } + return; + } + var softMask = dict.get('SMask', 'SM') || false; + var mask = dict.get('Mask') || false; + var SMALL_IMAGE_DIMENSIONS = 200; + if (inline && !softMask && !mask && !(image instanceof JpegStream) && w + h < SMALL_IMAGE_DIMENSIONS) { + var imageObj = new PDFImage(this.xref, resources, image, inline, null, null); + imgData = imageObj.createImageData(true); + operatorList.addOp(OPS.paintInlineImageXObject, [imgData]); + return; + } + var useNativeImageDecoder = !this.options.disableNativeImageDecoder; + var objId = 'img_' + this.idFactory.createObjId(); + operatorList.addDependency(objId); + args = [ + objId, + w, + h + ]; + if (useNativeImageDecoder && !softMask && !mask && image instanceof JpegStream && NativeImageDecoder.isSupported(image, this.xref, resources)) { + operatorList.addOp(OPS.paintJpegXObject, args); + this.handler.send('obj', [ + objId, + this.pageIndex, + 'JpegStream', + image.getIR(this.options.forceDataSchema) + ]); + return; + } + var nativeImageDecoder = null; + if (useNativeImageDecoder && (image instanceof JpegStream || mask instanceof JpegStream || softMask instanceof JpegStream)) { + nativeImageDecoder = new NativeImageDecoder(self.xref, resources, self.handler, self.options.forceDataSchema); + } + PDFImage.buildImage(self.handler, self.xref, resources, image, inline, nativeImageDecoder).then(function (imageObj) { + var imgData = imageObj.createImageData(false); + self.handler.send('obj', [ + objId, + self.pageIndex, + 'Image', + imgData + ], [imgData.data.buffer]); + }).then(undefined, function (reason) { + warn('Unable to decode image: ' + reason); + self.handler.send('obj', [ + objId, + self.pageIndex, + 'Image', + null + ]); + }); + operatorList.addOp(OPS.paintImageXObject, args); + if (cacheKey) { + imageCache[cacheKey] = { + fn: OPS.paintImageXObject, + args: args + }; + } + }, + handleSMask: function PartialEvaluator_handleSmask(smask, resources, operatorList, task, stateManager) { + var smaskContent = smask.get('G'); + var smaskOptions = { + subtype: smask.get('S').name, + backdrop: smask.get('BC') + }; + var transferObj = smask.get('TR'); + if (isPDFFunction(transferObj)) { + var transferFn = PDFFunction.parse(this.xref, transferObj); + var transferMap = new Uint8Array(256); + var tmp = new Float32Array(1); + for (var i = 0; i < 256; i++) { + tmp[0] = i / 255; + transferFn(tmp, 0, tmp, 0); + transferMap[i] = tmp[0] * 255 | 0; + } + smaskOptions.transferMap = transferMap; + } + return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone()); + }, + handleTilingType: function PartialEvaluator_handleTilingType(fn, args, resources, pattern, patternDict, operatorList, task) { + var tilingOpList = new OperatorList(); + var resourcesArray = [ + patternDict.get('Resources'), + resources + ]; + var patternResources = Dict.merge(this.xref, resourcesArray); + return this.getOperatorList(pattern, task, patternResources, tilingOpList).then(function () { + operatorList.addDependencies(tilingOpList.dependencies); + operatorList.addOp(fn, getTilingPatternIR({ + fnArray: tilingOpList.fnArray, + argsArray: tilingOpList.argsArray + }, patternDict, args)); + }); + }, + handleSetFont: function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, operatorList, task, state) { + var fontName; + if (fontArgs) { + fontArgs = fontArgs.slice(); + fontName = fontArgs[0].name; + } + var self = this; + return this.loadFont(fontName, fontRef, this.xref, resources).then(function (translated) { + if (!translated.font.isType3Font) { + return translated; + } + return translated.loadType3Data(self, resources, operatorList, task).then(function () { + return translated; + }, function (reason) { + self.handler.send('UnsupportedFeature', { featureId: UNSUPPORTED_FEATURES.font }); + return new TranslatedFont('g_font_error', new ErrorFont('Type3 font load error: ' + reason), translated.font); + }); + }).then(function (translated) { + state.font = translated.font; + translated.send(self.handler); + return translated.loadedName; + }); + }, + handleText: function PartialEvaluator_handleText(chars, state) { + var font = state.font; + var glyphs = font.charsToGlyphs(chars); + var isAddToPathSet = !!(state.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG); + if (font.data && (isAddToPathSet || this.options.disableFontFace)) { + var buildPath = function (fontChar) { + if (!font.renderer.hasBuiltPath(fontChar)) { + var path = font.renderer.getPathJs(fontChar); + this.handler.send('commonobj', [ + font.loadedName + '_path_' + fontChar, + 'FontPath', + path + ]); + } + }.bind(this); + for (var i = 0, ii = glyphs.length; i < ii; i++) { + var glyph = glyphs[i]; + buildPath(glyph.fontChar); + var accent = glyph.accent; + if (accent && accent.fontChar) { + buildPath(accent.fontChar); + } + } + } + return glyphs; + }, + setGState: function PartialEvaluator_setGState(resources, gState, operatorList, task, xref, stateManager) { + var gStateObj = []; + var gStateKeys = gState.getKeys(); + var self = this; + var promise = Promise.resolve(); + for (var i = 0, ii = gStateKeys.length; i < ii; i++) { + var key = gStateKeys[i]; + var value = gState.get(key); + switch (key) { + case 'Type': + break; + case 'LW': + case 'LC': + case 'LJ': + case 'ML': + case 'D': + case 'RI': + case 'FL': + case 'CA': + case 'ca': + gStateObj.push([ + key, + value + ]); + break; + case 'Font': + promise = promise.then(function () { + return self.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) { + operatorList.addDependency(loadedName); + gStateObj.push([ + key, + [ + loadedName, + value[1] + ] + ]); + }); + }); + break; + case 'BM': + gStateObj.push([ + key, + value + ]); + break; + case 'SMask': + if (isName(value, 'None')) { + gStateObj.push([ + key, + false + ]); + break; + } + if (isDict(value)) { + promise = promise.then(function (dict) { + return self.handleSMask(dict, resources, operatorList, task, stateManager); + }.bind(this, value)); + gStateObj.push([ + key, + true + ]); + } else { + warn('Unsupported SMask type'); + } + break; + case 'OP': + case 'op': + case 'OPM': + case 'BG': + case 'BG2': + case 'UCR': + case 'UCR2': + case 'TR': + case 'TR2': + case 'HT': + case 'SM': + case 'SA': + case 'AIS': + case 'TK': + info('graphic state operator ' + key); + break; + default: + info('Unknown graphic state operator ' + key); + break; + } + } + return promise.then(function () { + if (gStateObj.length > 0) { + operatorList.addOp(OPS.setGState, [gStateObj]); + } + }); + }, + loadFont: function PartialEvaluator_loadFont(fontName, font, xref, resources) { + function errorFont() { + return Promise.resolve(new TranslatedFont('g_font_error', new ErrorFont('Font ' + fontName + ' is not available'), font)); + } + var fontRef; + if (font) { + assert(isRef(font)); + fontRef = font; + } else { + var fontRes = resources.get('Font'); + if (fontRes) { + fontRef = fontRes.getRaw(fontName); + } else { + warn('fontRes not available'); + return errorFont(); + } + } + if (!fontRef) { + warn('fontRef not available'); + return errorFont(); + } + if (this.fontCache.has(fontRef)) { + return this.fontCache.get(fontRef); + } + font = xref.fetchIfRef(fontRef); + if (!isDict(font)) { + return errorFont(); + } + if (font.translated) { + return font.translated; + } + var fontCapability = createPromiseCapability(); + var preEvaluatedFont = this.preEvaluateFont(font, xref); + var descriptor = preEvaluatedFont.descriptor; + var fontRefIsRef = isRef(fontRef), fontID; + if (fontRefIsRef) { + fontID = fontRef.toString(); + } + if (isDict(descriptor)) { + if (!descriptor.fontAliases) { + descriptor.fontAliases = Object.create(null); + } + var fontAliases = descriptor.fontAliases; + var hash = preEvaluatedFont.hash; + if (fontAliases[hash]) { + var aliasFontRef = fontAliases[hash].aliasRef; + if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) { + this.fontCache.putAlias(fontRef, aliasFontRef); + return this.fontCache.get(fontRef); + } + } else { + fontAliases[hash] = { fontID: Font.getFontID() }; + } + if (fontRefIsRef) { + fontAliases[hash].aliasRef = fontRef; + } + fontID = fontAliases[hash].fontID; + } + if (fontRefIsRef) { + this.fontCache.put(fontRef, fontCapability.promise); + } else { + if (!fontID) { + fontID = this.idFactory.createObjId(); + } + this.fontCache.put('id_' + fontID, fontCapability.promise); + } + assert(fontID, 'The "fontID" must be defined.'); + font.loadedName = 'g_' + this.pdfManager.docId + '_f' + fontID; + font.translated = fontCapability.promise; + var translatedPromise; + try { + translatedPromise = this.translateFont(preEvaluatedFont, xref); + } catch (e) { + translatedPromise = Promise.reject(e); + } + var self = this; + translatedPromise.then(function (translatedFont) { + if (translatedFont.fontType !== undefined) { + var xrefFontStats = xref.stats.fontTypes; + xrefFontStats[translatedFont.fontType] = true; + } + fontCapability.resolve(new TranslatedFont(font.loadedName, translatedFont, font)); + }, function (reason) { + self.handler.send('UnsupportedFeature', { featureId: UNSUPPORTED_FEATURES.font }); + try { + var descriptor = preEvaluatedFont.descriptor; + var fontFile3 = descriptor && descriptor.get('FontFile3'); + var subtype = fontFile3 && fontFile3.get('Subtype'); + var fontType = getFontType(preEvaluatedFont.type, subtype && subtype.name); + var xrefFontStats = xref.stats.fontTypes; + xrefFontStats[fontType] = true; + } catch (ex) { + } + fontCapability.resolve(new TranslatedFont(font.loadedName, new ErrorFont(reason instanceof Error ? reason.message : reason), font)); + }); + return fontCapability.promise; + }, + buildPath: function PartialEvaluator_buildPath(operatorList, fn, args) { + var lastIndex = operatorList.length - 1; + if (!args) { + args = []; + } + if (lastIndex < 0 || operatorList.fnArray[lastIndex] !== OPS.constructPath) { + operatorList.addOp(OPS.constructPath, [ + [fn], + args + ]); + } else { + var opArgs = operatorList.argsArray[lastIndex]; + opArgs[0].push(fn); + Array.prototype.push.apply(opArgs[1], args); + } + }, + handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args, cs, patterns, resources, task, xref) { + var patternName = args[args.length - 1]; + var pattern; + if (isName(patternName) && (pattern = patterns.get(patternName.name))) { + var dict = isStream(pattern) ? pattern.dict : pattern; + var typeNum = dict.get('PatternType'); + if (typeNum === TILING_PATTERN) { + var color = cs.base ? cs.base.getRgb(args, 0) : null; + return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task); + } else if (typeNum === SHADING_PATTERN) { + var shading = dict.get('Shading'); + var matrix = dict.getArray('Matrix'); + pattern = Pattern.parseShading(shading, matrix, xref, resources, this.handler); + operatorList.addOp(fn, pattern.getIR()); + return Promise.resolve(); + } + return Promise.reject('Unknown PatternType: ' + typeNum); + } + operatorList.addOp(fn, args); + return Promise.resolve(); + }, + getOperatorList: function PartialEvaluator_getOperatorList(stream, task, resources, operatorList, initialState) { + var self = this; + var xref = this.xref; + var imageCache = Object.create(null); + assert(operatorList); + resources = resources || Dict.empty; + var xobjs = resources.get('XObject') || Dict.empty; + var patterns = resources.get('Pattern') || Dict.empty; + var stateManager = new StateManager(initialState || new EvalState()); + var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + var timeSlotManager = new TimeSlotManager(); + return new Promise(function promiseBody(resolve, reject) { + var next = function (promise) { + promise.then(function () { + try { + promiseBody(resolve, reject); + } catch (ex) { + reject(ex); + } + }, reject); + }; + task.ensureNotTerminated(); + timeSlotManager.reset(); + var stop, operation = {}, i, ii, cs; + while (!(stop = timeSlotManager.check())) { + operation.args = null; + if (!preprocessor.read(operation)) { + break; + } + var args = operation.args; + var fn = operation.fn; + switch (fn | 0) { + case OPS.paintXObject: + if (args[0].code) { + break; + } + var name = args[0].name; + if (!name) { + warn('XObject must be referred to by name.'); + continue; + } + if (imageCache[name] !== undefined) { + operatorList.addOp(imageCache[name].fn, imageCache[name].args); + args = null; + continue; + } + var xobj = xobjs.get(name); + if (xobj) { + assert(isStream(xobj), 'XObject should be a stream'); + var type = xobj.dict.get('Subtype'); + assert(isName(type), 'XObject should have a Name subtype'); + if (type.name === 'Form') { + stateManager.save(); + next(self.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone()).then(function () { + stateManager.restore(); + })); + return; + } else if (type.name === 'Image') { + self.buildPaintImageXObject(resources, xobj, false, operatorList, name, imageCache); + args = null; + continue; + } else if (type.name === 'PS') { + info('Ignored XObject subtype PS'); + continue; + } else { + error('Unhandled XObject subtype ' + type.name); + } + } + break; + case OPS.setFont: + var fontSize = args[1]; + next(self.handleSetFont(resources, args, null, operatorList, task, stateManager.state).then(function (loadedName) { + operatorList.addDependency(loadedName); + operatorList.addOp(OPS.setFont, [ + loadedName, + fontSize + ]); + })); + return; + case OPS.endInlineImage: + var cacheKey = args[0].cacheKey; + if (cacheKey) { + var cacheEntry = imageCache[cacheKey]; + if (cacheEntry !== undefined) { + operatorList.addOp(cacheEntry.fn, cacheEntry.args); + args = null; + continue; + } + } + self.buildPaintImageXObject(resources, args[0], true, operatorList, cacheKey, imageCache); + args = null; + continue; + case OPS.showText: + args[0] = self.handleText(args[0], stateManager.state); + break; + case OPS.showSpacedText: + var arr = args[0]; + var combinedGlyphs = []; + var arrLength = arr.length; + var state = stateManager.state; + for (i = 0; i < arrLength; ++i) { + var arrItem = arr[i]; + if (isString(arrItem)) { + Array.prototype.push.apply(combinedGlyphs, self.handleText(arrItem, state)); + } else if (isNum(arrItem)) { + combinedGlyphs.push(arrItem); + } + } + args[0] = combinedGlyphs; + fn = OPS.showText; + break; + case OPS.nextLineShowText: + operatorList.addOp(OPS.nextLine); + args[0] = self.handleText(args[0], stateManager.state); + fn = OPS.showText; + break; + case OPS.nextLineSetSpacingShowText: + operatorList.addOp(OPS.nextLine); + operatorList.addOp(OPS.setWordSpacing, [args.shift()]); + operatorList.addOp(OPS.setCharSpacing, [args.shift()]); + args[0] = self.handleText(args[0], stateManager.state); + fn = OPS.showText; + break; + case OPS.setTextRenderingMode: + stateManager.state.textRenderingMode = args[0]; + break; + case OPS.setFillColorSpace: + stateManager.state.fillColorSpace = ColorSpace.parse(args[0], xref, resources); + continue; + case OPS.setStrokeColorSpace: + stateManager.state.strokeColorSpace = ColorSpace.parse(args[0], xref, resources); + continue; + case OPS.setFillColor: + cs = stateManager.state.fillColorSpace; + args = cs.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeColor: + cs = stateManager.state.strokeColorSpace; + args = cs.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillGray: + stateManager.state.fillColorSpace = ColorSpace.singletons.gray; + args = ColorSpace.singletons.gray.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeGray: + stateManager.state.strokeColorSpace = ColorSpace.singletons.gray; + args = ColorSpace.singletons.gray.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillCMYKColor: + stateManager.state.fillColorSpace = ColorSpace.singletons.cmyk; + args = ColorSpace.singletons.cmyk.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeCMYKColor: + stateManager.state.strokeColorSpace = ColorSpace.singletons.cmyk; + args = ColorSpace.singletons.cmyk.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillRGBColor: + stateManager.state.fillColorSpace = ColorSpace.singletons.rgb; + args = ColorSpace.singletons.rgb.getRgb(args, 0); + break; + case OPS.setStrokeRGBColor: + stateManager.state.strokeColorSpace = ColorSpace.singletons.rgb; + args = ColorSpace.singletons.rgb.getRgb(args, 0); + break; + case OPS.setFillColorN: + cs = stateManager.state.fillColorSpace; + if (cs.name === 'Pattern') { + next(self.handleColorN(operatorList, OPS.setFillColorN, args, cs, patterns, resources, task, xref)); + return; + } + args = cs.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeColorN: + cs = stateManager.state.strokeColorSpace; + if (cs.name === 'Pattern') { + next(self.handleColorN(operatorList, OPS.setStrokeColorN, args, cs, patterns, resources, task, xref)); + return; + } + args = cs.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.shadingFill: + var shadingRes = resources.get('Shading'); + if (!shadingRes) { + error('No shading resource found'); + } + var shading = shadingRes.get(args[0].name); + if (!shading) { + error('No shading object found'); + } + var shadingFill = Pattern.parseShading(shading, null, xref, resources, self.handler); + var patternIR = shadingFill.getIR(); + args = [patternIR]; + fn = OPS.shadingFill; + break; + case OPS.setGState: + var dictName = args[0]; + var extGState = resources.get('ExtGState'); + if (!isDict(extGState) || !extGState.has(dictName.name)) { + break; + } + var gState = extGState.get(dictName.name); + next(self.setGState(resources, gState, operatorList, task, xref, stateManager)); + return; + case OPS.moveTo: + case OPS.lineTo: + case OPS.curveTo: + case OPS.curveTo2: + case OPS.curveTo3: + case OPS.closePath: + self.buildPath(operatorList, fn, args); + continue; + case OPS.rectangle: + self.buildPath(operatorList, fn, args); + continue; + case OPS.markPoint: + case OPS.markPointProps: + case OPS.beginMarkedContent: + case OPS.beginMarkedContentProps: + case OPS.endMarkedContent: + case OPS.beginCompat: + case OPS.endCompat: + continue; + default: + if (args !== null) { + for (i = 0, ii = args.length; i < ii; i++) { + if (args[i] instanceof Dict) { + break; + } + } + if (i < ii) { + warn('getOperatorList - ignoring operator: ' + fn); + continue; + } + } + } + operatorList.addOp(fn, args); + } + if (stop) { + next(deferred); + return; + } + for (i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) { + operatorList.addOp(OPS.restore, []); + } + resolve(); + }); + }, + getTextContent: function PartialEvaluator_getTextContent(stream, task, resources, stateManager, normalizeWhitespace, combineTextItems) { + stateManager = stateManager || new StateManager(new TextState()); + var WhitespaceRegexp = /\s/g; + var textContent = { + items: [], + styles: Object.create(null) + }; + var textContentItem = { + initialized: false, + str: [], + width: 0, + height: 0, + vertical: false, + lastAdvanceWidth: 0, + lastAdvanceHeight: 0, + textAdvanceScale: 0, + spaceWidth: 0, + fakeSpaceMin: Infinity, + fakeMultiSpaceMin: Infinity, + fakeMultiSpaceMax: -0, + textRunBreakAllowed: false, + transform: null, + fontName: null + }; + var SPACE_FACTOR = 0.3; + var MULTI_SPACE_FACTOR = 1.5; + var MULTI_SPACE_FACTOR_MAX = 4; + var self = this; + var xref = this.xref; + resources = xref.fetchIfRef(resources) || Dict.empty; + var xobjs = null; + var xobjsCache = Object.create(null); + var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + var textState; + function ensureTextContentItem() { + if (textContentItem.initialized) { + return textContentItem; + } + var font = textState.font; + if (!(font.loadedName in textContent.styles)) { + textContent.styles[font.loadedName] = { + fontFamily: font.fallbackName, + ascent: font.ascent, + descent: font.descent, + vertical: font.vertical + }; + } + textContentItem.fontName = font.loadedName; + var tsm = [ + textState.fontSize * textState.textHScale, + 0, + 0, + textState.fontSize, + 0, + textState.textRise + ]; + if (font.isType3Font && textState.fontMatrix !== FONT_IDENTITY_MATRIX && textState.fontSize === 1) { + var glyphHeight = font.bbox[3] - font.bbox[1]; + if (glyphHeight > 0) { + glyphHeight = glyphHeight * textState.fontMatrix[3]; + tsm[3] *= glyphHeight; + } + } + var trm = Util.transform(textState.ctm, Util.transform(textState.textMatrix, tsm)); + textContentItem.transform = trm; + if (!font.vertical) { + textContentItem.width = 0; + textContentItem.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]); + textContentItem.vertical = false; + } else { + textContentItem.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]); + textContentItem.height = 0; + textContentItem.vertical = true; + } + var a = textState.textLineMatrix[0]; + var b = textState.textLineMatrix[1]; + var scaleLineX = Math.sqrt(a * a + b * b); + a = textState.ctm[0]; + b = textState.ctm[1]; + var scaleCtmX = Math.sqrt(a * a + b * b); + textContentItem.textAdvanceScale = scaleCtmX * scaleLineX; + textContentItem.lastAdvanceWidth = 0; + textContentItem.lastAdvanceHeight = 0; + var spaceWidth = font.spaceWidth / 1000 * textState.fontSize; + if (spaceWidth) { + textContentItem.spaceWidth = spaceWidth; + textContentItem.fakeSpaceMin = spaceWidth * SPACE_FACTOR; + textContentItem.fakeMultiSpaceMin = spaceWidth * MULTI_SPACE_FACTOR; + textContentItem.fakeMultiSpaceMax = spaceWidth * MULTI_SPACE_FACTOR_MAX; + textContentItem.textRunBreakAllowed = !font.isMonospace; + } else { + textContentItem.spaceWidth = 0; + textContentItem.fakeSpaceMin = Infinity; + textContentItem.fakeMultiSpaceMin = Infinity; + textContentItem.fakeMultiSpaceMax = 0; + textContentItem.textRunBreakAllowed = false; + } + textContentItem.initialized = true; + return textContentItem; + } + function replaceWhitespace(str) { + var i = 0, ii = str.length, code; + while (i < ii && (code = str.charCodeAt(i)) >= 0x20 && code <= 0x7F) { + i++; + } + return i < ii ? str.replace(WhitespaceRegexp, ' ') : str; + } + function runBidiTransform(textChunk) { + var str = textChunk.str.join(''); + var bidiResult = bidi(str, -1, textChunk.vertical); + return { + str: normalizeWhitespace ? replaceWhitespace(bidiResult.str) : bidiResult.str, + dir: bidiResult.dir, + width: textChunk.width, + height: textChunk.height, + transform: textChunk.transform, + fontName: textChunk.fontName + }; + } + function handleSetFont(fontName, fontRef) { + return self.loadFont(fontName, fontRef, xref, resources).then(function (translated) { + textState.font = translated.font; + textState.fontMatrix = translated.font.fontMatrix || FONT_IDENTITY_MATRIX; + }); + } + function buildTextContentItem(chars) { + var font = textState.font; + var textChunk = ensureTextContentItem(); + var width = 0; + var height = 0; + var glyphs = font.charsToGlyphs(chars); + for (var i = 0; i < glyphs.length; i++) { + var glyph = glyphs[i]; + var glyphWidth = null; + if (font.vertical && glyph.vmetric) { + glyphWidth = glyph.vmetric[0]; + } else { + glyphWidth = glyph.width; + } + var glyphUnicode = glyph.unicode; + var NormalizedUnicodes = getNormalizedUnicodes(); + if (NormalizedUnicodes[glyphUnicode] !== undefined) { + glyphUnicode = NormalizedUnicodes[glyphUnicode]; + } + glyphUnicode = reverseIfRtl(glyphUnicode); + var charSpacing = textState.charSpacing; + if (glyph.isSpace) { + var wordSpacing = textState.wordSpacing; + charSpacing += wordSpacing; + if (wordSpacing > 0) { + addFakeSpaces(wordSpacing, textChunk.str); + } + } + var tx = 0; + var ty = 0; + if (!font.vertical) { + var w0 = glyphWidth * textState.fontMatrix[0]; + tx = (w0 * textState.fontSize + charSpacing) * textState.textHScale; + width += tx; + } else { + var w1 = glyphWidth * textState.fontMatrix[0]; + ty = w1 * textState.fontSize + charSpacing; + height += ty; + } + textState.translateTextMatrix(tx, ty); + textChunk.str.push(glyphUnicode); + } + if (!font.vertical) { + textChunk.lastAdvanceWidth = width; + textChunk.width += width; + } else { + textChunk.lastAdvanceHeight = height; + textChunk.height += Math.abs(height); + } + return textChunk; + } + function addFakeSpaces(width, strBuf) { + if (width < textContentItem.fakeSpaceMin) { + return; + } + if (width < textContentItem.fakeMultiSpaceMin) { + strBuf.push(' '); + return; + } + var fakeSpaces = Math.round(width / textContentItem.spaceWidth); + while (fakeSpaces-- > 0) { + strBuf.push(' '); + } + } + function flushTextContentItem() { + if (!textContentItem.initialized) { + return; + } + textContentItem.width *= textContentItem.textAdvanceScale; + textContentItem.height *= textContentItem.textAdvanceScale; + textContent.items.push(runBidiTransform(textContentItem)); + textContentItem.initialized = false; + textContentItem.str.length = 0; + } + var timeSlotManager = new TimeSlotManager(); + return new Promise(function promiseBody(resolve, reject) { + var next = function (promise) { + promise.then(function () { + try { + promiseBody(resolve, reject); + } catch (ex) { + reject(ex); + } + }, reject); + }; + task.ensureNotTerminated(); + timeSlotManager.reset(); + var stop, operation = {}, args = []; + while (!(stop = timeSlotManager.check())) { + args.length = 0; + operation.args = args; + if (!preprocessor.read(operation)) { + break; + } + textState = stateManager.state; + var fn = operation.fn; + args = operation.args; + var advance, diff; + switch (fn | 0) { + case OPS.setFont: + var fontNameArg = args[0].name, fontSizeArg = args[1]; + if (textState.font && fontNameArg === textState.fontName && fontSizeArg === textState.fontSize) { + break; + } + flushTextContentItem(); + textState.fontName = fontNameArg; + textState.fontSize = fontSizeArg; + next(handleSetFont(fontNameArg, null)); + return; + case OPS.setTextRise: + flushTextContentItem(); + textState.textRise = args[0]; + break; + case OPS.setHScale: + flushTextContentItem(); + textState.textHScale = args[0] / 100; + break; + case OPS.setLeading: + flushTextContentItem(); + textState.leading = args[0]; + break; + case OPS.moveText: + var isSameTextLine = !textState.font ? false : (textState.font.vertical ? args[0] : args[1]) === 0; + advance = args[0] - args[1]; + if (combineTextItems && isSameTextLine && textContentItem.initialized && advance > 0 && advance <= textContentItem.fakeMultiSpaceMax) { + textState.translateTextLineMatrix(args[0], args[1]); + textContentItem.width += args[0] - textContentItem.lastAdvanceWidth; + textContentItem.height += args[1] - textContentItem.lastAdvanceHeight; + diff = args[0] - textContentItem.lastAdvanceWidth - (args[1] - textContentItem.lastAdvanceHeight); + addFakeSpaces(diff, textContentItem.str); + break; + } + flushTextContentItem(); + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS.setLeadingMoveText: + flushTextContentItem(); + textState.leading = -args[1]; + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS.nextLine: + flushTextContentItem(); + textState.carriageReturn(); + break; + case OPS.setTextMatrix: + advance = textState.calcTextLineMatrixAdvance(args[0], args[1], args[2], args[3], args[4], args[5]); + if (combineTextItems && advance !== null && textContentItem.initialized && advance.value > 0 && advance.value <= textContentItem.fakeMultiSpaceMax) { + textState.translateTextLineMatrix(advance.width, advance.height); + textContentItem.width += advance.width - textContentItem.lastAdvanceWidth; + textContentItem.height += advance.height - textContentItem.lastAdvanceHeight; + diff = advance.width - textContentItem.lastAdvanceWidth - (advance.height - textContentItem.lastAdvanceHeight); + addFakeSpaces(diff, textContentItem.str); + break; + } + flushTextContentItem(); + textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); + textState.setTextLineMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); + break; + case OPS.setCharSpacing: + textState.charSpacing = args[0]; + break; + case OPS.setWordSpacing: + textState.wordSpacing = args[0]; + break; + case OPS.beginText: + flushTextContentItem(); + textState.textMatrix = IDENTITY_MATRIX.slice(); + textState.textLineMatrix = IDENTITY_MATRIX.slice(); + break; + case OPS.showSpacedText: + var items = args[0]; + var offset; + for (var j = 0, jj = items.length; j < jj; j++) { + if (typeof items[j] === 'string') { + buildTextContentItem(items[j]); + } else if (isNum(items[j])) { + ensureTextContentItem(); + advance = items[j] * textState.fontSize / 1000; + var breakTextRun = false; + if (textState.font.vertical) { + offset = advance; + textState.translateTextMatrix(0, offset); + breakTextRun = textContentItem.textRunBreakAllowed && advance > textContentItem.fakeMultiSpaceMax; + if (!breakTextRun) { + textContentItem.height += offset; + } + } else { + advance = -advance; + offset = advance * textState.textHScale; + textState.translateTextMatrix(offset, 0); + breakTextRun = textContentItem.textRunBreakAllowed && advance > textContentItem.fakeMultiSpaceMax; + if (!breakTextRun) { + textContentItem.width += offset; + } + } + if (breakTextRun) { + flushTextContentItem(); + } else if (advance > 0) { + addFakeSpaces(advance, textContentItem.str); + } + } + } + break; + case OPS.showText: + buildTextContentItem(args[0]); + break; + case OPS.nextLineShowText: + flushTextContentItem(); + textState.carriageReturn(); + buildTextContentItem(args[0]); + break; + case OPS.nextLineSetSpacingShowText: + flushTextContentItem(); + textState.wordSpacing = args[0]; + textState.charSpacing = args[1]; + textState.carriageReturn(); + buildTextContentItem(args[2]); + break; + case OPS.paintXObject: + flushTextContentItem(); + if (args[0].code) { + break; + } + if (!xobjs) { + xobjs = resources.get('XObject') || Dict.empty; + } + var name = args[0].name; + if (xobjsCache.key === name) { + if (xobjsCache.texts) { + Util.appendToArray(textContent.items, xobjsCache.texts.items); + Util.extendObj(textContent.styles, xobjsCache.texts.styles); + } + break; + } + var xobj = xobjs.get(name); + if (!xobj) { + break; + } + assert(isStream(xobj), 'XObject should be a stream'); + var type = xobj.dict.get('Subtype'); + assert(isName(type), 'XObject should have a Name subtype'); + if ('Form' !== type.name) { + xobjsCache.key = name; + xobjsCache.texts = null; + break; + } + stateManager.save(); + var matrix = xobj.dict.getArray('Matrix'); + if (isArray(matrix) && matrix.length === 6) { + stateManager.transform(matrix); + } + next(self.getTextContent(xobj, task, xobj.dict.get('Resources') || resources, stateManager, normalizeWhitespace, combineTextItems).then(function (formTextContent) { + Util.appendToArray(textContent.items, formTextContent.items); + Util.extendObj(textContent.styles, formTextContent.styles); + stateManager.restore(); + xobjsCache.key = name; + xobjsCache.texts = formTextContent; + })); + return; + case OPS.setGState: + flushTextContentItem(); + var dictName = args[0]; + var extGState = resources.get('ExtGState'); + if (!isDict(extGState) || !isName(dictName)) { + break; + } + var gState = extGState.get(dictName.name); + if (!isDict(gState)) { + break; + } + var gStateFont = gState.get('Font'); + if (gStateFont) { + textState.fontName = null; + textState.fontSize = gStateFont[1]; + next(handleSetFont(null, gStateFont[0])); + return; + } + break; + } + } + if (stop) { + next(deferred); + return; + } + flushTextContentItem(); + resolve(textContent); + }); + }, + extractDataStructures: function PartialEvaluator_extractDataStructures(dict, baseDict, xref, properties) { + var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode'); + var toUnicodePromise = toUnicode ? this.readToUnicode(toUnicode) : Promise.resolve(undefined); + if (properties.composite) { + var cidSystemInfo = dict.get('CIDSystemInfo'); + if (isDict(cidSystemInfo)) { + properties.cidSystemInfo = { + registry: cidSystemInfo.get('Registry'), + ordering: cidSystemInfo.get('Ordering'), + supplement: cidSystemInfo.get('Supplement') + }; + } + var cidToGidMap = dict.get('CIDToGIDMap'); + if (isStream(cidToGidMap)) { + properties.cidToGidMap = this.readCidToGidMap(cidToGidMap); + } + } + var differences = []; + var baseEncodingName = null; + var encoding; + if (dict.has('Encoding')) { + encoding = dict.get('Encoding'); + if (isDict(encoding)) { + baseEncodingName = encoding.get('BaseEncoding'); + baseEncodingName = isName(baseEncodingName) ? baseEncodingName.name : null; + if (encoding.has('Differences')) { + var diffEncoding = encoding.get('Differences'); + var index = 0; + for (var j = 0, jj = diffEncoding.length; j < jj; j++) { + var data = xref.fetchIfRef(diffEncoding[j]); + if (isNum(data)) { + index = data; + } else if (isName(data)) { + differences[index++] = data.name; + } else { + error('Invalid entry in \'Differences\' array: ' + data); + } + } + } + } else if (isName(encoding)) { + baseEncodingName = encoding.name; + } else { + error('Encoding is not a Name nor a Dict'); + } + if (baseEncodingName !== 'MacRomanEncoding' && baseEncodingName !== 'MacExpertEncoding' && baseEncodingName !== 'WinAnsiEncoding') { + baseEncodingName = null; + } + } + if (baseEncodingName) { + properties.defaultEncoding = getEncoding(baseEncodingName).slice(); + } else { + var isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + var isNonsymbolicFont = !!(properties.flags & FontFlags.Nonsymbolic); + encoding = StandardEncoding; + if (properties.type === 'TrueType' && !isNonsymbolicFont) { + encoding = WinAnsiEncoding; + } + if (isSymbolicFont) { + encoding = MacRomanEncoding; + if (!properties.file) { + if (/Symbol/i.test(properties.name)) { + encoding = SymbolSetEncoding; + } else if (/Dingbats/i.test(properties.name)) { + encoding = ZapfDingbatsEncoding; + } + } + } + properties.defaultEncoding = encoding; + } + properties.differences = differences; + properties.baseEncodingName = baseEncodingName; + properties.hasEncoding = !!baseEncodingName || differences.length > 0; + properties.dict = dict; + return toUnicodePromise.then(function (toUnicode) { + properties.toUnicode = toUnicode; + return this.buildToUnicode(properties); + }.bind(this)).then(function (toUnicode) { + properties.toUnicode = toUnicode; + return properties; + }); + }, + buildToUnicode: function PartialEvaluator_buildToUnicode(properties) { + properties.hasIncludedToUnicodeMap = !!properties.toUnicode && properties.toUnicode.length > 0; + if (properties.hasIncludedToUnicodeMap) { + return Promise.resolve(properties.toUnicode); + } + var toUnicode, charcode, glyphName; + if (!properties.composite) { + toUnicode = []; + var encoding = properties.defaultEncoding.slice(); + var baseEncodingName = properties.baseEncodingName; + var differences = properties.differences; + for (charcode in differences) { + glyphName = differences[charcode]; + if (glyphName === '.notdef') { + continue; + } + encoding[charcode] = glyphName; + } + var glyphsUnicodeMap = getGlyphsUnicode(); + for (charcode in encoding) { + glyphName = encoding[charcode]; + if (glyphName === '') { + continue; + } else if (glyphsUnicodeMap[glyphName] === undefined) { + var code = 0; + switch (glyphName[0]) { + case 'G': + if (glyphName.length === 3) { + code = parseInt(glyphName.substr(1), 16); + } + break; + case 'g': + if (glyphName.length === 5) { + code = parseInt(glyphName.substr(1), 16); + } + break; + case 'C': + case 'c': + if (glyphName.length >= 3) { + code = +glyphName.substr(1); + } + break; + default: + var unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap); + if (unicode !== -1) { + code = unicode; + } + } + if (code) { + if (baseEncodingName && code === +charcode) { + var baseEncoding = getEncoding(baseEncodingName); + if (baseEncoding && (glyphName = baseEncoding[charcode])) { + toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]); + continue; + } + } + toUnicode[charcode] = String.fromCharCode(code); + } + continue; + } + toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]); + } + return Promise.resolve(new ToUnicodeMap(toUnicode)); + } + if (properties.composite && (properties.cMap.builtInCMap && !(properties.cMap instanceof IdentityCMap) || properties.cidSystemInfo.registry === 'Adobe' && (properties.cidSystemInfo.ordering === 'GB1' || properties.cidSystemInfo.ordering === 'CNS1' || properties.cidSystemInfo.ordering === 'Japan1' || properties.cidSystemInfo.ordering === 'Korea1'))) { + var registry = properties.cidSystemInfo.registry; + var ordering = properties.cidSystemInfo.ordering; + var ucs2CMapName = Name.get(registry + '-' + ordering + '-UCS2'); + return CMapFactory.create({ + encoding: ucs2CMapName, + fetchBuiltInCMap: this.fetchBuiltInCMap, + useCMap: null + }).then(function (ucs2CMap) { + var cMap = properties.cMap; + toUnicode = []; + cMap.forEach(function (charcode, cid) { + assert(cid <= 0xffff, 'Max size of CID is 65,535'); + var ucs2 = ucs2CMap.lookup(cid); + if (ucs2) { + toUnicode[charcode] = String.fromCharCode((ucs2.charCodeAt(0) << 8) + ucs2.charCodeAt(1)); + } + }); + return new ToUnicodeMap(toUnicode); + }); + } + return Promise.resolve(new IdentityToUnicodeMap(properties.firstChar, properties.lastChar)); + }, + readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) { + var cmapObj = toUnicode; + if (isName(cmapObj)) { + return CMapFactory.create({ + encoding: cmapObj, + fetchBuiltInCMap: this.fetchBuiltInCMap, + useCMap: null + }).then(function (cmap) { + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 0xFFFF); + } + return new ToUnicodeMap(cmap.getMap()); + }); + } else if (isStream(cmapObj)) { + return CMapFactory.create({ + encoding: cmapObj, + fetchBuiltInCMap: this.fetchBuiltInCMap, + useCMap: null + }).then(function (cmap) { + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 0xFFFF); + } + var map = new Array(cmap.length); + cmap.forEach(function (charCode, token) { + var str = []; + for (var k = 0; k < token.length; k += 2) { + var w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1); + if ((w1 & 0xF800) !== 0xD800) { + str.push(w1); + continue; + } + k += 2; + var w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1); + str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000); + } + map[charCode] = String.fromCharCode.apply(String, str); + }); + return new ToUnicodeMap(map); + }); + } + return Promise.resolve(null); + }, + readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) { + var glyphsData = cidToGidStream.getBytes(); + var result = []; + for (var j = 0, jj = glyphsData.length; j < jj; j++) { + var glyphID = glyphsData[j++] << 8 | glyphsData[j]; + if (glyphID === 0) { + continue; + } + var code = j >> 1; + result[code] = glyphID; + } + return result; + }, + extractWidths: function PartialEvaluator_extractWidths(dict, xref, descriptor, properties) { + var glyphsWidths = []; + var defaultWidth = 0; + var glyphsVMetrics = []; + var defaultVMetrics; + var i, ii, j, jj, start, code, widths; + if (properties.composite) { + defaultWidth = dict.get('DW') || 1000; + widths = dict.get('W'); + if (widths) { + for (i = 0, ii = widths.length; i < ii; i++) { + start = xref.fetchIfRef(widths[i++]); + code = xref.fetchIfRef(widths[i]); + if (isArray(code)) { + for (j = 0, jj = code.length; j < jj; j++) { + glyphsWidths[start++] = xref.fetchIfRef(code[j]); + } + } else { + var width = xref.fetchIfRef(widths[++i]); + for (j = start; j <= code; j++) { + glyphsWidths[j] = width; + } + } + } + } + if (properties.vertical) { + var vmetrics = dict.getArray('DW2') || [ + 880, + -1000 + ]; + defaultVMetrics = [ + vmetrics[1], + defaultWidth * 0.5, + vmetrics[0] + ]; + vmetrics = dict.get('W2'); + if (vmetrics) { + for (i = 0, ii = vmetrics.length; i < ii; i++) { + start = xref.fetchIfRef(vmetrics[i++]); + code = xref.fetchIfRef(vmetrics[i]); + if (isArray(code)) { + for (j = 0, jj = code.length; j < jj; j++) { + glyphsVMetrics[start++] = [ + xref.fetchIfRef(code[j++]), + xref.fetchIfRef(code[j++]), + xref.fetchIfRef(code[j]) + ]; + } + } else { + var vmetric = [ + xref.fetchIfRef(vmetrics[++i]), + xref.fetchIfRef(vmetrics[++i]), + xref.fetchIfRef(vmetrics[++i]) + ]; + for (j = start; j <= code; j++) { + glyphsVMetrics[j] = vmetric; + } + } + } + } + } + } else { + var firstChar = properties.firstChar; + widths = dict.get('Widths'); + if (widths) { + j = firstChar; + for (i = 0, ii = widths.length; i < ii; i++) { + glyphsWidths[j++] = xref.fetchIfRef(widths[i]); + } + defaultWidth = parseFloat(descriptor.get('MissingWidth')) || 0; + } else { + var baseFontName = dict.get('BaseFont'); + if (isName(baseFontName)) { + var metrics = this.getBaseFontMetrics(baseFontName.name); + glyphsWidths = this.buildCharCodeToWidth(metrics.widths, properties); + defaultWidth = metrics.defaultWidth; + } + } + } + var isMonospace = true; + var firstWidth = defaultWidth; + for (var glyph in glyphsWidths) { + var glyphWidth = glyphsWidths[glyph]; + if (!glyphWidth) { + continue; + } + if (!firstWidth) { + firstWidth = glyphWidth; + continue; + } + if (firstWidth !== glyphWidth) { + isMonospace = false; + break; + } + } + if (isMonospace) { + properties.flags |= FontFlags.FixedPitch; + } + properties.defaultWidth = defaultWidth; + properties.widths = glyphsWidths; + properties.defaultVMetrics = defaultVMetrics; + properties.vmetrics = glyphsVMetrics; + }, + isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) { + var fontNameWoStyle = baseFontName.split('-')[0]; + return fontNameWoStyle in getSerifFonts() || fontNameWoStyle.search(/serif/gi) !== -1; + }, + getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) { + var defaultWidth = 0; + var widths = []; + var monospace = false; + var stdFontMap = getStdFontMap(); + var lookupName = stdFontMap[name] || name; + var Metrics = getMetrics(); + if (!(lookupName in Metrics)) { + if (this.isSerifFont(name)) { + lookupName = 'Times-Roman'; + } else { + lookupName = 'Helvetica'; + } + } + var glyphWidths = Metrics[lookupName]; + if (isNum(glyphWidths)) { + defaultWidth = glyphWidths; + monospace = true; + } else { + widths = glyphWidths(); + } + return { + defaultWidth: defaultWidth, + monospace: monospace, + widths: widths + }; + }, + buildCharCodeToWidth: function PartialEvaluator_bulildCharCodeToWidth(widthsByGlyphName, properties) { + var widths = Object.create(null); + var differences = properties.differences; + var encoding = properties.defaultEncoding; + for (var charCode = 0; charCode < 256; charCode++) { + if (charCode in differences && widthsByGlyphName[differences[charCode]]) { + widths[charCode] = widthsByGlyphName[differences[charCode]]; + continue; + } + if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) { + widths[charCode] = widthsByGlyphName[encoding[charCode]]; + continue; + } + } + return widths; + }, + preEvaluateFont: function PartialEvaluator_preEvaluateFont(dict, xref) { + var baseDict = dict; + var type = dict.get('Subtype'); + assert(isName(type), 'invalid font Subtype'); + var composite = false; + var uint8array; + if (type.name === 'Type0') { + var df = dict.get('DescendantFonts'); + if (!df) { + error('Descendant fonts are not specified'); + } + dict = isArray(df) ? xref.fetchIfRef(df[0]) : df; + type = dict.get('Subtype'); + assert(isName(type), 'invalid font Subtype'); + composite = true; + } + var descriptor = dict.get('FontDescriptor'); + if (descriptor) { + var hash = new MurmurHash3_64(); + var encoding = baseDict.getRaw('Encoding'); + if (isName(encoding)) { + hash.update(encoding.name); + } else if (isRef(encoding)) { + hash.update(encoding.toString()); + } else if (isDict(encoding)) { + var keys = encoding.getKeys(); + for (var i = 0, ii = keys.length; i < ii; i++) { + var entry = encoding.getRaw(keys[i]); + if (isName(entry)) { + hash.update(entry.name); + } else if (isRef(entry)) { + hash.update(entry.toString()); + } else if (isArray(entry)) { + var diffLength = entry.length, diffBuf = new Array(diffLength); + for (var j = 0; j < diffLength; j++) { + var diffEntry = entry[j]; + if (isName(diffEntry)) { + diffBuf[j] = diffEntry.name; + } else if (isNum(diffEntry) || isRef(diffEntry)) { + diffBuf[j] = diffEntry.toString(); + } + } + hash.update(diffBuf.join()); + } + } + } + var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode'); + if (isStream(toUnicode)) { + var stream = toUnicode.str || toUnicode; + uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start); + hash.update(uint8array); + } else if (isName(toUnicode)) { + hash.update(toUnicode.name); + } + var widths = dict.get('Widths') || baseDict.get('Widths'); + if (widths) { + uint8array = new Uint8Array(new Uint32Array(widths).buffer); + hash.update(uint8array); + } + } + return { + descriptor: descriptor, + dict: dict, + baseDict: baseDict, + composite: composite, + type: type.name, + hash: hash ? hash.hexdigest() : '' + }; + }, + translateFont: function PartialEvaluator_translateFont(preEvaluatedFont, xref) { + var baseDict = preEvaluatedFont.baseDict; + var dict = preEvaluatedFont.dict; + var composite = preEvaluatedFont.composite; + var descriptor = preEvaluatedFont.descriptor; + var type = preEvaluatedFont.type; + var maxCharIndex = composite ? 0xFFFF : 0xFF; + var properties; + if (!descriptor) { + if (type === 'Type3') { + descriptor = new Dict(null); + descriptor.set('FontName', Name.get(type)); + descriptor.set('FontBBox', dict.getArray('FontBBox')); + } else { + var baseFontName = dict.get('BaseFont'); + if (!isName(baseFontName)) { + error('Base font is not specified'); + } + baseFontName = baseFontName.name.replace(/[,_]/g, '-'); + var metrics = this.getBaseFontMetrics(baseFontName); + var fontNameWoStyle = baseFontName.split('-')[0]; + var flags = (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | (metrics.monospace ? FontFlags.FixedPitch : 0) | (getSymbolsFonts()[fontNameWoStyle] ? FontFlags.Symbolic : FontFlags.Nonsymbolic); + properties = { + type: type, + name: baseFontName, + widths: metrics.widths, + defaultWidth: metrics.defaultWidth, + flags: flags, + firstChar: 0, + lastChar: maxCharIndex + }; + return this.extractDataStructures(dict, dict, xref, properties).then(function (properties) { + properties.widths = this.buildCharCodeToWidth(metrics.widths, properties); + return new Font(baseFontName, null, properties); + }.bind(this)); + } + } + var firstChar = dict.get('FirstChar') || 0; + var lastChar = dict.get('LastChar') || maxCharIndex; + var fontName = descriptor.get('FontName'); + var baseFont = dict.get('BaseFont'); + if (isString(fontName)) { + fontName = Name.get(fontName); + } + if (isString(baseFont)) { + baseFont = Name.get(baseFont); + } + if (type !== 'Type3') { + var fontNameStr = fontName && fontName.name; + var baseFontStr = baseFont && baseFont.name; + if (fontNameStr !== baseFontStr) { + info('The FontDescriptor\'s FontName is "' + fontNameStr + '" but should be the same as the Font\'s BaseFont "' + baseFontStr + '"'); + if (fontNameStr && baseFontStr && baseFontStr.indexOf(fontNameStr) === 0) { + fontName = baseFont; + } + } + } + fontName = fontName || baseFont; + assert(isName(fontName), 'invalid font name'); + var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3'); + if (fontFile) { + if (fontFile.dict) { + var subtype = fontFile.dict.get('Subtype'); + if (subtype) { + subtype = subtype.name; + } + var length1 = fontFile.dict.get('Length1'); + var length2 = fontFile.dict.get('Length2'); + var length3 = fontFile.dict.get('Length3'); + } + } + properties = { + type: type, + name: fontName.name, + subtype: subtype, + file: fontFile, + length1: length1, + length2: length2, + length3: length3, + loadedName: baseDict.loadedName, + composite: composite, + wideChars: composite, + fixedPitch: false, + fontMatrix: dict.getArray('FontMatrix') || FONT_IDENTITY_MATRIX, + firstChar: firstChar || 0, + lastChar: lastChar || maxCharIndex, + bbox: descriptor.getArray('FontBBox'), + ascent: descriptor.get('Ascent'), + descent: descriptor.get('Descent'), + xHeight: descriptor.get('XHeight'), + capHeight: descriptor.get('CapHeight'), + flags: descriptor.get('Flags'), + italicAngle: descriptor.get('ItalicAngle'), + coded: false + }; + var cMapPromise; + if (composite) { + var cidEncoding = baseDict.get('Encoding'); + if (isName(cidEncoding)) { + properties.cidEncoding = cidEncoding.name; + } + cMapPromise = CMapFactory.create({ + encoding: cidEncoding, + fetchBuiltInCMap: this.fetchBuiltInCMap, + useCMap: null + }).then(function (cMap) { + properties.cMap = cMap; + properties.vertical = properties.cMap.vertical; + }); + } else { + cMapPromise = Promise.resolve(undefined); + } + return cMapPromise.then(function () { + return this.extractDataStructures(dict, baseDict, xref, properties); + }.bind(this)).then(function (properties) { + this.extractWidths(dict, xref, descriptor, properties); + if (type === 'Type3') { + properties.isType3Font = true; + } + return new Font(fontName.name, fontFile, properties); + }.bind(this)); + } + }; + return PartialEvaluator; +}(); +var TranslatedFont = function TranslatedFontClosure() { + function TranslatedFont(loadedName, font, dict) { + this.loadedName = loadedName; + this.font = font; + this.dict = dict; + this.type3Loaded = null; + this.sent = false; + } + TranslatedFont.prototype = { + send: function (handler) { + if (this.sent) { + return; + } + var fontData = this.font.exportData(); + handler.send('commonobj', [ + this.loadedName, + 'Font', + fontData + ]); + this.sent = true; + }, + loadType3Data: function (evaluator, resources, parentOperatorList, task) { + assert(this.font.isType3Font); + if (this.type3Loaded) { + return this.type3Loaded; + } + var translatedFont = this.font; + var loadCharProcsPromise = Promise.resolve(); + var charProcs = this.dict.get('CharProcs'); + var fontResources = this.dict.get('Resources') || resources; + var charProcKeys = charProcs.getKeys(); + var charProcOperatorList = Object.create(null); + for (var i = 0, n = charProcKeys.length; i < n; ++i) { + loadCharProcsPromise = loadCharProcsPromise.then(function (key) { + var glyphStream = charProcs.get(key); + var operatorList = new OperatorList(); + return evaluator.getOperatorList(glyphStream, task, fontResources, operatorList).then(function () { + charProcOperatorList[key] = operatorList.getIR(); + parentOperatorList.addDependencies(operatorList.dependencies); + }, function (reason) { + warn('Type3 font resource \"' + key + '\" is not available'); + var operatorList = new OperatorList(); + charProcOperatorList[key] = operatorList.getIR(); + }); + }.bind(this, charProcKeys[i])); + } + this.type3Loaded = loadCharProcsPromise.then(function () { + translatedFont.charProcOperatorList = charProcOperatorList; + }); + return this.type3Loaded; + } + }; + return TranslatedFont; +}(); +var OperatorList = function OperatorListClosure() { + var CHUNK_SIZE = 1000; + var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; + function getTransfers(queue) { + var transfers = []; + var fnArray = queue.fnArray, argsArray = queue.argsArray; + for (var i = 0, ii = queue.length; i < ii; i++) { + switch (fnArray[i]) { + case OPS.paintInlineImageXObject: + case OPS.paintInlineImageXObjectGroup: + case OPS.paintImageMaskXObject: + var arg = argsArray[i][0]; + if (!arg.cached) { + transfers.push(arg.data.buffer); + } + break; + } + } + return transfers; + } + function OperatorList(intent, messageHandler, pageIndex) { + this.messageHandler = messageHandler; + this.fnArray = []; + this.argsArray = []; + this.dependencies = Object.create(null); + this._totalLength = 0; + this.pageIndex = pageIndex; + this.intent = intent; + } + OperatorList.prototype = { + get length() { + return this.argsArray.length; + }, + get totalLength() { + return this._totalLength + this.length; + }, + addOp: function (fn, args) { + this.fnArray.push(fn); + this.argsArray.push(args); + if (this.messageHandler) { + if (this.fnArray.length >= CHUNK_SIZE) { + this.flush(); + } else if (this.fnArray.length >= CHUNK_SIZE_ABOUT && (fn === OPS.restore || fn === OPS.endText)) { + this.flush(); + } + } + }, + addDependency: function (dependency) { + if (dependency in this.dependencies) { + return; + } + this.dependencies[dependency] = true; + this.addOp(OPS.dependency, [dependency]); + }, + addDependencies: function (dependencies) { + for (var key in dependencies) { + this.addDependency(key); + } + }, + addOpList: function (opList) { + Util.extendObj(this.dependencies, opList.dependencies); + for (var i = 0, ii = opList.length; i < ii; i++) { + this.addOp(opList.fnArray[i], opList.argsArray[i]); + } + }, + getIR: function () { + return { + fnArray: this.fnArray, + argsArray: this.argsArray, + length: this.length + }; + }, + flush: function (lastChunk) { + if (this.intent !== 'oplist') { + new QueueOptimizer().optimize(this); + } + var transfers = getTransfers(this); + var length = this.length; + this._totalLength += length; + this.messageHandler.send('RenderPageChunk', { + operatorList: { + fnArray: this.fnArray, + argsArray: this.argsArray, + lastChunk: lastChunk, + length: length + }, + pageIndex: this.pageIndex, + intent: this.intent + }, transfers); + this.dependencies = Object.create(null); + this.fnArray.length = 0; + this.argsArray.length = 0; + } + }; + return OperatorList; +}(); +var StateManager = function StateManagerClosure() { + function StateManager(initialState) { + this.state = initialState; + this.stateStack = []; + } + StateManager.prototype = { + save: function () { + var old = this.state; + this.stateStack.push(this.state); + this.state = old.clone(); + }, + restore: function () { + var prev = this.stateStack.pop(); + if (prev) { + this.state = prev; + } + }, + transform: function (args) { + this.state.ctm = Util.transform(this.state.ctm, args); + } + }; + return StateManager; +}(); +var TextState = function TextStateClosure() { + function TextState() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.fontName = null; + this.fontSize = 0; + this.font = null; + this.fontMatrix = FONT_IDENTITY_MATRIX; + this.textMatrix = IDENTITY_MATRIX.slice(); + this.textLineMatrix = IDENTITY_MATRIX.slice(); + this.charSpacing = 0; + this.wordSpacing = 0; + this.leading = 0; + this.textHScale = 1; + this.textRise = 0; + } + TextState.prototype = { + setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { + var m = this.textMatrix; + m[0] = a; + m[1] = b; + m[2] = c; + m[3] = d; + m[4] = e; + m[5] = f; + }, + setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { + var m = this.textLineMatrix; + m[0] = a; + m[1] = b; + m[2] = c; + m[3] = d; + m[4] = e; + m[5] = f; + }, + translateTextMatrix: function TextState_translateTextMatrix(x, y) { + var m = this.textMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + }, + translateTextLineMatrix: function TextState_translateTextMatrix(x, y) { + var m = this.textLineMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + }, + calcTextLineMatrixAdvance: function TextState_calcTextLineMatrixAdvance(a, b, c, d, e, f) { + var font = this.font; + if (!font) { + return null; + } + var m = this.textLineMatrix; + if (!(a === m[0] && b === m[1] && c === m[2] && d === m[3])) { + return null; + } + var txDiff = e - m[4], tyDiff = f - m[5]; + if (font.vertical && txDiff !== 0 || !font.vertical && tyDiff !== 0) { + return null; + } + var tx, ty, denominator = a * d - b * c; + if (font.vertical) { + tx = -tyDiff * c / denominator; + ty = tyDiff * a / denominator; + } else { + tx = txDiff * d / denominator; + ty = -txDiff * b / denominator; + } + return { + width: tx, + height: ty, + value: font.vertical ? ty : tx + }; + }, + calcRenderMatrix: function TextState_calcRendeMatrix(ctm) { + var tsm = [ + this.fontSize * this.textHScale, + 0, + 0, + this.fontSize, + 0, + this.textRise + ]; + return Util.transform(ctm, Util.transform(this.textMatrix, tsm)); + }, + carriageReturn: function TextState_carriageReturn() { + this.translateTextLineMatrix(0, -this.leading); + this.textMatrix = this.textLineMatrix.slice(); + }, + clone: function TextState_clone() { + var clone = Object.create(this); + clone.textMatrix = this.textMatrix.slice(); + clone.textLineMatrix = this.textLineMatrix.slice(); + clone.fontMatrix = this.fontMatrix.slice(); + return clone; + } + }; + return TextState; +}(); +var EvalState = function EvalStateClosure() { + function EvalState() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.font = null; + this.textRenderingMode = TextRenderingMode.FILL; + this.fillColorSpace = ColorSpace.singletons.gray; + this.strokeColorSpace = ColorSpace.singletons.gray; + } + EvalState.prototype = { + clone: function CanvasExtraState_clone() { + return Object.create(this); + } + }; + return EvalState; +}(); +var EvaluatorPreprocessor = function EvaluatorPreprocessorClosure() { + var getOPMap = getLookupTableFactory(function (t) { + t['w'] = { + id: OPS.setLineWidth, + numArgs: 1, + variableArgs: false + }; + t['J'] = { + id: OPS.setLineCap, + numArgs: 1, + variableArgs: false + }; + t['j'] = { + id: OPS.setLineJoin, + numArgs: 1, + variableArgs: false + }; + t['M'] = { + id: OPS.setMiterLimit, + numArgs: 1, + variableArgs: false + }; + t['d'] = { + id: OPS.setDash, + numArgs: 2, + variableArgs: false + }; + t['ri'] = { + id: OPS.setRenderingIntent, + numArgs: 1, + variableArgs: false + }; + t['i'] = { + id: OPS.setFlatness, + numArgs: 1, + variableArgs: false + }; + t['gs'] = { + id: OPS.setGState, + numArgs: 1, + variableArgs: false + }; + t['q'] = { + id: OPS.save, + numArgs: 0, + variableArgs: false + }; + t['Q'] = { + id: OPS.restore, + numArgs: 0, + variableArgs: false + }; + t['cm'] = { + id: OPS.transform, + numArgs: 6, + variableArgs: false + }; + t['m'] = { + id: OPS.moveTo, + numArgs: 2, + variableArgs: false + }; + t['l'] = { + id: OPS.lineTo, + numArgs: 2, + variableArgs: false + }; + t['c'] = { + id: OPS.curveTo, + numArgs: 6, + variableArgs: false + }; + t['v'] = { + id: OPS.curveTo2, + numArgs: 4, + variableArgs: false + }; + t['y'] = { + id: OPS.curveTo3, + numArgs: 4, + variableArgs: false + }; + t['h'] = { + id: OPS.closePath, + numArgs: 0, + variableArgs: false + }; + t['re'] = { + id: OPS.rectangle, + numArgs: 4, + variableArgs: false + }; + t['S'] = { + id: OPS.stroke, + numArgs: 0, + variableArgs: false + }; + t['s'] = { + id: OPS.closeStroke, + numArgs: 0, + variableArgs: false + }; + t['f'] = { + id: OPS.fill, + numArgs: 0, + variableArgs: false + }; + t['F'] = { + id: OPS.fill, + numArgs: 0, + variableArgs: false + }; + t['f*'] = { + id: OPS.eoFill, + numArgs: 0, + variableArgs: false + }; + t['B'] = { + id: OPS.fillStroke, + numArgs: 0, + variableArgs: false + }; + t['B*'] = { + id: OPS.eoFillStroke, + numArgs: 0, + variableArgs: false + }; + t['b'] = { + id: OPS.closeFillStroke, + numArgs: 0, + variableArgs: false + }; + t['b*'] = { + id: OPS.closeEOFillStroke, + numArgs: 0, + variableArgs: false + }; + t['n'] = { + id: OPS.endPath, + numArgs: 0, + variableArgs: false + }; + t['W'] = { + id: OPS.clip, + numArgs: 0, + variableArgs: false + }; + t['W*'] = { + id: OPS.eoClip, + numArgs: 0, + variableArgs: false + }; + t['BT'] = { + id: OPS.beginText, + numArgs: 0, + variableArgs: false + }; + t['ET'] = { + id: OPS.endText, + numArgs: 0, + variableArgs: false + }; + t['Tc'] = { + id: OPS.setCharSpacing, + numArgs: 1, + variableArgs: false + }; + t['Tw'] = { + id: OPS.setWordSpacing, + numArgs: 1, + variableArgs: false + }; + t['Tz'] = { + id: OPS.setHScale, + numArgs: 1, + variableArgs: false + }; + t['TL'] = { + id: OPS.setLeading, + numArgs: 1, + variableArgs: false + }; + t['Tf'] = { + id: OPS.setFont, + numArgs: 2, + variableArgs: false + }; + t['Tr'] = { + id: OPS.setTextRenderingMode, + numArgs: 1, + variableArgs: false + }; + t['Ts'] = { + id: OPS.setTextRise, + numArgs: 1, + variableArgs: false + }; + t['Td'] = { + id: OPS.moveText, + numArgs: 2, + variableArgs: false + }; + t['TD'] = { + id: OPS.setLeadingMoveText, + numArgs: 2, + variableArgs: false + }; + t['Tm'] = { + id: OPS.setTextMatrix, + numArgs: 6, + variableArgs: false + }; + t['T*'] = { + id: OPS.nextLine, + numArgs: 0, + variableArgs: false + }; + t['Tj'] = { + id: OPS.showText, + numArgs: 1, + variableArgs: false + }; + t['TJ'] = { + id: OPS.showSpacedText, + numArgs: 1, + variableArgs: false + }; + t['\''] = { + id: OPS.nextLineShowText, + numArgs: 1, + variableArgs: false + }; + t['"'] = { + id: OPS.nextLineSetSpacingShowText, + numArgs: 3, + variableArgs: false + }; + t['d0'] = { + id: OPS.setCharWidth, + numArgs: 2, + variableArgs: false + }; + t['d1'] = { + id: OPS.setCharWidthAndBounds, + numArgs: 6, + variableArgs: false + }; + t['CS'] = { + id: OPS.setStrokeColorSpace, + numArgs: 1, + variableArgs: false + }; + t['cs'] = { + id: OPS.setFillColorSpace, + numArgs: 1, + variableArgs: false + }; + t['SC'] = { + id: OPS.setStrokeColor, + numArgs: 4, + variableArgs: true + }; + t['SCN'] = { + id: OPS.setStrokeColorN, + numArgs: 33, + variableArgs: true + }; + t['sc'] = { + id: OPS.setFillColor, + numArgs: 4, + variableArgs: true + }; + t['scn'] = { + id: OPS.setFillColorN, + numArgs: 33, + variableArgs: true + }; + t['G'] = { + id: OPS.setStrokeGray, + numArgs: 1, + variableArgs: false + }; + t['g'] = { + id: OPS.setFillGray, + numArgs: 1, + variableArgs: false + }; + t['RG'] = { + id: OPS.setStrokeRGBColor, + numArgs: 3, + variableArgs: false + }; + t['rg'] = { + id: OPS.setFillRGBColor, + numArgs: 3, + variableArgs: false + }; + t['K'] = { + id: OPS.setStrokeCMYKColor, + numArgs: 4, + variableArgs: false + }; + t['k'] = { + id: OPS.setFillCMYKColor, + numArgs: 4, + variableArgs: false + }; + t['sh'] = { + id: OPS.shadingFill, + numArgs: 1, + variableArgs: false + }; + t['BI'] = { + id: OPS.beginInlineImage, + numArgs: 0, + variableArgs: false + }; + t['ID'] = { + id: OPS.beginImageData, + numArgs: 0, + variableArgs: false + }; + t['EI'] = { + id: OPS.endInlineImage, + numArgs: 1, + variableArgs: false + }; + t['Do'] = { + id: OPS.paintXObject, + numArgs: 1, + variableArgs: false + }; + t['MP'] = { + id: OPS.markPoint, + numArgs: 1, + variableArgs: false + }; + t['DP'] = { + id: OPS.markPointProps, + numArgs: 2, + variableArgs: false + }; + t['BMC'] = { + id: OPS.beginMarkedContent, + numArgs: 1, + variableArgs: false + }; + t['BDC'] = { + id: OPS.beginMarkedContentProps, + numArgs: 2, + variableArgs: false + }; + t['EMC'] = { + id: OPS.endMarkedContent, + numArgs: 0, + variableArgs: false + }; + t['BX'] = { + id: OPS.beginCompat, + numArgs: 0, + variableArgs: false + }; + t['EX'] = { + id: OPS.endCompat, + numArgs: 0, + variableArgs: false + }; + t['BM'] = null; + t['BD'] = null; + t['true'] = null; + t['fa'] = null; + t['fal'] = null; + t['fals'] = null; + t['false'] = null; + t['nu'] = null; + t['nul'] = null; + t['null'] = null; + }); + function EvaluatorPreprocessor(stream, xref, stateManager) { + this.opMap = getOPMap(); + this.parser = new Parser(new Lexer(stream, this.opMap), false, xref); + this.stateManager = stateManager; + this.nonProcessedArgs = []; + } + EvaluatorPreprocessor.prototype = { + get savedStatesDepth() { + return this.stateManager.stateStack.length; + }, + read: function EvaluatorPreprocessor_read(operation) { + var args = operation.args; + while (true) { + var obj = this.parser.getObj(); + if (isCmd(obj)) { + var cmd = obj.cmd; + var opSpec = this.opMap[cmd]; + if (!opSpec) { + warn('Unknown command "' + cmd + '"'); + continue; + } + var fn = opSpec.id; + var numArgs = opSpec.numArgs; + var argsLength = args !== null ? args.length : 0; + if (!opSpec.variableArgs) { + if (argsLength !== numArgs) { + var nonProcessedArgs = this.nonProcessedArgs; + while (argsLength > numArgs) { + nonProcessedArgs.push(args.shift()); + argsLength--; + } + while (argsLength < numArgs && nonProcessedArgs.length !== 0) { + if (args === null) { + args = []; + } + args.unshift(nonProcessedArgs.pop()); + argsLength++; + } + } + if (argsLength < numArgs) { + warn('Skipping command ' + fn + ': expected ' + numArgs + ' args, but received ' + argsLength + ' args.'); + if (args !== null) { + args.length = 0; + } + continue; + } + } else if (argsLength > numArgs) { + info('Command ' + fn + ': expected [0,' + numArgs + '] args, but received ' + argsLength + ' args.'); + } + this.preprocessCommand(fn, args); + operation.fn = fn; + operation.args = args; + return true; + } + if (isEOF(obj)) { + return false; + } + if (obj !== null) { + if (args === null) { + args = []; + } + args.push(obj); + assert(args.length <= 33, 'Too many arguments'); + } + } + }, + preprocessCommand: function EvaluatorPreprocessor_preprocessCommand(fn, args) { + switch (fn | 0) { + case OPS.save: + this.stateManager.save(); + break; + case OPS.restore: + this.stateManager.restore(); + break; + case OPS.transform: + this.stateManager.transform(args); + break; + } + } + }; + return EvaluatorPreprocessor; +}(); +var QueueOptimizer = function QueueOptimizerClosure() { + function addState(parentState, pattern, fn) { + var state = parentState; + for (var i = 0, ii = pattern.length - 1; i < ii; i++) { + var item = pattern[i]; + state = state[item] || (state[item] = []); + } + state[pattern[pattern.length - 1]] = fn; + } + function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray) { + var iFirstPIMXO = iFirstSave + 2; + for (var i = 0; i < count; i++) { + var arg = argsArray[iFirstPIMXO + 4 * i]; + var imageMask = arg.length === 1 && arg[0]; + if (imageMask && imageMask.width === 1 && imageMask.height === 1 && (!imageMask.data.length || imageMask.data.length === 1 && imageMask.data[0] === 0)) { + fnArray[iFirstPIMXO + 4 * i] = OPS.paintSolidColorImageMask; + continue; + } + break; + } + return count - i; + } + var InitialState = []; + addState(InitialState, [ + OPS.save, + OPS.transform, + OPS.paintInlineImageXObject, + OPS.restore + ], function foundInlineImageGroup(context) { + var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10; + var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200; + var MAX_WIDTH = 1000; + var IMAGE_PADDING = 1; + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstSave = curr - 3; + var iFirstTransform = curr - 2; + var iFirstPIIXO = curr - 1; + var i = iFirstSave + 4; + var ii = fnArray.length; + while (i + 3 < ii) { + if (fnArray[i] !== OPS.save || fnArray[i + 1] !== OPS.transform || fnArray[i + 2] !== OPS.paintInlineImageXObject || fnArray[i + 3] !== OPS.restore) { + break; + } + i += 4; + } + var count = Math.min((i - iFirstSave) / 4, MAX_IMAGES_IN_INLINE_IMAGES_BLOCK); + if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) { + return i; + } + var maxX = 0; + var map = [], maxLineHeight = 0; + var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING; + var q; + for (q = 0; q < count; q++) { + var transform = argsArray[iFirstTransform + (q << 2)]; + var img = argsArray[iFirstPIIXO + (q << 2)][0]; + if (currentX + img.width > MAX_WIDTH) { + maxX = Math.max(maxX, currentX); + currentY += maxLineHeight + 2 * IMAGE_PADDING; + currentX = 0; + maxLineHeight = 0; + } + map.push({ + transform: transform, + x: currentX, + y: currentY, + w: img.width, + h: img.height + }); + currentX += img.width + 2 * IMAGE_PADDING; + maxLineHeight = Math.max(maxLineHeight, img.height); + } + var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING; + var imgHeight = currentY + maxLineHeight + IMAGE_PADDING; + var imgData = new Uint8Array(imgWidth * imgHeight * 4); + var imgRowSize = imgWidth << 2; + for (q = 0; q < count; q++) { + var data = argsArray[iFirstPIIXO + (q << 2)][0].data; + var rowSize = map[q].w << 2; + var dataOffset = 0; + var offset = map[q].x + map[q].y * imgWidth << 2; + imgData.set(data.subarray(0, rowSize), offset - imgRowSize); + for (var k = 0, kk = map[q].h; k < kk; k++) { + imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset); + dataOffset += rowSize; + offset += imgRowSize; + } + imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset); + while (offset >= 0) { + data[offset - 4] = data[offset]; + data[offset - 3] = data[offset + 1]; + data[offset - 2] = data[offset + 2]; + data[offset - 1] = data[offset + 3]; + data[offset + rowSize] = data[offset + rowSize - 4]; + data[offset + rowSize + 1] = data[offset + rowSize - 3]; + data[offset + rowSize + 2] = data[offset + rowSize - 2]; + data[offset + rowSize + 3] = data[offset + rowSize - 1]; + offset -= imgRowSize; + } + } + fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup); + argsArray.splice(iFirstSave, count * 4, [ + { + width: imgWidth, + height: imgHeight, + kind: ImageKind.RGBA_32BPP, + data: imgData + }, + map + ]); + return iFirstSave + 1; + }); + addState(InitialState, [ + OPS.save, + OPS.transform, + OPS.paintImageMaskXObject, + OPS.restore + ], function foundImageMaskGroup(context) { + var MIN_IMAGES_IN_MASKS_BLOCK = 10; + var MAX_IMAGES_IN_MASKS_BLOCK = 100; + var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000; + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstSave = curr - 3; + var iFirstTransform = curr - 2; + var iFirstPIMXO = curr - 1; + var i = iFirstSave + 4; + var ii = fnArray.length; + while (i + 3 < ii) { + if (fnArray[i] !== OPS.save || fnArray[i + 1] !== OPS.transform || fnArray[i + 2] !== OPS.paintImageMaskXObject || fnArray[i + 3] !== OPS.restore) { + break; + } + i += 4; + } + var count = (i - iFirstSave) / 4; + count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray); + if (count < MIN_IMAGES_IN_MASKS_BLOCK) { + return i; + } + var q; + var isSameImage = false; + var iTransform, transformArgs; + var firstPIMXOArg0 = argsArray[iFirstPIMXO][0]; + if (argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0) { + isSameImage = true; + var firstTransformArg0 = argsArray[iFirstTransform][0]; + var firstTransformArg3 = argsArray[iFirstTransform][3]; + iTransform = iFirstTransform + 4; + var iPIMXO = iFirstPIMXO + 4; + for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) { + transformArgs = argsArray[iTransform]; + if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== 0 || transformArgs[2] !== 0 || transformArgs[3] !== firstTransformArg3) { + if (q < MIN_IMAGES_IN_MASKS_BLOCK) { + isSameImage = false; + } else { + count = q; + } + break; + } + } + } + if (isSameImage) { + count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK); + var positions = new Float32Array(count * 2); + iTransform = iFirstTransform; + for (q = 0; q < count; q++, iTransform += 4) { + transformArgs = argsArray[iTransform]; + positions[q << 1] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, [ + firstPIMXOArg0, + firstTransformArg0, + firstTransformArg3, + positions + ]); + } else { + count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK); + var images = []; + for (q = 0; q < count; q++) { + transformArgs = argsArray[iFirstTransform + (q << 2)]; + var maskParams = argsArray[iFirstPIMXO + (q << 2)][0]; + images.push({ + data: maskParams.data, + width: maskParams.width, + height: maskParams.height, + transform: transformArgs + }); + } + fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectGroup); + argsArray.splice(iFirstSave, count * 4, [images]); + } + return iFirstSave + 1; + }); + addState(InitialState, [ + OPS.save, + OPS.transform, + OPS.paintImageXObject, + OPS.restore + ], function (context) { + var MIN_IMAGES_IN_BLOCK = 3; + var MAX_IMAGES_IN_BLOCK = 1000; + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstSave = curr - 3; + var iFirstTransform = curr - 2; + var iFirstPIXO = curr - 1; + var iFirstRestore = curr; + if (argsArray[iFirstTransform][1] !== 0 || argsArray[iFirstTransform][2] !== 0) { + return iFirstRestore + 1; + } + var firstPIXOArg0 = argsArray[iFirstPIXO][0]; + var firstTransformArg0 = argsArray[iFirstTransform][0]; + var firstTransformArg3 = argsArray[iFirstTransform][3]; + var i = iFirstSave + 4; + var ii = fnArray.length; + while (i + 3 < ii) { + if (fnArray[i] !== OPS.save || fnArray[i + 1] !== OPS.transform || fnArray[i + 2] !== OPS.paintImageXObject || fnArray[i + 3] !== OPS.restore) { + break; + } + if (argsArray[i + 1][0] !== firstTransformArg0 || argsArray[i + 1][1] !== 0 || argsArray[i + 1][2] !== 0 || argsArray[i + 1][3] !== firstTransformArg3) { + break; + } + if (argsArray[i + 2][0] !== firstPIXOArg0) { + break; + } + i += 4; + } + var count = Math.min((i - iFirstSave) / 4, MAX_IMAGES_IN_BLOCK); + if (count < MIN_IMAGES_IN_BLOCK) { + return i; + } + var positions = new Float32Array(count * 2); + var iTransform = iFirstTransform; + for (var q = 0; q < count; q++, iTransform += 4) { + var transformArgs = argsArray[iTransform]; + positions[q << 1] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + var args = [ + firstPIXOArg0, + firstTransformArg0, + firstTransformArg3, + positions + ]; + fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, args); + return iFirstSave + 1; + }); + addState(InitialState, [ + OPS.beginText, + OPS.setFont, + OPS.setTextMatrix, + OPS.showText, + OPS.endText + ], function (context) { + var MIN_CHARS_IN_BLOCK = 3; + var MAX_CHARS_IN_BLOCK = 1000; + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstBeginText = curr - 4; + var iFirstSetFont = curr - 3; + var iFirstSetTextMatrix = curr - 2; + var iFirstShowText = curr - 1; + var iFirstEndText = curr; + var firstSetFontArg0 = argsArray[iFirstSetFont][0]; + var firstSetFontArg1 = argsArray[iFirstSetFont][1]; + var i = iFirstBeginText + 5; + var ii = fnArray.length; + while (i + 4 < ii) { + if (fnArray[i] !== OPS.beginText || fnArray[i + 1] !== OPS.setFont || fnArray[i + 2] !== OPS.setTextMatrix || fnArray[i + 3] !== OPS.showText || fnArray[i + 4] !== OPS.endText) { + break; + } + if (argsArray[i + 1][0] !== firstSetFontArg0 || argsArray[i + 1][1] !== firstSetFontArg1) { + break; + } + i += 5; + } + var count = Math.min((i - iFirstBeginText) / 5, MAX_CHARS_IN_BLOCK); + if (count < MIN_CHARS_IN_BLOCK) { + return i; + } + var iFirst = iFirstBeginText; + if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) { + count++; + iFirst -= 5; + } + var iEndText = iFirst + 4; + for (var q = 1; q < count; q++) { + fnArray.splice(iEndText, 3); + argsArray.splice(iEndText, 3); + iEndText += 2; + } + return iEndText + 1; + }); + function QueueOptimizer() { + } + QueueOptimizer.prototype = { + optimize: function QueueOptimizer_optimize(queue) { + var fnArray = queue.fnArray, argsArray = queue.argsArray; + var context = { + iCurr: 0, + fnArray: fnArray, + argsArray: argsArray + }; + var state; + var i = 0, ii = fnArray.length; + while (i < ii) { + state = (state || InitialState)[fnArray[i]]; + if (typeof state === 'function') { + context.iCurr = i; + i = state(context); + state = undefined; + ii = context.fnArray.length; + } else { + i++; + } + } + } + }; + return QueueOptimizer; +}(); +exports.OperatorList = OperatorList; +exports.PartialEvaluator = PartialEvaluator; + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var coreArithmeticDecoder = __w_pdfjs_require__(10); +var info = sharedUtil.info; +var warn = sharedUtil.warn; +var error = sharedUtil.error; +var log2 = sharedUtil.log2; +var readUint16 = sharedUtil.readUint16; +var readUint32 = sharedUtil.readUint32; +var ArithmeticDecoder = coreArithmeticDecoder.ArithmeticDecoder; +var JpxImage = function JpxImageClosure() { + var SubbandsGainLog2 = { + 'LL': 0, + 'LH': 1, + 'HL': 1, + 'HH': 2 + }; + function JpxImage() { + this.failOnCorruptedImage = false; + } + JpxImage.prototype = { + parse: function JpxImage_parse(data) { + var head = readUint16(data, 0); + if (head === 0xFF4F) { + this.parseCodestream(data, 0, data.length); + return; + } + var position = 0, length = data.length; + while (position < length) { + var headerSize = 8; + var lbox = readUint32(data, position); + var tbox = readUint32(data, position + 4); + position += headerSize; + if (lbox === 1) { + lbox = readUint32(data, position) * 4294967296 + readUint32(data, position + 4); + position += 8; + headerSize += 8; + } + if (lbox === 0) { + lbox = length - position + headerSize; + } + if (lbox < headerSize) { + error('JPX Error: Invalid box field size'); + } + var dataLength = lbox - headerSize; + var jumpDataLength = true; + switch (tbox) { + case 0x6A703268: + jumpDataLength = false; + break; + case 0x636F6C72: + var method = data[position]; + if (method === 1) { + var colorspace = readUint32(data, position + 3); + switch (colorspace) { + case 16: + case 17: + case 18: + break; + default: + warn('Unknown colorspace ' + colorspace); + break; + } + } else if (method === 2) { + info('ICC profile not supported'); + } + break; + case 0x6A703263: + this.parseCodestream(data, position, position + dataLength); + break; + case 0x6A502020: + if (0x0d0a870a !== readUint32(data, position)) { + warn('Invalid JP2 signature'); + } + break; + case 0x6A501A1A: + case 0x66747970: + case 0x72726571: + case 0x72657320: + case 0x69686472: + break; + default: + var headerType = String.fromCharCode(tbox >> 24 & 0xFF, tbox >> 16 & 0xFF, tbox >> 8 & 0xFF, tbox & 0xFF); + warn('Unsupported header type ' + tbox + ' (' + headerType + ')'); + break; + } + if (jumpDataLength) { + position += dataLength; + } + } + }, + parseImageProperties: function JpxImage_parseImageProperties(stream) { + var newByte = stream.getByte(); + while (newByte >= 0) { + var oldByte = newByte; + newByte = stream.getByte(); + var code = oldByte << 8 | newByte; + if (code === 0xFF51) { + stream.skip(4); + var Xsiz = stream.getInt32() >>> 0; + var Ysiz = stream.getInt32() >>> 0; + var XOsiz = stream.getInt32() >>> 0; + var YOsiz = stream.getInt32() >>> 0; + stream.skip(16); + var Csiz = stream.getUint16(); + this.width = Xsiz - XOsiz; + this.height = Ysiz - YOsiz; + this.componentsCount = Csiz; + this.bitsPerComponent = 8; + return; + } + } + error('JPX Error: No size marker found in JPX stream'); + }, + parseCodestream: function JpxImage_parseCodestream(data, start, end) { + var context = {}; + var doNotRecover = false; + try { + var position = start; + while (position + 1 < end) { + var code = readUint16(data, position); + position += 2; + var length = 0, j, sqcd, spqcds, spqcdSize, scalarExpounded, tile; + switch (code) { + case 0xFF4F: + context.mainHeader = true; + break; + case 0xFFD9: + break; + case 0xFF51: + length = readUint16(data, position); + var siz = {}; + siz.Xsiz = readUint32(data, position + 4); + siz.Ysiz = readUint32(data, position + 8); + siz.XOsiz = readUint32(data, position + 12); + siz.YOsiz = readUint32(data, position + 16); + siz.XTsiz = readUint32(data, position + 20); + siz.YTsiz = readUint32(data, position + 24); + siz.XTOsiz = readUint32(data, position + 28); + siz.YTOsiz = readUint32(data, position + 32); + var componentsCount = readUint16(data, position + 36); + siz.Csiz = componentsCount; + var components = []; + j = position + 38; + for (var i = 0; i < componentsCount; i++) { + var component = { + precision: (data[j] & 0x7F) + 1, + isSigned: !!(data[j] & 0x80), + XRsiz: data[j + 1], + YRsiz: data[j + 1] + }; + calculateComponentDimensions(component, siz); + components.push(component); + } + context.SIZ = siz; + context.components = components; + calculateTileGrids(context, components); + context.QCC = []; + context.COC = []; + break; + case 0xFF5C: + length = readUint16(data, position); + var qcd = {}; + j = position + 2; + sqcd = data[j++]; + switch (sqcd & 0x1F) { + case 0: + spqcdSize = 8; + scalarExpounded = true; + break; + case 1: + spqcdSize = 16; + scalarExpounded = false; + break; + case 2: + spqcdSize = 16; + scalarExpounded = true; + break; + default: + throw new Error('Invalid SQcd value ' + sqcd); + } + qcd.noQuantization = spqcdSize === 8; + qcd.scalarExpounded = scalarExpounded; + qcd.guardBits = sqcd >> 5; + spqcds = []; + while (j < length + position) { + var spqcd = {}; + if (spqcdSize === 8) { + spqcd.epsilon = data[j++] >> 3; + spqcd.mu = 0; + } else { + spqcd.epsilon = data[j] >> 3; + spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1]; + j += 2; + } + spqcds.push(spqcd); + } + qcd.SPqcds = spqcds; + if (context.mainHeader) { + context.QCD = qcd; + } else { + context.currentTile.QCD = qcd; + context.currentTile.QCC = []; + } + break; + case 0xFF5D: + length = readUint16(data, position); + var qcc = {}; + j = position + 2; + var cqcc; + if (context.SIZ.Csiz < 257) { + cqcc = data[j++]; + } else { + cqcc = readUint16(data, j); + j += 2; + } + sqcd = data[j++]; + switch (sqcd & 0x1F) { + case 0: + spqcdSize = 8; + scalarExpounded = true; + break; + case 1: + spqcdSize = 16; + scalarExpounded = false; + break; + case 2: + spqcdSize = 16; + scalarExpounded = true; + break; + default: + throw new Error('Invalid SQcd value ' + sqcd); + } + qcc.noQuantization = spqcdSize === 8; + qcc.scalarExpounded = scalarExpounded; + qcc.guardBits = sqcd >> 5; + spqcds = []; + while (j < length + position) { + spqcd = {}; + if (spqcdSize === 8) { + spqcd.epsilon = data[j++] >> 3; + spqcd.mu = 0; + } else { + spqcd.epsilon = data[j] >> 3; + spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1]; + j += 2; + } + spqcds.push(spqcd); + } + qcc.SPqcds = spqcds; + if (context.mainHeader) { + context.QCC[cqcc] = qcc; + } else { + context.currentTile.QCC[cqcc] = qcc; + } + break; + case 0xFF52: + length = readUint16(data, position); + var cod = {}; + j = position + 2; + var scod = data[j++]; + cod.entropyCoderWithCustomPrecincts = !!(scod & 1); + cod.sopMarkerUsed = !!(scod & 2); + cod.ephMarkerUsed = !!(scod & 4); + cod.progressionOrder = data[j++]; + cod.layersCount = readUint16(data, j); + j += 2; + cod.multipleComponentTransform = data[j++]; + cod.decompositionLevelsCount = data[j++]; + cod.xcb = (data[j++] & 0xF) + 2; + cod.ycb = (data[j++] & 0xF) + 2; + var blockStyle = data[j++]; + cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1); + cod.resetContextProbabilities = !!(blockStyle & 2); + cod.terminationOnEachCodingPass = !!(blockStyle & 4); + cod.verticalyStripe = !!(blockStyle & 8); + cod.predictableTermination = !!(blockStyle & 16); + cod.segmentationSymbolUsed = !!(blockStyle & 32); + cod.reversibleTransformation = data[j++]; + if (cod.entropyCoderWithCustomPrecincts) { + var precinctsSizes = []; + while (j < length + position) { + var precinctsSize = data[j++]; + precinctsSizes.push({ + PPx: precinctsSize & 0xF, + PPy: precinctsSize >> 4 + }); + } + cod.precinctsSizes = precinctsSizes; + } + var unsupported = []; + if (cod.selectiveArithmeticCodingBypass) { + unsupported.push('selectiveArithmeticCodingBypass'); + } + if (cod.resetContextProbabilities) { + unsupported.push('resetContextProbabilities'); + } + if (cod.terminationOnEachCodingPass) { + unsupported.push('terminationOnEachCodingPass'); + } + if (cod.verticalyStripe) { + unsupported.push('verticalyStripe'); + } + if (cod.predictableTermination) { + unsupported.push('predictableTermination'); + } + if (unsupported.length > 0) { + doNotRecover = true; + throw new Error('Unsupported COD options (' + unsupported.join(', ') + ')'); + } + if (context.mainHeader) { + context.COD = cod; + } else { + context.currentTile.COD = cod; + context.currentTile.COC = []; + } + break; + case 0xFF90: + length = readUint16(data, position); + tile = {}; + tile.index = readUint16(data, position + 2); + tile.length = readUint32(data, position + 4); + tile.dataEnd = tile.length + position - 2; + tile.partIndex = data[position + 8]; + tile.partsCount = data[position + 9]; + context.mainHeader = false; + if (tile.partIndex === 0) { + tile.COD = context.COD; + tile.COC = context.COC.slice(0); + tile.QCD = context.QCD; + tile.QCC = context.QCC.slice(0); + } + context.currentTile = tile; + break; + case 0xFF93: + tile = context.currentTile; + if (tile.partIndex === 0) { + initializeTile(context, tile.index); + buildPackets(context); + } + length = tile.dataEnd - position; + parseTilePackets(context, data, position, length); + break; + case 0xFF55: + case 0xFF57: + case 0xFF58: + case 0xFF64: + length = readUint16(data, position); + break; + case 0xFF53: + throw new Error('Codestream code 0xFF53 (COC) is ' + 'not implemented'); + default: + throw new Error('Unknown codestream code: ' + code.toString(16)); + } + position += length; + } + } catch (e) { + if (doNotRecover || this.failOnCorruptedImage) { + error('JPX Error: ' + e.message); + } else { + warn('JPX: Trying to recover from: ' + e.message); + } + } + this.tiles = transformComponents(context); + this.width = context.SIZ.Xsiz - context.SIZ.XOsiz; + this.height = context.SIZ.Ysiz - context.SIZ.YOsiz; + this.componentsCount = context.SIZ.Csiz; + } + }; + function calculateComponentDimensions(component, siz) { + component.x0 = Math.ceil(siz.XOsiz / component.XRsiz); + component.x1 = Math.ceil(siz.Xsiz / component.XRsiz); + component.y0 = Math.ceil(siz.YOsiz / component.YRsiz); + component.y1 = Math.ceil(siz.Ysiz / component.YRsiz); + component.width = component.x1 - component.x0; + component.height = component.y1 - component.y0; + } + function calculateTileGrids(context, components) { + var siz = context.SIZ; + var tile, tiles = []; + var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz); + var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz); + for (var q = 0; q < numYtiles; q++) { + for (var p = 0; p < numXtiles; p++) { + tile = {}; + tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz); + tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz); + tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz); + tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz); + tile.width = tile.tx1 - tile.tx0; + tile.height = tile.ty1 - tile.ty0; + tile.components = []; + tiles.push(tile); + } + } + context.tiles = tiles; + var componentsCount = siz.Csiz; + for (var i = 0, ii = componentsCount; i < ii; i++) { + var component = components[i]; + for (var j = 0, jj = tiles.length; j < jj; j++) { + var tileComponent = {}; + tile = tiles[j]; + tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz); + tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz); + tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz); + tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz); + tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0; + tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0; + tile.components[i] = tileComponent; + } + } + } + function getBlocksDimensions(context, component, r) { + var codOrCoc = component.codingStyleParameters; + var result = {}; + if (!codOrCoc.entropyCoderWithCustomPrecincts) { + result.PPx = 15; + result.PPy = 15; + } else { + result.PPx = codOrCoc.precinctsSizes[r].PPx; + result.PPy = codOrCoc.precinctsSizes[r].PPy; + } + result.xcb_ = r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : Math.min(codOrCoc.xcb, result.PPx); + result.ycb_ = r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : Math.min(codOrCoc.ycb, result.PPy); + return result; + } + function buildPrecincts(context, resolution, dimensions) { + var precinctWidth = 1 << dimensions.PPx; + var precinctHeight = 1 << dimensions.PPy; + var isZeroRes = resolution.resLevel === 0; + var precinctWidthInSubband = 1 << dimensions.PPx + (isZeroRes ? 0 : -1); + var precinctHeightInSubband = 1 << dimensions.PPy + (isZeroRes ? 0 : -1); + var numprecinctswide = resolution.trx1 > resolution.trx0 ? Math.ceil(resolution.trx1 / precinctWidth) - Math.floor(resolution.trx0 / precinctWidth) : 0; + var numprecinctshigh = resolution.try1 > resolution.try0 ? Math.ceil(resolution.try1 / precinctHeight) - Math.floor(resolution.try0 / precinctHeight) : 0; + var numprecincts = numprecinctswide * numprecinctshigh; + resolution.precinctParameters = { + precinctWidth: precinctWidth, + precinctHeight: precinctHeight, + numprecinctswide: numprecinctswide, + numprecinctshigh: numprecinctshigh, + numprecincts: numprecincts, + precinctWidthInSubband: precinctWidthInSubband, + precinctHeightInSubband: precinctHeightInSubband + }; + } + function buildCodeblocks(context, subband, dimensions) { + var xcb_ = dimensions.xcb_; + var ycb_ = dimensions.ycb_; + var codeblockWidth = 1 << xcb_; + var codeblockHeight = 1 << ycb_; + var cbx0 = subband.tbx0 >> xcb_; + var cby0 = subband.tby0 >> ycb_; + var cbx1 = subband.tbx1 + codeblockWidth - 1 >> xcb_; + var cby1 = subband.tby1 + codeblockHeight - 1 >> ycb_; + var precinctParameters = subband.resolution.precinctParameters; + var codeblocks = []; + var precincts = []; + var i, j, codeblock, precinctNumber; + for (j = cby0; j < cby1; j++) { + for (i = cbx0; i < cbx1; i++) { + codeblock = { + cbx: i, + cby: j, + tbx0: codeblockWidth * i, + tby0: codeblockHeight * j, + tbx1: codeblockWidth * (i + 1), + tby1: codeblockHeight * (j + 1) + }; + codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0); + codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0); + codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1); + codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1); + var pi = Math.floor((codeblock.tbx0_ - subband.tbx0) / precinctParameters.precinctWidthInSubband); + var pj = Math.floor((codeblock.tby0_ - subband.tby0) / precinctParameters.precinctHeightInSubband); + precinctNumber = pi + pj * precinctParameters.numprecinctswide; + codeblock.precinctNumber = precinctNumber; + codeblock.subbandType = subband.type; + codeblock.Lblock = 3; + if (codeblock.tbx1_ <= codeblock.tbx0_ || codeblock.tby1_ <= codeblock.tby0_) { + continue; + } + codeblocks.push(codeblock); + var precinct = precincts[precinctNumber]; + if (precinct !== undefined) { + if (i < precinct.cbxMin) { + precinct.cbxMin = i; + } else if (i > precinct.cbxMax) { + precinct.cbxMax = i; + } + if (j < precinct.cbyMin) { + precinct.cbxMin = j; + } else if (j > precinct.cbyMax) { + precinct.cbyMax = j; + } + } else { + precincts[precinctNumber] = precinct = { + cbxMin: i, + cbyMin: j, + cbxMax: i, + cbyMax: j + }; + } + codeblock.precinct = precinct; + } + } + subband.codeblockParameters = { + codeblockWidth: xcb_, + codeblockHeight: ycb_, + numcodeblockwide: cbx1 - cbx0 + 1, + numcodeblockhigh: cby1 - cby0 + 1 + }; + subband.codeblocks = codeblocks; + subband.precincts = precincts; + } + function createPacket(resolution, precinctNumber, layerNumber) { + var precinctCodeblocks = []; + var subbands = resolution.subbands; + for (var i = 0, ii = subbands.length; i < ii; i++) { + var subband = subbands[i]; + var codeblocks = subband.codeblocks; + for (var j = 0, jj = codeblocks.length; j < jj; j++) { + var codeblock = codeblocks[j]; + if (codeblock.precinctNumber !== precinctNumber) { + continue; + } + precinctCodeblocks.push(codeblock); + } + } + return { + layerNumber: layerNumber, + codeblocks: precinctCodeblocks + }; + } + function LayerResolutionComponentPositionIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var maxDecompositionLevelsCount = 0; + for (var q = 0; q < componentsCount; q++) { + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount); + } + var l = 0, r = 0, i = 0, k = 0; + this.nextPacket = function JpxImage_nextPacket() { + for (; l < layersCount; l++) { + for (; r <= maxDecompositionLevelsCount; r++) { + for (; i < componentsCount; i++) { + var component = tile.components[i]; + if (r > component.codingStyleParameters.decompositionLevelsCount) { + continue; + } + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + for (; k < numprecincts;) { + var packet = createPacket(resolution, k, l); + k++; + return packet; + } + k = 0; + } + i = 0; + } + r = 0; + } + error('JPX Error: Out of packets'); + }; + } + function ResolutionLayerComponentPositionIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var maxDecompositionLevelsCount = 0; + for (var q = 0; q < componentsCount; q++) { + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount); + } + var r = 0, l = 0, i = 0, k = 0; + this.nextPacket = function JpxImage_nextPacket() { + for (; r <= maxDecompositionLevelsCount; r++) { + for (; l < layersCount; l++) { + for (; i < componentsCount; i++) { + var component = tile.components[i]; + if (r > component.codingStyleParameters.decompositionLevelsCount) { + continue; + } + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + for (; k < numprecincts;) { + var packet = createPacket(resolution, k, l); + k++; + return packet; + } + k = 0; + } + i = 0; + } + l = 0; + } + error('JPX Error: Out of packets'); + }; + } + function ResolutionPositionComponentLayerIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var l, r, c, p; + var maxDecompositionLevelsCount = 0; + for (c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, component.codingStyleParameters.decompositionLevelsCount); + } + var maxNumPrecinctsInLevel = new Int32Array(maxDecompositionLevelsCount + 1); + for (r = 0; r <= maxDecompositionLevelsCount; ++r) { + var maxNumPrecincts = 0; + for (c = 0; c < componentsCount; ++c) { + var resolutions = tile.components[c].resolutions; + if (r < resolutions.length) { + maxNumPrecincts = Math.max(maxNumPrecincts, resolutions[r].precinctParameters.numprecincts); + } + } + maxNumPrecinctsInLevel[r] = maxNumPrecincts; + } + l = 0; + r = 0; + c = 0; + p = 0; + this.nextPacket = function JpxImage_nextPacket() { + for (; r <= maxDecompositionLevelsCount; r++) { + for (; p < maxNumPrecinctsInLevel[r]; p++) { + for (; c < componentsCount; c++) { + var component = tile.components[c]; + if (r > component.codingStyleParameters.decompositionLevelsCount) { + continue; + } + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + if (p >= numprecincts) { + continue; + } + for (; l < layersCount;) { + var packet = createPacket(resolution, p, l); + l++; + return packet; + } + l = 0; + } + c = 0; + } + p = 0; + } + error('JPX Error: Out of packets'); + }; + } + function PositionComponentResolutionLayerIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var precinctsSizes = getPrecinctSizesInImageScale(tile); + var precinctsIterationSizes = precinctsSizes; + var l = 0, r = 0, c = 0, px = 0, py = 0; + this.nextPacket = function JpxImage_nextPacket() { + for (; py < precinctsIterationSizes.maxNumHigh; py++) { + for (; px < precinctsIterationSizes.maxNumWide; px++) { + for (; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount; + for (; r <= decompositionLevelsCount; r++) { + var resolution = component.resolutions[r]; + var sizeInImageScale = precinctsSizes.components[c].resolutions[r]; + var k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution); + if (k === null) { + continue; + } + for (; l < layersCount;) { + var packet = createPacket(resolution, k, l); + l++; + return packet; + } + l = 0; + } + r = 0; + } + c = 0; + } + px = 0; + } + error('JPX Error: Out of packets'); + }; + } + function ComponentPositionResolutionLayerIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var precinctsSizes = getPrecinctSizesInImageScale(tile); + var l = 0, r = 0, c = 0, px = 0, py = 0; + this.nextPacket = function JpxImage_nextPacket() { + for (; c < componentsCount; ++c) { + var component = tile.components[c]; + var precinctsIterationSizes = precinctsSizes.components[c]; + var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount; + for (; py < precinctsIterationSizes.maxNumHigh; py++) { + for (; px < precinctsIterationSizes.maxNumWide; px++) { + for (; r <= decompositionLevelsCount; r++) { + var resolution = component.resolutions[r]; + var sizeInImageScale = precinctsIterationSizes.resolutions[r]; + var k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution); + if (k === null) { + continue; + } + for (; l < layersCount;) { + var packet = createPacket(resolution, k, l); + l++; + return packet; + } + l = 0; + } + r = 0; + } + px = 0; + } + py = 0; + } + error('JPX Error: Out of packets'); + }; + } + function getPrecinctIndexIfExist(pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) { + var posX = pxIndex * precinctIterationSizes.minWidth; + var posY = pyIndex * precinctIterationSizes.minHeight; + if (posX % sizeInImageScale.width !== 0 || posY % sizeInImageScale.height !== 0) { + return null; + } + var startPrecinctRowIndex = posY / sizeInImageScale.width * resolution.precinctParameters.numprecinctswide; + return posX / sizeInImageScale.height + startPrecinctRowIndex; + } + function getPrecinctSizesInImageScale(tile) { + var componentsCount = tile.components.length; + var minWidth = Number.MAX_VALUE; + var minHeight = Number.MAX_VALUE; + var maxNumWide = 0; + var maxNumHigh = 0; + var sizePerComponent = new Array(componentsCount); + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount; + var sizePerResolution = new Array(decompositionLevelsCount + 1); + var minWidthCurrentComponent = Number.MAX_VALUE; + var minHeightCurrentComponent = Number.MAX_VALUE; + var maxNumWideCurrentComponent = 0; + var maxNumHighCurrentComponent = 0; + var scale = 1; + for (var r = decompositionLevelsCount; r >= 0; --r) { + var resolution = component.resolutions[r]; + var widthCurrentResolution = scale * resolution.precinctParameters.precinctWidth; + var heightCurrentResolution = scale * resolution.precinctParameters.precinctHeight; + minWidthCurrentComponent = Math.min(minWidthCurrentComponent, widthCurrentResolution); + minHeightCurrentComponent = Math.min(minHeightCurrentComponent, heightCurrentResolution); + maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent, resolution.precinctParameters.numprecinctswide); + maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent, resolution.precinctParameters.numprecinctshigh); + sizePerResolution[r] = { + width: widthCurrentResolution, + height: heightCurrentResolution + }; + scale <<= 1; + } + minWidth = Math.min(minWidth, minWidthCurrentComponent); + minHeight = Math.min(minHeight, minHeightCurrentComponent); + maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent); + maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent); + sizePerComponent[c] = { + resolutions: sizePerResolution, + minWidth: minWidthCurrentComponent, + minHeight: minHeightCurrentComponent, + maxNumWide: maxNumWideCurrentComponent, + maxNumHigh: maxNumHighCurrentComponent + }; + } + return { + components: sizePerComponent, + minWidth: minWidth, + minHeight: minHeight, + maxNumWide: maxNumWide, + maxNumHigh: maxNumHigh + }; + } + function buildPackets(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var componentsCount = siz.Csiz; + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount; + var resolutions = []; + var subbands = []; + for (var r = 0; r <= decompositionLevelsCount; r++) { + var blocksDimensions = getBlocksDimensions(context, component, r); + var resolution = {}; + var scale = 1 << decompositionLevelsCount - r; + resolution.trx0 = Math.ceil(component.tcx0 / scale); + resolution.try0 = Math.ceil(component.tcy0 / scale); + resolution.trx1 = Math.ceil(component.tcx1 / scale); + resolution.try1 = Math.ceil(component.tcy1 / scale); + resolution.resLevel = r; + buildPrecincts(context, resolution, blocksDimensions); + resolutions.push(resolution); + var subband; + if (r === 0) { + subband = {}; + subband.type = 'LL'; + subband.tbx0 = Math.ceil(component.tcx0 / scale); + subband.tby0 = Math.ceil(component.tcy0 / scale); + subband.tbx1 = Math.ceil(component.tcx1 / scale); + subband.tby1 = Math.ceil(component.tcy1 / scale); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolution.subbands = [subband]; + } else { + var bscale = 1 << decompositionLevelsCount - r + 1; + var resolutionSubbands = []; + subband = {}; + subband.type = 'HL'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); + subband.tby0 = Math.ceil(component.tcy0 / bscale); + subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); + subband.tby1 = Math.ceil(component.tcy1 / bscale); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + subband = {}; + subband.type = 'LH'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale); + subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); + subband.tbx1 = Math.ceil(component.tcx1 / bscale); + subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + subband = {}; + subband.type = 'HH'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); + subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); + subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); + subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + resolution.subbands = resolutionSubbands; + } + } + component.resolutions = resolutions; + component.subbands = subbands; + } + var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder; + switch (progressionOrder) { + case 0: + tile.packetsIterator = new LayerResolutionComponentPositionIterator(context); + break; + case 1: + tile.packetsIterator = new ResolutionLayerComponentPositionIterator(context); + break; + case 2: + tile.packetsIterator = new ResolutionPositionComponentLayerIterator(context); + break; + case 3: + tile.packetsIterator = new PositionComponentResolutionLayerIterator(context); + break; + case 4: + tile.packetsIterator = new ComponentPositionResolutionLayerIterator(context); + break; + default: + error('JPX Error: Unsupported progression order ' + progressionOrder); + } + } + function parseTilePackets(context, data, offset, dataLength) { + var position = 0; + var buffer, bufferSize = 0, skipNextBit = false; + function readBits(count) { + while (bufferSize < count) { + var b = data[offset + position]; + position++; + if (skipNextBit) { + buffer = buffer << 7 | b; + bufferSize += 7; + skipNextBit = false; + } else { + buffer = buffer << 8 | b; + bufferSize += 8; + } + if (b === 0xFF) { + skipNextBit = true; + } + } + bufferSize -= count; + return buffer >>> bufferSize & (1 << count) - 1; + } + function skipMarkerIfEqual(value) { + if (data[offset + position - 1] === 0xFF && data[offset + position] === value) { + skipBytes(1); + return true; + } else if (data[offset + position] === 0xFF && data[offset + position + 1] === value) { + skipBytes(2); + return true; + } + return false; + } + function skipBytes(count) { + position += count; + } + function alignToByte() { + bufferSize = 0; + if (skipNextBit) { + position++; + skipNextBit = false; + } + } + function readCodingpasses() { + if (readBits(1) === 0) { + return 1; + } + if (readBits(1) === 0) { + return 2; + } + var value = readBits(2); + if (value < 3) { + return value + 3; + } + value = readBits(5); + if (value < 31) { + return value + 6; + } + value = readBits(7); + return value + 37; + } + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var sopMarkerUsed = context.COD.sopMarkerUsed; + var ephMarkerUsed = context.COD.ephMarkerUsed; + var packetsIterator = tile.packetsIterator; + while (position < dataLength) { + alignToByte(); + if (sopMarkerUsed && skipMarkerIfEqual(0x91)) { + skipBytes(4); + } + var packet = packetsIterator.nextPacket(); + if (!readBits(1)) { + continue; + } + var layerNumber = packet.layerNumber; + var queue = [], codeblock; + for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) { + codeblock = packet.codeblocks[i]; + var precinct = codeblock.precinct; + var codeblockColumn = codeblock.cbx - precinct.cbxMin; + var codeblockRow = codeblock.cby - precinct.cbyMin; + var codeblockIncluded = false; + var firstTimeInclusion = false; + var valueReady; + if (codeblock['included'] !== undefined) { + codeblockIncluded = !!readBits(1); + } else { + precinct = codeblock.precinct; + var inclusionTree, zeroBitPlanesTree; + if (precinct['inclusionTree'] !== undefined) { + inclusionTree = precinct.inclusionTree; + } else { + var width = precinct.cbxMax - precinct.cbxMin + 1; + var height = precinct.cbyMax - precinct.cbyMin + 1; + inclusionTree = new InclusionTree(width, height, layerNumber); + zeroBitPlanesTree = new TagTree(width, height); + precinct.inclusionTree = inclusionTree; + precinct.zeroBitPlanesTree = zeroBitPlanesTree; + } + if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) { + while (true) { + if (readBits(1)) { + valueReady = !inclusionTree.nextLevel(); + if (valueReady) { + codeblock.included = true; + codeblockIncluded = firstTimeInclusion = true; + break; + } + } else { + inclusionTree.incrementValue(layerNumber); + break; + } + } + } + } + if (!codeblockIncluded) { + continue; + } + if (firstTimeInclusion) { + zeroBitPlanesTree = precinct.zeroBitPlanesTree; + zeroBitPlanesTree.reset(codeblockColumn, codeblockRow); + while (true) { + if (readBits(1)) { + valueReady = !zeroBitPlanesTree.nextLevel(); + if (valueReady) { + break; + } + } else { + zeroBitPlanesTree.incrementValue(); + } + } + codeblock.zeroBitPlanes = zeroBitPlanesTree.value; + } + var codingpasses = readCodingpasses(); + while (readBits(1)) { + codeblock.Lblock++; + } + var codingpassesLog2 = log2(codingpasses); + var bits = (codingpasses < 1 << codingpassesLog2 ? codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock; + var codedDataLength = readBits(bits); + queue.push({ + codeblock: codeblock, + codingpasses: codingpasses, + dataLength: codedDataLength + }); + } + alignToByte(); + if (ephMarkerUsed) { + skipMarkerIfEqual(0x92); + } + while (queue.length > 0) { + var packetItem = queue.shift(); + codeblock = packetItem.codeblock; + if (codeblock['data'] === undefined) { + codeblock.data = []; + } + codeblock.data.push({ + data: data, + start: offset + position, + end: offset + position + packetItem.dataLength, + codingpasses: packetItem.codingpasses + }); + position += packetItem.dataLength; + } + } + return position; + } + function copyCoefficients(coefficients, levelWidth, levelHeight, subband, delta, mb, reversible, segmentationSymbolUsed) { + var x0 = subband.tbx0; + var y0 = subband.tby0; + var width = subband.tbx1 - subband.tbx0; + var codeblocks = subband.codeblocks; + var right = subband.type.charAt(0) === 'H' ? 1 : 0; + var bottom = subband.type.charAt(1) === 'H' ? levelWidth : 0; + for (var i = 0, ii = codeblocks.length; i < ii; ++i) { + var codeblock = codeblocks[i]; + var blockWidth = codeblock.tbx1_ - codeblock.tbx0_; + var blockHeight = codeblock.tby1_ - codeblock.tby0_; + if (blockWidth === 0 || blockHeight === 0) { + continue; + } + if (codeblock['data'] === undefined) { + continue; + } + var bitModel, currentCodingpassType; + bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, codeblock.zeroBitPlanes, mb); + currentCodingpassType = 2; + var data = codeblock.data, totalLength = 0, codingpasses = 0; + var j, jj, dataItem; + for (j = 0, jj = data.length; j < jj; j++) { + dataItem = data[j]; + totalLength += dataItem.end - dataItem.start; + codingpasses += dataItem.codingpasses; + } + var encodedData = new Uint8Array(totalLength); + var position = 0; + for (j = 0, jj = data.length; j < jj; j++) { + dataItem = data[j]; + var chunk = dataItem.data.subarray(dataItem.start, dataItem.end); + encodedData.set(chunk, position); + position += chunk.length; + } + var decoder = new ArithmeticDecoder(encodedData, 0, totalLength); + bitModel.setDecoder(decoder); + for (j = 0; j < codingpasses; j++) { + switch (currentCodingpassType) { + case 0: + bitModel.runSignificancePropagationPass(); + break; + case 1: + bitModel.runMagnitudeRefinementPass(); + break; + case 2: + bitModel.runCleanupPass(); + if (segmentationSymbolUsed) { + bitModel.checkSegmentationSymbol(); + } + break; + } + currentCodingpassType = (currentCodingpassType + 1) % 3; + } + var offset = codeblock.tbx0_ - x0 + (codeblock.tby0_ - y0) * width; + var sign = bitModel.coefficentsSign; + var magnitude = bitModel.coefficentsMagnitude; + var bitsDecoded = bitModel.bitsDecoded; + var magnitudeCorrection = reversible ? 0 : 0.5; + var k, n, nb; + position = 0; + var interleave = subband.type !== 'LL'; + for (j = 0; j < blockHeight; j++) { + var row = offset / width | 0; + var levelOffset = 2 * row * (levelWidth - width) + right + bottom; + for (k = 0; k < blockWidth; k++) { + n = magnitude[position]; + if (n !== 0) { + n = (n + magnitudeCorrection) * delta; + if (sign[position] !== 0) { + n = -n; + } + nb = bitsDecoded[position]; + var pos = interleave ? levelOffset + (offset << 1) : offset; + if (reversible && nb >= mb) { + coefficients[pos] = n; + } else { + coefficients[pos] = n * (1 << mb - nb); + } + } + offset++; + position++; + } + offset += width - blockWidth; + } + } + } + function transformTile(context, tile, c) { + var component = tile.components[c]; + var codingStyleParameters = component.codingStyleParameters; + var quantizationParameters = component.quantizationParameters; + var decompositionLevelsCount = codingStyleParameters.decompositionLevelsCount; + var spqcds = quantizationParameters.SPqcds; + var scalarExpounded = quantizationParameters.scalarExpounded; + var guardBits = quantizationParameters.guardBits; + var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed; + var precision = context.components[c].precision; + var reversible = codingStyleParameters.reversibleTransformation; + var transform = reversible ? new ReversibleTransform() : new IrreversibleTransform(); + var subbandCoefficients = []; + var b = 0; + for (var i = 0; i <= decompositionLevelsCount; i++) { + var resolution = component.resolutions[i]; + var width = resolution.trx1 - resolution.trx0; + var height = resolution.try1 - resolution.try0; + var coefficients = new Float32Array(width * height); + for (var j = 0, jj = resolution.subbands.length; j < jj; j++) { + var mu, epsilon; + if (!scalarExpounded) { + mu = spqcds[0].mu; + epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0); + } else { + mu = spqcds[b].mu; + epsilon = spqcds[b].epsilon; + b++; + } + var subband = resolution.subbands[j]; + var gainLog2 = SubbandsGainLog2[subband.type]; + var delta = reversible ? 1 : Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048); + var mb = guardBits + epsilon - 1; + copyCoefficients(coefficients, width, height, subband, delta, mb, reversible, segmentationSymbolUsed); + } + subbandCoefficients.push({ + width: width, + height: height, + items: coefficients + }); + } + var result = transform.calculate(subbandCoefficients, component.tcx0, component.tcy0); + return { + left: component.tcx0, + top: component.tcy0, + width: result.width, + height: result.height, + items: result.items + }; + } + function transformComponents(context) { + var siz = context.SIZ; + var components = context.components; + var componentsCount = siz.Csiz; + var resultImages = []; + for (var i = 0, ii = context.tiles.length; i < ii; i++) { + var tile = context.tiles[i]; + var transformedTiles = []; + var c; + for (c = 0; c < componentsCount; c++) { + transformedTiles[c] = transformTile(context, tile, c); + } + var tile0 = transformedTiles[0]; + var out = new Uint8Array(tile0.items.length * componentsCount); + var result = { + left: tile0.left, + top: tile0.top, + width: tile0.width, + height: tile0.height, + items: out + }; + var shift, offset, max, min, maxK; + var pos = 0, j, jj, y0, y1, y2, r, g, b, k, val; + if (tile.codingStyleDefaultParameters.multipleComponentTransform) { + var fourComponents = componentsCount === 4; + var y0items = transformedTiles[0].items; + var y1items = transformedTiles[1].items; + var y2items = transformedTiles[2].items; + var y3items = fourComponents ? transformedTiles[3].items : null; + shift = components[0].precision - 8; + offset = (128 << shift) + 0.5; + max = 255 * (1 << shift); + maxK = max * 0.5; + min = -maxK; + var component0 = tile.components[0]; + var alpha01 = componentsCount - 3; + jj = y0items.length; + if (!component0.codingStyleParameters.reversibleTransformation) { + for (j = 0; j < jj; j++, pos += alpha01) { + y0 = y0items[j] + offset; + y1 = y1items[j]; + y2 = y2items[j]; + r = y0 + 1.402 * y2; + g = y0 - 0.34413 * y1 - 0.71414 * y2; + b = y0 + 1.772 * y1; + out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift; + out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift; + out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift; + } + } else { + for (j = 0; j < jj; j++, pos += alpha01) { + y0 = y0items[j] + offset; + y1 = y1items[j]; + y2 = y2items[j]; + g = y0 - (y2 + y1 >> 2); + r = g + y2; + b = g + y1; + out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift; + out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift; + out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift; + } + } + if (fourComponents) { + for (j = 0, pos = 3; j < jj; j++, pos += 4) { + k = y3items[j]; + out[pos] = k <= min ? 0 : k >= maxK ? 255 : k + offset >> shift; + } + } + } else { + for (c = 0; c < componentsCount; c++) { + var items = transformedTiles[c].items; + shift = components[c].precision - 8; + offset = (128 << shift) + 0.5; + max = 127.5 * (1 << shift); + min = -max; + for (pos = c, j = 0, jj = items.length; j < jj; j++) { + val = items[j]; + out[pos] = val <= min ? 0 : val >= max ? 255 : val + offset >> shift; + pos += componentsCount; + } + } + } + resultImages.push(result); + } + return resultImages; + } + function initializeTile(context, tileIndex) { + var siz = context.SIZ; + var componentsCount = siz.Csiz; + var tile = context.tiles[tileIndex]; + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var qcdOrQcc = context.currentTile.QCC[c] !== undefined ? context.currentTile.QCC[c] : context.currentTile.QCD; + component.quantizationParameters = qcdOrQcc; + var codOrCoc = context.currentTile.COC[c] !== undefined ? context.currentTile.COC[c] : context.currentTile.COD; + component.codingStyleParameters = codOrCoc; + } + tile.codingStyleDefaultParameters = context.currentTile.COD; + } + var TagTree = function TagTreeClosure() { + function TagTree(width, height) { + var levelsLength = log2(Math.max(width, height)) + 1; + this.levels = []; + for (var i = 0; i < levelsLength; i++) { + var level = { + width: width, + height: height, + items: [] + }; + this.levels.push(level); + width = Math.ceil(width / 2); + height = Math.ceil(height / 2); + } + } + TagTree.prototype = { + reset: function TagTree_reset(i, j) { + var currentLevel = 0, value = 0, level; + while (currentLevel < this.levels.length) { + level = this.levels[currentLevel]; + var index = i + j * level.width; + if (level.items[index] !== undefined) { + value = level.items[index]; + break; + } + level.index = index; + i >>= 1; + j >>= 1; + currentLevel++; + } + currentLevel--; + level = this.levels[currentLevel]; + level.items[level.index] = value; + this.currentLevel = currentLevel; + delete this.value; + }, + incrementValue: function TagTree_incrementValue() { + var level = this.levels[this.currentLevel]; + level.items[level.index]++; + }, + nextLevel: function TagTree_nextLevel() { + var currentLevel = this.currentLevel; + var level = this.levels[currentLevel]; + var value = level.items[level.index]; + currentLevel--; + if (currentLevel < 0) { + this.value = value; + return false; + } + this.currentLevel = currentLevel; + level = this.levels[currentLevel]; + level.items[level.index] = value; + return true; + } + }; + return TagTree; + }(); + var InclusionTree = function InclusionTreeClosure() { + function InclusionTree(width, height, defaultValue) { + var levelsLength = log2(Math.max(width, height)) + 1; + this.levels = []; + for (var i = 0; i < levelsLength; i++) { + var items = new Uint8Array(width * height); + for (var j = 0, jj = items.length; j < jj; j++) { + items[j] = defaultValue; + } + var level = { + width: width, + height: height, + items: items + }; + this.levels.push(level); + width = Math.ceil(width / 2); + height = Math.ceil(height / 2); + } + } + InclusionTree.prototype = { + reset: function InclusionTree_reset(i, j, stopValue) { + var currentLevel = 0; + while (currentLevel < this.levels.length) { + var level = this.levels[currentLevel]; + var index = i + j * level.width; + level.index = index; + var value = level.items[index]; + if (value === 0xFF) { + break; + } + if (value > stopValue) { + this.currentLevel = currentLevel; + this.propagateValues(); + return false; + } + i >>= 1; + j >>= 1; + currentLevel++; + } + this.currentLevel = currentLevel - 1; + return true; + }, + incrementValue: function InclusionTree_incrementValue(stopValue) { + var level = this.levels[this.currentLevel]; + level.items[level.index] = stopValue + 1; + this.propagateValues(); + }, + propagateValues: function InclusionTree_propagateValues() { + var levelIndex = this.currentLevel; + var level = this.levels[levelIndex]; + var currentValue = level.items[level.index]; + while (--levelIndex >= 0) { + level = this.levels[levelIndex]; + level.items[level.index] = currentValue; + } + }, + nextLevel: function InclusionTree_nextLevel() { + var currentLevel = this.currentLevel; + var level = this.levels[currentLevel]; + var value = level.items[level.index]; + level.items[level.index] = 0xFF; + currentLevel--; + if (currentLevel < 0) { + return false; + } + this.currentLevel = currentLevel; + level = this.levels[currentLevel]; + level.items[level.index] = value; + return true; + } + }; + return InclusionTree; + }(); + var BitModel = function BitModelClosure() { + var UNIFORM_CONTEXT = 17; + var RUNLENGTH_CONTEXT = 18; + var LLAndLHContextsLabel = new Uint8Array([ + 0, + 5, + 8, + 0, + 3, + 7, + 8, + 0, + 4, + 7, + 8, + 0, + 0, + 0, + 0, + 0, + 1, + 6, + 8, + 0, + 3, + 7, + 8, + 0, + 4, + 7, + 8, + 0, + 0, + 0, + 0, + 0, + 2, + 6, + 8, + 0, + 3, + 7, + 8, + 0, + 4, + 7, + 8, + 0, + 0, + 0, + 0, + 0, + 2, + 6, + 8, + 0, + 3, + 7, + 8, + 0, + 4, + 7, + 8, + 0, + 0, + 0, + 0, + 0, + 2, + 6, + 8, + 0, + 3, + 7, + 8, + 0, + 4, + 7, + 8 + ]); + var HLContextLabel = new Uint8Array([ + 0, + 3, + 4, + 0, + 5, + 7, + 7, + 0, + 8, + 8, + 8, + 0, + 0, + 0, + 0, + 0, + 1, + 3, + 4, + 0, + 6, + 7, + 7, + 0, + 8, + 8, + 8, + 0, + 0, + 0, + 0, + 0, + 2, + 3, + 4, + 0, + 6, + 7, + 7, + 0, + 8, + 8, + 8, + 0, + 0, + 0, + 0, + 0, + 2, + 3, + 4, + 0, + 6, + 7, + 7, + 0, + 8, + 8, + 8, + 0, + 0, + 0, + 0, + 0, + 2, + 3, + 4, + 0, + 6, + 7, + 7, + 0, + 8, + 8, + 8 + ]); + var HHContextLabel = new Uint8Array([ + 0, + 1, + 2, + 0, + 1, + 2, + 2, + 0, + 2, + 2, + 2, + 0, + 0, + 0, + 0, + 0, + 3, + 4, + 5, + 0, + 4, + 5, + 5, + 0, + 5, + 5, + 5, + 0, + 0, + 0, + 0, + 0, + 6, + 7, + 7, + 0, + 7, + 7, + 7, + 0, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 8, + 8, + 8, + 0, + 8, + 8, + 8, + 0, + 8, + 8, + 8, + 0, + 0, + 0, + 0, + 0, + 8, + 8, + 8, + 0, + 8, + 8, + 8, + 0, + 8, + 8, + 8 + ]); + function BitModel(width, height, subband, zeroBitPlanes, mb) { + this.width = width; + this.height = height; + this.contextLabelTable = subband === 'HH' ? HHContextLabel : subband === 'HL' ? HLContextLabel : LLAndLHContextsLabel; + var coefficientCount = width * height; + this.neighborsSignificance = new Uint8Array(coefficientCount); + this.coefficentsSign = new Uint8Array(coefficientCount); + this.coefficentsMagnitude = mb > 14 ? new Uint32Array(coefficientCount) : mb > 6 ? new Uint16Array(coefficientCount) : new Uint8Array(coefficientCount); + this.processingFlags = new Uint8Array(coefficientCount); + var bitsDecoded = new Uint8Array(coefficientCount); + if (zeroBitPlanes !== 0) { + for (var i = 0; i < coefficientCount; i++) { + bitsDecoded[i] = zeroBitPlanes; + } + } + this.bitsDecoded = bitsDecoded; + this.reset(); + } + BitModel.prototype = { + setDecoder: function BitModel_setDecoder(decoder) { + this.decoder = decoder; + }, + reset: function BitModel_reset() { + this.contexts = new Int8Array(19); + this.contexts[0] = 4 << 1 | 0; + this.contexts[UNIFORM_CONTEXT] = 46 << 1 | 0; + this.contexts[RUNLENGTH_CONTEXT] = 3 << 1 | 0; + }, + setNeighborsSignificance: function BitModel_setNeighborsSignificance(row, column, index) { + var neighborsSignificance = this.neighborsSignificance; + var width = this.width, height = this.height; + var left = column > 0; + var right = column + 1 < width; + var i; + if (row > 0) { + i = index - width; + if (left) { + neighborsSignificance[i - 1] += 0x10; + } + if (right) { + neighborsSignificance[i + 1] += 0x10; + } + neighborsSignificance[i] += 0x04; + } + if (row + 1 < height) { + i = index + width; + if (left) { + neighborsSignificance[i - 1] += 0x10; + } + if (right) { + neighborsSignificance[i + 1] += 0x10; + } + neighborsSignificance[i] += 0x04; + } + if (left) { + neighborsSignificance[index - 1] += 0x01; + } + if (right) { + neighborsSignificance[index + 1] += 0x01; + } + neighborsSignificance[index] |= 0x80; + }, + runSignificancePropagationPass: function BitModel_runSignificancePropagationPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var neighborsSignificance = this.neighborsSignificance; + var processingFlags = this.processingFlags; + var contexts = this.contexts; + var labels = this.contextLabelTable; + var bitsDecoded = this.bitsDecoded; + var processedInverseMask = ~1; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + for (var i0 = 0; i0 < height; i0 += 4) { + for (var j = 0; j < width; j++) { + var index = i0 * width + j; + for (var i1 = 0; i1 < 4; i1++, index += width) { + var i = i0 + i1; + if (i >= height) { + break; + } + processingFlags[index] &= processedInverseMask; + if (coefficentsMagnitude[index] || !neighborsSignificance[index]) { + continue; + } + var contextLabel = labels[neighborsSignificance[index]]; + var decision = decoder.readBit(contexts, contextLabel); + if (decision) { + var sign = this.decodeSignBit(i, j, index); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j, index); + processingFlags[index] |= firstMagnitudeBitMask; + } + bitsDecoded[index]++; + processingFlags[index] |= processedMask; + } + } + } + }, + decodeSignBit: function BitModel_decodeSignBit(row, column, index) { + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var contribution, sign0, sign1, significance1; + var contextLabel, decoded; + significance1 = column > 0 && coefficentsMagnitude[index - 1] !== 0; + if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) { + sign1 = coefficentsSign[index + 1]; + if (significance1) { + sign0 = coefficentsSign[index - 1]; + contribution = 1 - sign1 - sign0; + } else { + contribution = 1 - sign1 - sign1; + } + } else if (significance1) { + sign0 = coefficentsSign[index - 1]; + contribution = 1 - sign0 - sign0; + } else { + contribution = 0; + } + var horizontalContribution = 3 * contribution; + significance1 = row > 0 && coefficentsMagnitude[index - width] !== 0; + if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) { + sign1 = coefficentsSign[index + width]; + if (significance1) { + sign0 = coefficentsSign[index - width]; + contribution = 1 - sign1 - sign0 + horizontalContribution; + } else { + contribution = 1 - sign1 - sign1 + horizontalContribution; + } + } else if (significance1) { + sign0 = coefficentsSign[index - width]; + contribution = 1 - sign0 - sign0 + horizontalContribution; + } else { + contribution = horizontalContribution; + } + if (contribution >= 0) { + contextLabel = 9 + contribution; + decoded = this.decoder.readBit(this.contexts, contextLabel); + } else { + contextLabel = 9 - contribution; + decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1; + } + return decoded; + }, + runMagnitudeRefinementPass: function BitModel_runMagnitudeRefinementPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var neighborsSignificance = this.neighborsSignificance; + var contexts = this.contexts; + var bitsDecoded = this.bitsDecoded; + var processingFlags = this.processingFlags; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + var length = width * height; + var width4 = width * 4; + for (var index0 = 0, indexNext; index0 < length; index0 = indexNext) { + indexNext = Math.min(length, index0 + width4); + for (var j = 0; j < width; j++) { + for (var index = index0 + j; index < indexNext; index += width) { + if (!coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) { + continue; + } + var contextLabel = 16; + if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) { + processingFlags[index] ^= firstMagnitudeBitMask; + var significance = neighborsSignificance[index] & 127; + contextLabel = significance === 0 ? 15 : 14; + } + var bit = decoder.readBit(contexts, contextLabel); + coefficentsMagnitude[index] = coefficentsMagnitude[index] << 1 | bit; + bitsDecoded[index]++; + processingFlags[index] |= processedMask; + } + } + } + }, + runCleanupPass: function BitModel_runCleanupPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var neighborsSignificance = this.neighborsSignificance; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var contexts = this.contexts; + var labels = this.contextLabelTable; + var bitsDecoded = this.bitsDecoded; + var processingFlags = this.processingFlags; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + var oneRowDown = width; + var twoRowsDown = width * 2; + var threeRowsDown = width * 3; + var iNext; + for (var i0 = 0; i0 < height; i0 = iNext) { + iNext = Math.min(i0 + 4, height); + var indexBase = i0 * width; + var checkAllEmpty = i0 + 3 < height; + for (var j = 0; j < width; j++) { + var index0 = indexBase + j; + var allEmpty = checkAllEmpty && processingFlags[index0] === 0 && processingFlags[index0 + oneRowDown] === 0 && processingFlags[index0 + twoRowsDown] === 0 && processingFlags[index0 + threeRowsDown] === 0 && neighborsSignificance[index0] === 0 && neighborsSignificance[index0 + oneRowDown] === 0 && neighborsSignificance[index0 + twoRowsDown] === 0 && neighborsSignificance[index0 + threeRowsDown] === 0; + var i1 = 0, index = index0; + var i = i0, sign; + if (allEmpty) { + var hasSignificantCoefficent = decoder.readBit(contexts, RUNLENGTH_CONTEXT); + if (!hasSignificantCoefficent) { + bitsDecoded[index0]++; + bitsDecoded[index0 + oneRowDown]++; + bitsDecoded[index0 + twoRowsDown]++; + bitsDecoded[index0 + threeRowsDown]++; + continue; + } + i1 = decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT); + if (i1 !== 0) { + i = i0 + i1; + index += i1 * width; + } + sign = this.decodeSignBit(i, j, index); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j, index); + processingFlags[index] |= firstMagnitudeBitMask; + index = index0; + for (var i2 = i0; i2 <= i; i2++, index += width) { + bitsDecoded[index]++; + } + i1++; + } + for (i = i0 + i1; i < iNext; i++, index += width) { + if (coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) { + continue; + } + var contextLabel = labels[neighborsSignificance[index]]; + var decision = decoder.readBit(contexts, contextLabel); + if (decision === 1) { + sign = this.decodeSignBit(i, j, index); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j, index); + processingFlags[index] |= firstMagnitudeBitMask; + } + bitsDecoded[index]++; + } + } + } + }, + checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() { + var decoder = this.decoder; + var contexts = this.contexts; + var symbol = decoder.readBit(contexts, UNIFORM_CONTEXT) << 3 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 2 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT); + if (symbol !== 0xA) { + error('JPX Error: Invalid segmentation symbol'); + } + } + }; + return BitModel; + }(); + var Transform = function TransformClosure() { + function Transform() { + } + Transform.prototype.calculate = function transformCalculate(subbands, u0, v0) { + var ll = subbands[0]; + for (var i = 1, ii = subbands.length; i < ii; i++) { + ll = this.iterate(ll, subbands[i], u0, v0); + } + return ll; + }; + Transform.prototype.extend = function extend(buffer, offset, size) { + var i1 = offset - 1, j1 = offset + 1; + var i2 = offset + size - 2, j2 = offset + size; + buffer[i1--] = buffer[j1++]; + buffer[j2++] = buffer[i2--]; + buffer[i1--] = buffer[j1++]; + buffer[j2++] = buffer[i2--]; + buffer[i1--] = buffer[j1++]; + buffer[j2++] = buffer[i2--]; + buffer[i1] = buffer[j1]; + buffer[j2] = buffer[i2]; + }; + Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh, u0, v0) { + var llWidth = ll.width, llHeight = ll.height, llItems = ll.items; + var width = hl_lh_hh.width; + var height = hl_lh_hh.height; + var items = hl_lh_hh.items; + var i, j, k, l, u, v; + for (k = 0, i = 0; i < llHeight; i++) { + l = i * 2 * width; + for (j = 0; j < llWidth; j++, k++, l += 2) { + items[l] = llItems[k]; + } + } + llItems = ll.items = null; + var bufferPadding = 4; + var rowBuffer = new Float32Array(width + 2 * bufferPadding); + if (width === 1) { + if ((u0 & 1) !== 0) { + for (v = 0, k = 0; v < height; v++, k += width) { + items[k] *= 0.5; + } + } + } else { + for (v = 0, k = 0; v < height; v++, k += width) { + rowBuffer.set(items.subarray(k, k + width), bufferPadding); + this.extend(rowBuffer, bufferPadding, width); + this.filter(rowBuffer, bufferPadding, width); + items.set(rowBuffer.subarray(bufferPadding, bufferPadding + width), k); + } + } + var numBuffers = 16; + var colBuffers = []; + for (i = 0; i < numBuffers; i++) { + colBuffers.push(new Float32Array(height + 2 * bufferPadding)); + } + var b, currentBuffer = 0; + ll = bufferPadding + height; + if (height === 1) { + if ((v0 & 1) !== 0) { + for (u = 0; u < width; u++) { + items[u] *= 0.5; + } + } + } else { + for (u = 0; u < width; u++) { + if (currentBuffer === 0) { + numBuffers = Math.min(width - u, numBuffers); + for (k = u, l = bufferPadding; l < ll; k += width, l++) { + for (b = 0; b < numBuffers; b++) { + colBuffers[b][l] = items[k + b]; + } + } + currentBuffer = numBuffers; + } + currentBuffer--; + var buffer = colBuffers[currentBuffer]; + this.extend(buffer, bufferPadding, height); + this.filter(buffer, bufferPadding, height); + if (currentBuffer === 0) { + k = u - numBuffers + 1; + for (l = bufferPadding; l < ll; k += width, l++) { + for (b = 0; b < numBuffers; b++) { + items[k + b] = colBuffers[b][l]; + } + } + } + } + } + return { + width: width, + height: height, + items: items + }; + }; + return Transform; + }(); + var IrreversibleTransform = function IrreversibleTransformClosure() { + function IrreversibleTransform() { + Transform.call(this); + } + IrreversibleTransform.prototype = Object.create(Transform.prototype); + IrreversibleTransform.prototype.filter = function irreversibleTransformFilter(x, offset, length) { + var len = length >> 1; + offset = offset | 0; + var j, n, current, next; + var alpha = -1.586134342059924; + var beta = -0.052980118572961; + var gamma = 0.882911075530934; + var delta = 0.443506852043971; + var K = 1.230174104914001; + var K_ = 1 / K; + j = offset - 3; + for (n = len + 4; n--; j += 2) { + x[j] *= K_; + } + j = offset - 2; + current = delta * x[j - 1]; + for (n = len + 3; n--; j += 2) { + next = delta * x[j + 1]; + x[j] = K * x[j] - current - next; + if (n--) { + j += 2; + current = delta * x[j + 1]; + x[j] = K * x[j] - current - next; + } else { + break; + } + } + j = offset - 1; + current = gamma * x[j - 1]; + for (n = len + 2; n--; j += 2) { + next = gamma * x[j + 1]; + x[j] -= current + next; + if (n--) { + j += 2; + current = gamma * x[j + 1]; + x[j] -= current + next; + } else { + break; + } + } + j = offset; + current = beta * x[j - 1]; + for (n = len + 1; n--; j += 2) { + next = beta * x[j + 1]; + x[j] -= current + next; + if (n--) { + j += 2; + current = beta * x[j + 1]; + x[j] -= current + next; + } else { + break; + } + } + if (len !== 0) { + j = offset + 1; + current = alpha * x[j - 1]; + for (n = len; n--; j += 2) { + next = alpha * x[j + 1]; + x[j] -= current + next; + if (n--) { + j += 2; + current = alpha * x[j + 1]; + x[j] -= current + next; + } else { + break; + } + } + } + }; + return IrreversibleTransform; + }(); + var ReversibleTransform = function ReversibleTransformClosure() { + function ReversibleTransform() { + Transform.call(this); + } + ReversibleTransform.prototype = Object.create(Transform.prototype); + ReversibleTransform.prototype.filter = function reversibleTransformFilter(x, offset, length) { + var len = length >> 1; + offset = offset | 0; + var j, n; + for (j = offset, n = len + 1; n--; j += 2) { + x[j] -= x[j - 1] + x[j + 1] + 2 >> 2; + } + for (j = offset + 1, n = len; n--; j += 2) { + x[j] += x[j - 1] + x[j + 1] >> 1; + } + }; + return ReversibleTransform; + }(); + return JpxImage; +}(); +exports.JpxImage = JpxImage; + +/***/ }), +/* 16 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreCrypto = __w_pdfjs_require__(13); +var coreParser = __w_pdfjs_require__(5); +var coreChunkedStream = __w_pdfjs_require__(12); +var coreColorSpace = __w_pdfjs_require__(3); +var InvalidPDFException = sharedUtil.InvalidPDFException; +var MissingDataException = sharedUtil.MissingDataException; +var XRefParseException = sharedUtil.XRefParseException; +var assert = sharedUtil.assert; +var bytesToString = sharedUtil.bytesToString; +var createPromiseCapability = sharedUtil.createPromiseCapability; +var error = sharedUtil.error; +var info = sharedUtil.info; +var isArray = sharedUtil.isArray; +var isBool = sharedUtil.isBool; +var isInt = sharedUtil.isInt; +var isString = sharedUtil.isString; +var shadow = sharedUtil.shadow; +var stringToPDFString = sharedUtil.stringToPDFString; +var stringToUTF8String = sharedUtil.stringToUTF8String; +var warn = sharedUtil.warn; +var createValidAbsoluteUrl = sharedUtil.createValidAbsoluteUrl; +var Util = sharedUtil.Util; +var Ref = corePrimitives.Ref; +var RefSet = corePrimitives.RefSet; +var RefSetCache = corePrimitives.RefSetCache; +var isName = corePrimitives.isName; +var isCmd = corePrimitives.isCmd; +var isDict = corePrimitives.isDict; +var isRef = corePrimitives.isRef; +var isRefsEqual = corePrimitives.isRefsEqual; +var isStream = corePrimitives.isStream; +var CipherTransformFactory = coreCrypto.CipherTransformFactory; +var Lexer = coreParser.Lexer; +var Parser = coreParser.Parser; +var ChunkedStream = coreChunkedStream.ChunkedStream; +var ColorSpace = coreColorSpace.ColorSpace; +var Catalog = function CatalogClosure() { + function Catalog(pdfManager, xref, pageFactory) { + this.pdfManager = pdfManager; + this.xref = xref; + this.catDict = xref.getCatalogObj(); + this.fontCache = new RefSetCache(); + this.builtInCMapCache = Object.create(null); + assert(isDict(this.catDict), 'catalog object is not a dictionary'); + this.pageFactory = pageFactory; + this.pagePromises = []; + } + Catalog.prototype = { + get metadata() { + var streamRef = this.catDict.getRaw('Metadata'); + if (!isRef(streamRef)) { + return shadow(this, 'metadata', null); + } + var encryptMetadata = !this.xref.encrypt ? false : this.xref.encrypt.encryptMetadata; + var stream = this.xref.fetch(streamRef, !encryptMetadata); + var metadata; + if (stream && isDict(stream.dict)) { + var type = stream.dict.get('Type'); + var subtype = stream.dict.get('Subtype'); + if (isName(type, 'Metadata') && isName(subtype, 'XML')) { + try { + metadata = stringToUTF8String(bytesToString(stream.getBytes())); + } catch (e) { + info('Skipping invalid metadata.'); + } + } + } + return shadow(this, 'metadata', metadata); + }, + get toplevelPagesDict() { + var pagesObj = this.catDict.get('Pages'); + assert(isDict(pagesObj), 'invalid top-level pages dictionary'); + return shadow(this, 'toplevelPagesDict', pagesObj); + }, + get documentOutline() { + var obj = null; + try { + obj = this.readDocumentOutline(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Unable to read document outline'); + } + return shadow(this, 'documentOutline', obj); + }, + readDocumentOutline: function Catalog_readDocumentOutline() { + var obj = this.catDict.get('Outlines'); + if (!isDict(obj)) { + return null; + } + obj = obj.getRaw('First'); + if (!isRef(obj)) { + return null; + } + var root = { items: [] }; + var queue = [{ + obj: obj, + parent: root + }]; + var processed = new RefSet(); + processed.put(obj); + var xref = this.xref, blackColor = new Uint8Array(3); + while (queue.length > 0) { + var i = queue.shift(); + var outlineDict = xref.fetchIfRef(i.obj); + if (outlineDict === null) { + continue; + } + assert(outlineDict.has('Title'), 'Invalid outline item'); + var data = { + url: null, + dest: null + }; + Catalog.parseDestDictionary({ + destDict: outlineDict, + resultObj: data, + docBaseUrl: this.pdfManager.docBaseUrl + }); + var title = outlineDict.get('Title'); + var flags = outlineDict.get('F') || 0; + var color = outlineDict.getArray('C'), rgbColor = blackColor; + if (isArray(color) && color.length === 3 && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { + rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0); + } + var outlineItem = { + dest: data.dest, + url: data.url, + unsafeUrl: data.unsafeUrl, + newWindow: data.newWindow, + title: stringToPDFString(title), + color: rgbColor, + count: outlineDict.get('Count'), + bold: !!(flags & 2), + italic: !!(flags & 1), + items: [] + }; + i.parent.items.push(outlineItem); + obj = outlineDict.getRaw('First'); + if (isRef(obj) && !processed.has(obj)) { + queue.push({ + obj: obj, + parent: outlineItem + }); + processed.put(obj); + } + obj = outlineDict.getRaw('Next'); + if (isRef(obj) && !processed.has(obj)) { + queue.push({ + obj: obj, + parent: i.parent + }); + processed.put(obj); + } + } + return root.items.length > 0 ? root.items : null; + }, + get numPages() { + var obj = this.toplevelPagesDict.get('Count'); + assert(isInt(obj), 'page count in top level pages object is not an integer'); + return shadow(this, 'num', obj); + }, + get destinations() { + function fetchDestination(dest) { + return isDict(dest) ? dest.get('D') : dest; + } + var xref = this.xref; + var dests = {}, nameTreeRef, nameDictionaryRef; + var obj = this.catDict.get('Names'); + if (obj && obj.has('Dests')) { + nameTreeRef = obj.getRaw('Dests'); + } else if (this.catDict.has('Dests')) { + nameDictionaryRef = this.catDict.get('Dests'); + } + if (nameDictionaryRef) { + obj = nameDictionaryRef; + obj.forEach(function catalogForEach(key, value) { + if (!value) { + return; + } + dests[key] = fetchDestination(value); + }); + } + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + var names = nameTree.getAll(); + for (var name in names) { + dests[name] = fetchDestination(names[name]); + } + } + return shadow(this, 'destinations', dests); + }, + getDestination: function Catalog_getDestination(destinationId) { + function fetchDestination(dest) { + return isDict(dest) ? dest.get('D') : dest; + } + var xref = this.xref; + var dest = null, nameTreeRef, nameDictionaryRef; + var obj = this.catDict.get('Names'); + if (obj && obj.has('Dests')) { + nameTreeRef = obj.getRaw('Dests'); + } else if (this.catDict.has('Dests')) { + nameDictionaryRef = this.catDict.get('Dests'); + } + if (nameDictionaryRef) { + var value = nameDictionaryRef.get(destinationId); + if (value) { + dest = fetchDestination(value); + } + } + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + dest = fetchDestination(nameTree.get(destinationId)); + } + return dest; + }, + get pageLabels() { + var obj = null; + try { + obj = this.readPageLabels(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Unable to read page labels.'); + } + return shadow(this, 'pageLabels', obj); + }, + readPageLabels: function Catalog_readPageLabels() { + var obj = this.catDict.getRaw('PageLabels'); + if (!obj) { + return null; + } + var pageLabels = new Array(this.numPages); + var style = null; + var prefix = ''; + var numberTree = new NumberTree(obj, this.xref); + var nums = numberTree.getAll(); + var currentLabel = '', currentIndex = 1; + for (var i = 0, ii = this.numPages; i < ii; i++) { + if (i in nums) { + var labelDict = nums[i]; + assert(isDict(labelDict), 'The PageLabel is not a dictionary.'); + var type = labelDict.get('Type'); + assert(!type || isName(type, 'PageLabel'), 'Invalid type in PageLabel dictionary.'); + var s = labelDict.get('S'); + assert(!s || isName(s), 'Invalid style in PageLabel dictionary.'); + style = s ? s.name : null; + var p = labelDict.get('P'); + assert(!p || isString(p), 'Invalid prefix in PageLabel dictionary.'); + prefix = p ? stringToPDFString(p) : ''; + var st = labelDict.get('St'); + assert(!st || isInt(st) && st >= 1, 'Invalid start in PageLabel dictionary.'); + currentIndex = st || 1; + } + switch (style) { + case 'D': + currentLabel = currentIndex; + break; + case 'R': + case 'r': + currentLabel = Util.toRoman(currentIndex, style === 'r'); + break; + case 'A': + case 'a': + var LIMIT = 26; + var A_UPPER_CASE = 0x41, A_LOWER_CASE = 0x61; + var baseCharCode = style === 'a' ? A_LOWER_CASE : A_UPPER_CASE; + var letterIndex = currentIndex - 1; + var character = String.fromCharCode(baseCharCode + letterIndex % LIMIT); + var charBuf = []; + for (var j = 0, jj = letterIndex / LIMIT | 0; j <= jj; j++) { + charBuf.push(character); + } + currentLabel = charBuf.join(''); + break; + default: + assert(!style, 'Invalid style "' + style + '" in PageLabel dictionary.'); + } + pageLabels[i] = prefix + currentLabel; + currentLabel = ''; + currentIndex++; + } + return pageLabels; + }, + get attachments() { + var xref = this.xref; + var attachments = null, nameTreeRef; + var obj = this.catDict.get('Names'); + if (obj) { + nameTreeRef = obj.getRaw('EmbeddedFiles'); + } + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + var names = nameTree.getAll(); + for (var name in names) { + var fs = new FileSpec(names[name], xref); + if (!attachments) { + attachments = Object.create(null); + } + attachments[stringToPDFString(name)] = fs.serializable; + } + } + return shadow(this, 'attachments', attachments); + }, + get javaScript() { + var xref = this.xref; + var obj = this.catDict.get('Names'); + var javaScript = []; + function appendIfJavaScriptDict(jsDict) { + var type = jsDict.get('S'); + if (!isName(type, 'JavaScript')) { + return; + } + var js = jsDict.get('JS'); + if (isStream(js)) { + js = bytesToString(js.getBytes()); + } else if (!isString(js)) { + return; + } + javaScript.push(stringToPDFString(js)); + } + if (obj && obj.has('JavaScript')) { + var nameTree = new NameTree(obj.getRaw('JavaScript'), xref); + var names = nameTree.getAll(); + for (var name in names) { + var jsDict = names[name]; + if (isDict(jsDict)) { + appendIfJavaScriptDict(jsDict); + } + } + } + var openactionDict = this.catDict.get('OpenAction'); + if (isDict(openactionDict, 'Action')) { + var actionType = openactionDict.get('S'); + if (isName(actionType, 'Named')) { + var action = openactionDict.get('N'); + if (isName(action, 'Print')) { + javaScript.push('print({});'); + } + } else { + appendIfJavaScriptDict(openactionDict); + } + } + return shadow(this, 'javaScript', javaScript); + }, + cleanup: function Catalog_cleanup() { + var promises = []; + this.fontCache.forEach(function (promise) { + promises.push(promise); + }); + return Promise.all(promises).then(function (translatedFonts) { + for (var i = 0, ii = translatedFonts.length; i < ii; i++) { + var font = translatedFonts[i].dict; + delete font.translated; + } + this.fontCache.clear(); + this.builtInCMapCache = Object.create(null); + }.bind(this)); + }, + getPage: function Catalog_getPage(pageIndex) { + if (!(pageIndex in this.pagePromises)) { + this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then(function (a) { + var dict = a[0]; + var ref = a[1]; + return this.pageFactory.createPage(pageIndex, dict, ref, this.fontCache, this.builtInCMapCache); + }.bind(this)); + } + return this.pagePromises[pageIndex]; + }, + getPageDict: function Catalog_getPageDict(pageIndex) { + var capability = createPromiseCapability(); + var nodesToVisit = [this.catDict.getRaw('Pages')]; + var currentPageIndex = 0; + var xref = this.xref; + function next() { + while (nodesToVisit.length) { + var currentNode = nodesToVisit.pop(); + if (isRef(currentNode)) { + xref.fetchAsync(currentNode).then(function (obj) { + if (isDict(obj, 'Page') || isDict(obj) && !obj.has('Kids')) { + if (pageIndex === currentPageIndex) { + capability.resolve([ + obj, + currentNode + ]); + } else { + currentPageIndex++; + next(); + } + return; + } + nodesToVisit.push(obj); + next(); + }, capability.reject); + return; + } + assert(isDict(currentNode), 'page dictionary kid reference points to wrong type of object'); + var count = currentNode.get('Count'); + if (currentPageIndex + count <= pageIndex) { + currentPageIndex += count; + continue; + } + var kids = currentNode.get('Kids'); + assert(isArray(kids), 'page dictionary kids object is not an array'); + for (var last = kids.length - 1; last >= 0; last--) { + nodesToVisit.push(kids[last]); + } + } + capability.reject('Page index ' + pageIndex + ' not found.'); + } + next(); + return capability.promise; + }, + getPageIndex: function Catalog_getPageIndex(pageRef) { + var xref = this.xref; + function pagesBeforeRef(kidRef) { + var total = 0; + var parentRef; + return xref.fetchAsync(kidRef).then(function (node) { + if (isRefsEqual(kidRef, pageRef) && !isDict(node, 'Page') && !(isDict(node) && !node.has('Type') && node.has('Contents'))) { + throw new Error('The reference does not point to a /Page Dict.'); + } + if (!node) { + return null; + } + assert(isDict(node), 'node must be a Dict.'); + parentRef = node.getRaw('Parent'); + return node.getAsync('Parent'); + }).then(function (parent) { + if (!parent) { + return null; + } + assert(isDict(parent), 'parent must be a Dict.'); + return parent.getAsync('Kids'); + }).then(function (kids) { + if (!kids) { + return null; + } + var kidPromises = []; + var found = false; + for (var i = 0; i < kids.length; i++) { + var kid = kids[i]; + assert(isRef(kid), 'kid must be a Ref.'); + if (kid.num === kidRef.num) { + found = true; + break; + } + kidPromises.push(xref.fetchAsync(kid).then(function (kid) { + if (kid.has('Count')) { + var count = kid.get('Count'); + total += count; + } else { + total++; + } + })); + } + if (!found) { + error('kid ref not found in parents kids'); + } + return Promise.all(kidPromises).then(function () { + return [ + total, + parentRef + ]; + }); + }); + } + var total = 0; + function next(ref) { + return pagesBeforeRef(ref).then(function (args) { + if (!args) { + return total; + } + var count = args[0]; + var parentRef = args[1]; + total += count; + return next(parentRef); + }); + } + return next(pageRef); + } + }; + Catalog.parseDestDictionary = function Catalog_parseDestDictionary(params) { + function addDefaultProtocolToUrl(url) { + if (url.indexOf('www.') === 0) { + return 'http://' + url; + } + return url; + } + function tryConvertUrlEncoding(url) { + try { + return stringToUTF8String(url); + } catch (e) { + return url; + } + } + var destDict = params.destDict; + if (!isDict(destDict)) { + warn('Catalog_parseDestDictionary: "destDict" must be a dictionary.'); + return; + } + var resultObj = params.resultObj; + if (typeof resultObj !== 'object') { + warn('Catalog_parseDestDictionary: "resultObj" must be an object.'); + return; + } + var docBaseUrl = params.docBaseUrl || null; + var action = destDict.get('A'), url, dest; + if (isDict(action)) { + var linkType = action.get('S').name; + switch (linkType) { + case 'URI': + url = action.get('URI'); + if (isName(url)) { + url = '/' + url.name; + } else if (isString(url)) { + url = addDefaultProtocolToUrl(url); + } + break; + case 'GoTo': + dest = action.get('D'); + break; + case 'Launch': + case 'GoToR': + var urlDict = action.get('F'); + if (isDict(urlDict)) { + url = urlDict.get('F') || null; + } else if (isString(urlDict)) { + url = urlDict; + } + var remoteDest = action.get('D'); + if (remoteDest) { + if (isName(remoteDest)) { + remoteDest = remoteDest.name; + } + if (isString(url)) { + var baseUrl = url.split('#')[0]; + if (isString(remoteDest)) { + url = baseUrl + '#' + (/^\d+$/.test(remoteDest) ? 'nameddest=' : '') + remoteDest; + } else if (isArray(remoteDest)) { + url = baseUrl + '#' + JSON.stringify(remoteDest); + } + } + } + var newWindow = action.get('NewWindow'); + if (isBool(newWindow)) { + resultObj.newWindow = newWindow; + } + break; + case 'Named': + var namedAction = action.get('N'); + if (isName(namedAction)) { + resultObj.action = namedAction.name; + } + break; + case 'JavaScript': + var jsAction = action.get('JS'), js; + if (isStream(jsAction)) { + js = bytesToString(jsAction.getBytes()); + } else if (isString(jsAction)) { + js = jsAction; + } + if (js) { + var URL_OPEN_METHODS = [ + 'app.launchURL', + 'window.open' + ]; + var regex = new RegExp('^\\s*(' + URL_OPEN_METHODS.join('|').split('.').join('\\.') + ')\\((?:\'|\")([^\'\"]*)(?:\'|\")(?:,\\s*(\\w+)\\)|\\))', 'i'); + var jsUrl = regex.exec(stringToPDFString(js)); + if (jsUrl && jsUrl[2]) { + url = jsUrl[2]; + if (jsUrl[3] === 'true' && jsUrl[1] === 'app.launchURL') { + resultObj.newWindow = true; + } + break; + } + } + default: + warn('Catalog_parseDestDictionary: Unrecognized link type "' + linkType + '".'); + break; + } + } else if (destDict.has('Dest')) { + dest = destDict.get('Dest'); + } + if (isString(url)) { + url = tryConvertUrlEncoding(url); + var absoluteUrl = createValidAbsoluteUrl(url, docBaseUrl); + if (absoluteUrl) { + resultObj.url = absoluteUrl.href; + } + resultObj.unsafeUrl = url; + } + if (dest) { + if (isName(dest)) { + dest = dest.name; + } + if (isString(dest) || isArray(dest)) { + resultObj.dest = dest; + } + } + }; + return Catalog; +}(); +var XRef = function XRefClosure() { + function XRef(stream, pdfManager) { + this.stream = stream; + this.pdfManager = pdfManager; + this.entries = []; + this.xrefstms = Object.create(null); + this.cache = []; + this.stats = { + streamTypes: [], + fontTypes: [] + }; + } + XRef.prototype = { + setStartXRef: function XRef_setStartXRef(startXRef) { + this.startXRefQueue = [startXRef]; + }, + parse: function XRef_parse(recoveryMode) { + var trailerDict; + if (!recoveryMode) { + trailerDict = this.readXRef(); + } else { + warn('Indexing all PDF objects'); + trailerDict = this.indexObjects(); + } + trailerDict.assignXref(this); + this.trailer = trailerDict; + var encrypt = trailerDict.get('Encrypt'); + if (isDict(encrypt)) { + var ids = trailerDict.get('ID'); + var fileId = ids && ids.length ? ids[0] : ''; + encrypt.suppressEncryption = true; + this.encrypt = new CipherTransformFactory(encrypt, fileId, this.pdfManager.password); + } + if (!(this.root = trailerDict.get('Root'))) { + error('Invalid root reference'); + } + }, + processXRefTable: function XRef_processXRefTable(parser) { + if (!('tableState' in this)) { + this.tableState = { + entryNum: 0, + streamPos: parser.lexer.stream.pos, + parserBuf1: parser.buf1, + parserBuf2: parser.buf2 + }; + } + var obj = this.readXRefTable(parser); + if (!isCmd(obj, 'trailer')) { + error('Invalid XRef table: could not find trailer dictionary'); + } + var dict = parser.getObj(); + if (!isDict(dict) && dict.dict) { + dict = dict.dict; + } + if (!isDict(dict)) { + error('Invalid XRef table: could not parse trailer dictionary'); + } + delete this.tableState; + return dict; + }, + readXRefTable: function XRef_readXRefTable(parser) { + var stream = parser.lexer.stream; + var tableState = this.tableState; + stream.pos = tableState.streamPos; + parser.buf1 = tableState.parserBuf1; + parser.buf2 = tableState.parserBuf2; + var obj; + while (true) { + if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) { + if (isCmd(obj = parser.getObj(), 'trailer')) { + break; + } + tableState.firstEntryNum = obj; + tableState.entryCount = parser.getObj(); + } + var first = tableState.firstEntryNum; + var count = tableState.entryCount; + if (!isInt(first) || !isInt(count)) { + error('Invalid XRef table: wrong types in subsection header'); + } + for (var i = tableState.entryNum; i < count; i++) { + tableState.streamPos = stream.pos; + tableState.entryNum = i; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + var entry = {}; + entry.offset = parser.getObj(); + entry.gen = parser.getObj(); + var type = parser.getObj(); + if (isCmd(type, 'f')) { + entry.free = true; + } else if (isCmd(type, 'n')) { + entry.uncompressed = true; + } + if (!isInt(entry.offset) || !isInt(entry.gen) || !(entry.free || entry.uncompressed)) { + error('Invalid entry in XRef subsection: ' + first + ', ' + count); + } + if (i === 0 && entry.free && first === 1) { + first = 0; + } + if (!this.entries[i + first]) { + this.entries[i + first] = entry; + } + } + tableState.entryNum = 0; + tableState.streamPos = stream.pos; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + delete tableState.firstEntryNum; + delete tableState.entryCount; + } + if (this.entries[0] && !this.entries[0].free) { + error('Invalid XRef table: unexpected first object'); + } + return obj; + }, + processXRefStream: function XRef_processXRefStream(stream) { + if (!('streamState' in this)) { + var streamParameters = stream.dict; + var byteWidths = streamParameters.get('W'); + var range = streamParameters.get('Index'); + if (!range) { + range = [ + 0, + streamParameters.get('Size') + ]; + } + this.streamState = { + entryRanges: range, + byteWidths: byteWidths, + entryNum: 0, + streamPos: stream.pos + }; + } + this.readXRefStream(stream); + delete this.streamState; + return stream.dict; + }, + readXRefStream: function XRef_readXRefStream(stream) { + var i, j; + var streamState = this.streamState; + stream.pos = streamState.streamPos; + var byteWidths = streamState.byteWidths; + var typeFieldWidth = byteWidths[0]; + var offsetFieldWidth = byteWidths[1]; + var generationFieldWidth = byteWidths[2]; + var entryRanges = streamState.entryRanges; + while (entryRanges.length > 0) { + var first = entryRanges[0]; + var n = entryRanges[1]; + if (!isInt(first) || !isInt(n)) { + error('Invalid XRef range fields: ' + first + ', ' + n); + } + if (!isInt(typeFieldWidth) || !isInt(offsetFieldWidth) || !isInt(generationFieldWidth)) { + error('Invalid XRef entry fields length: ' + first + ', ' + n); + } + for (i = streamState.entryNum; i < n; ++i) { + streamState.entryNum = i; + streamState.streamPos = stream.pos; + var type = 0, offset = 0, generation = 0; + for (j = 0; j < typeFieldWidth; ++j) { + type = type << 8 | stream.getByte(); + } + if (typeFieldWidth === 0) { + type = 1; + } + for (j = 0; j < offsetFieldWidth; ++j) { + offset = offset << 8 | stream.getByte(); + } + for (j = 0; j < generationFieldWidth; ++j) { + generation = generation << 8 | stream.getByte(); + } + var entry = {}; + entry.offset = offset; + entry.gen = generation; + switch (type) { + case 0: + entry.free = true; + break; + case 1: + entry.uncompressed = true; + break; + case 2: + break; + default: + error('Invalid XRef entry type: ' + type); + } + if (!this.entries[first + i]) { + this.entries[first + i] = entry; + } + } + streamState.entryNum = 0; + streamState.streamPos = stream.pos; + entryRanges.splice(0, 2); + } + }, + indexObjects: function XRef_indexObjects() { + var TAB = 0x9, LF = 0xA, CR = 0xD, SPACE = 0x20; + var PERCENT = 0x25, LT = 0x3C; + function readToken(data, offset) { + var token = '', ch = data[offset]; + while (ch !== LF && ch !== CR && ch !== LT) { + if (++offset >= data.length) { + break; + } + token += String.fromCharCode(ch); + ch = data[offset]; + } + return token; + } + function skipUntil(data, offset, what) { + var length = what.length, dataLength = data.length; + var skipped = 0; + while (offset < dataLength) { + var i = 0; + while (i < length && data[offset + i] === what[i]) { + ++i; + } + if (i >= length) { + break; + } + offset++; + skipped++; + } + return skipped; + } + var objRegExp = /^(\d+)\s+(\d+)\s+obj\b/; + var trailerBytes = new Uint8Array([ + 116, + 114, + 97, + 105, + 108, + 101, + 114 + ]); + var startxrefBytes = new Uint8Array([ + 115, + 116, + 97, + 114, + 116, + 120, + 114, + 101, + 102 + ]); + var endobjBytes = new Uint8Array([ + 101, + 110, + 100, + 111, + 98, + 106 + ]); + var xrefBytes = new Uint8Array([ + 47, + 88, + 82, + 101, + 102 + ]); + this.entries.length = 0; + var stream = this.stream; + stream.pos = 0; + var buffer = stream.getBytes(); + var position = stream.start, length = buffer.length; + var trailers = [], xrefStms = []; + while (position < length) { + var ch = buffer[position]; + if (ch === TAB || ch === LF || ch === CR || ch === SPACE) { + ++position; + continue; + } + if (ch === PERCENT) { + do { + ++position; + if (position >= length) { + break; + } + ch = buffer[position]; + } while (ch !== LF && ch !== CR); + continue; + } + var token = readToken(buffer, position); + var m; + if (token.indexOf('xref') === 0 && (token.length === 4 || /\s/.test(token[4]))) { + position += skipUntil(buffer, position, trailerBytes); + trailers.push(position); + position += skipUntil(buffer, position, startxrefBytes); + } else if (m = objRegExp.exec(token)) { + if (typeof this.entries[m[1]] === 'undefined') { + this.entries[m[1]] = { + offset: position - stream.start, + gen: m[2] | 0, + uncompressed: true + }; + } + var contentLength = skipUntil(buffer, position, endobjBytes) + 7; + var content = buffer.subarray(position, position + contentLength); + var xrefTagOffset = skipUntil(content, 0, xrefBytes); + if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) { + xrefStms.push(position - stream.start); + this.xrefstms[position - stream.start] = 1; + } + position += contentLength; + } else if (token.indexOf('trailer') === 0 && (token.length === 7 || /\s/.test(token[7]))) { + trailers.push(position); + position += skipUntil(buffer, position, startxrefBytes); + } else { + position += token.length + 1; + } + } + var i, ii; + for (i = 0, ii = xrefStms.length; i < ii; ++i) { + this.startXRefQueue.push(xrefStms[i]); + this.readXRef(true); + } + var dict; + for (i = 0, ii = trailers.length; i < ii; ++i) { + stream.pos = trailers[i]; + var parser = new Parser(new Lexer(stream), true, this, true); + var obj = parser.getObj(); + if (!isCmd(obj, 'trailer')) { + continue; + } + dict = parser.getObj(); + if (!isDict(dict)) { + continue; + } + if (dict.has('ID')) { + return dict; + } + } + if (dict) { + return dict; + } + throw new InvalidPDFException('Invalid PDF structure'); + }, + readXRef: function XRef_readXRef(recoveryMode) { + var stream = this.stream; + try { + while (this.startXRefQueue.length) { + var startXRef = this.startXRefQueue[0]; + stream.pos = startXRef + stream.start; + var parser = new Parser(new Lexer(stream), true, this); + var obj = parser.getObj(); + var dict; + if (isCmd(obj, 'xref')) { + dict = this.processXRefTable(parser); + if (!this.topDict) { + this.topDict = dict; + } + obj = dict.get('XRefStm'); + if (isInt(obj)) { + var pos = obj; + if (!(pos in this.xrefstms)) { + this.xrefstms[pos] = 1; + this.startXRefQueue.push(pos); + } + } + } else if (isInt(obj)) { + if (!isInt(parser.getObj()) || !isCmd(parser.getObj(), 'obj') || !isStream(obj = parser.getObj())) { + error('Invalid XRef stream'); + } + dict = this.processXRefStream(obj); + if (!this.topDict) { + this.topDict = dict; + } + if (!dict) { + error('Failed to read XRef stream'); + } + } else { + error('Invalid XRef stream header'); + } + obj = dict.get('Prev'); + if (isInt(obj)) { + this.startXRefQueue.push(obj); + } else if (isRef(obj)) { + this.startXRefQueue.push(obj.num); + } + this.startXRefQueue.shift(); + } + return this.topDict; + } catch (e) { + if (e instanceof MissingDataException) { + throw e; + } + info('(while reading XRef): ' + e); + } + if (recoveryMode) { + return; + } + throw new XRefParseException(); + }, + getEntry: function XRef_getEntry(i) { + var xrefEntry = this.entries[i]; + if (xrefEntry && !xrefEntry.free && xrefEntry.offset) { + return xrefEntry; + } + return null; + }, + fetchIfRef: function XRef_fetchIfRef(obj, suppressEncryption) { + if (!isRef(obj)) { + return obj; + } + return this.fetch(obj, suppressEncryption); + }, + fetch: function XRef_fetch(ref, suppressEncryption) { + assert(isRef(ref), 'ref object is not a reference'); + var num = ref.num; + if (num in this.cache) { + var cacheEntry = this.cache[num]; + if (isDict(cacheEntry) && !cacheEntry.objId) { + cacheEntry.objId = ref.toString(); + } + return cacheEntry; + } + var xrefEntry = this.getEntry(num); + if (xrefEntry === null) { + return this.cache[num] = null; + } + if (xrefEntry.uncompressed) { + xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption); + } else { + xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption); + } + if (isDict(xrefEntry)) { + xrefEntry.objId = ref.toString(); + } else if (isStream(xrefEntry)) { + xrefEntry.dict.objId = ref.toString(); + } + return xrefEntry; + }, + fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry, suppressEncryption) { + var gen = ref.gen; + var num = ref.num; + if (xrefEntry.gen !== gen) { + error('inconsistent generation in XRef'); + } + var stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start); + var parser = new Parser(new Lexer(stream), true, this); + var obj1 = parser.getObj(); + var obj2 = parser.getObj(); + var obj3 = parser.getObj(); + if (!isInt(obj1) || parseInt(obj1, 10) !== num || !isInt(obj2) || parseInt(obj2, 10) !== gen || !isCmd(obj3)) { + error('bad XRef entry'); + } + if (!isCmd(obj3, 'obj')) { + if (obj3.cmd.indexOf('obj') === 0) { + num = parseInt(obj3.cmd.substring(3), 10); + if (!isNaN(num)) { + return num; + } + } + error('bad XRef entry'); + } + if (this.encrypt && !suppressEncryption) { + xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen)); + } else { + xrefEntry = parser.getObj(); + } + if (!isStream(xrefEntry)) { + this.cache[num] = xrefEntry; + } + return xrefEntry; + }, + fetchCompressed: function XRef_fetchCompressed(xrefEntry, suppressEncryption) { + var tableOffset = xrefEntry.offset; + var stream = this.fetch(new Ref(tableOffset, 0)); + if (!isStream(stream)) { + error('bad ObjStm stream'); + } + var first = stream.dict.get('First'); + var n = stream.dict.get('N'); + if (!isInt(first) || !isInt(n)) { + error('invalid first and n parameters for ObjStm stream'); + } + var parser = new Parser(new Lexer(stream), false, this); + parser.allowStreams = true; + var i, entries = [], num, nums = []; + for (i = 0; i < n; ++i) { + num = parser.getObj(); + if (!isInt(num)) { + error('invalid object number in the ObjStm stream: ' + num); + } + nums.push(num); + var offset = parser.getObj(); + if (!isInt(offset)) { + error('invalid object offset in the ObjStm stream: ' + offset); + } + } + for (i = 0; i < n; ++i) { + entries.push(parser.getObj()); + if (isCmd(parser.buf1, 'endobj')) { + parser.shift(); + } + num = nums[i]; + var entry = this.entries[num]; + if (entry && entry.offset === tableOffset && entry.gen === i) { + this.cache[num] = entries[i]; + } + } + xrefEntry = entries[xrefEntry.gen]; + if (xrefEntry === undefined) { + error('bad XRef entry for compressed object'); + } + return xrefEntry; + }, + fetchIfRefAsync: function XRef_fetchIfRefAsync(obj, suppressEncryption) { + if (!isRef(obj)) { + return Promise.resolve(obj); + } + return this.fetchAsync(obj, suppressEncryption); + }, + fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) { + var streamManager = this.stream.manager; + var xref = this; + return new Promise(function tryFetch(resolve, reject) { + try { + resolve(xref.fetch(ref, suppressEncryption)); + } catch (e) { + if (e instanceof MissingDataException) { + streamManager.requestRange(e.begin, e.end).then(function () { + tryFetch(resolve, reject); + }, reject); + return; + } + reject(e); + } + }); + }, + getCatalogObj: function XRef_getCatalogObj() { + return this.root; + } + }; + return XRef; +}(); +var NameOrNumberTree = function NameOrNumberTreeClosure() { + function NameOrNumberTree(root, xref) { + throw new Error('Cannot initialize NameOrNumberTree.'); + } + NameOrNumberTree.prototype = { + getAll: function NameOrNumberTree_getAll() { + var dict = Object.create(null); + if (!this.root) { + return dict; + } + var xref = this.xref; + var processed = new RefSet(); + processed.put(this.root); + var queue = [this.root]; + while (queue.length > 0) { + var i, n; + var obj = xref.fetchIfRef(queue.shift()); + if (!isDict(obj)) { + continue; + } + if (obj.has('Kids')) { + var kids = obj.get('Kids'); + for (i = 0, n = kids.length; i < n; i++) { + var kid = kids[i]; + assert(!processed.has(kid), 'Duplicate entry in "' + this._type + '" tree.'); + queue.push(kid); + processed.put(kid); + } + continue; + } + var entries = obj.get(this._type); + if (isArray(entries)) { + for (i = 0, n = entries.length; i < n; i += 2) { + dict[xref.fetchIfRef(entries[i])] = xref.fetchIfRef(entries[i + 1]); + } + } + } + return dict; + }, + get: function NameOrNumberTree_get(key) { + if (!this.root) { + return null; + } + var xref = this.xref; + var kidsOrEntries = xref.fetchIfRef(this.root); + var loopCount = 0; + var MAX_LEVELS = 10; + var l, r, m; + while (kidsOrEntries.has('Kids')) { + if (++loopCount > MAX_LEVELS) { + warn('Search depth limit reached for "' + this._type + '" tree.'); + return null; + } + var kids = kidsOrEntries.get('Kids'); + if (!isArray(kids)) { + return null; + } + l = 0; + r = kids.length - 1; + while (l <= r) { + m = l + r >> 1; + var kid = xref.fetchIfRef(kids[m]); + var limits = kid.get('Limits'); + if (key < xref.fetchIfRef(limits[0])) { + r = m - 1; + } else if (key > xref.fetchIfRef(limits[1])) { + l = m + 1; + } else { + kidsOrEntries = xref.fetchIfRef(kids[m]); + break; + } + } + if (l > r) { + return null; + } + } + var entries = kidsOrEntries.get(this._type); + if (isArray(entries)) { + l = 0; + r = entries.length - 2; + while (l <= r) { + m = l + r & ~1; + var currentKey = xref.fetchIfRef(entries[m]); + if (key < currentKey) { + r = m - 2; + } else if (key > currentKey) { + l = m + 2; + } else { + return xref.fetchIfRef(entries[m + 1]); + } + } + } + return null; + } + }; + return NameOrNumberTree; +}(); +var NameTree = function NameTreeClosure() { + function NameTree(root, xref) { + this.root = root; + this.xref = xref; + this._type = 'Names'; + } + Util.inherit(NameTree, NameOrNumberTree, {}); + return NameTree; +}(); +var NumberTree = function NumberTreeClosure() { + function NumberTree(root, xref) { + this.root = root; + this.xref = xref; + this._type = 'Nums'; + } + Util.inherit(NumberTree, NameOrNumberTree, {}); + return NumberTree; +}(); +var FileSpec = function FileSpecClosure() { + function FileSpec(root, xref) { + if (!root || !isDict(root)) { + return; + } + this.xref = xref; + this.root = root; + if (root.has('FS')) { + this.fs = root.get('FS'); + } + this.description = root.has('Desc') ? stringToPDFString(root.get('Desc')) : ''; + if (root.has('RF')) { + warn('Related file specifications are not supported'); + } + this.contentAvailable = true; + if (!root.has('EF')) { + this.contentAvailable = false; + warn('Non-embedded file specifications are not supported'); + } + } + function pickPlatformItem(dict) { + if (dict.has('UF')) { + return dict.get('UF'); + } else if (dict.has('F')) { + return dict.get('F'); + } else if (dict.has('Unix')) { + return dict.get('Unix'); + } else if (dict.has('Mac')) { + return dict.get('Mac'); + } else if (dict.has('DOS')) { + return dict.get('DOS'); + } + return null; + } + FileSpec.prototype = { + get filename() { + if (!this._filename && this.root) { + var filename = pickPlatformItem(this.root) || 'unnamed'; + this._filename = stringToPDFString(filename).replace(/\\\\/g, '\\').replace(/\\\//g, '/').replace(/\\/g, '/'); + } + return this._filename; + }, + get content() { + if (!this.contentAvailable) { + return null; + } + if (!this.contentRef && this.root) { + this.contentRef = pickPlatformItem(this.root.get('EF')); + } + var content = null; + if (this.contentRef) { + var xref = this.xref; + var fileObj = xref.fetchIfRef(this.contentRef); + if (fileObj && isStream(fileObj)) { + content = fileObj.getBytes(); + } else { + warn('Embedded file specification points to non-existing/invalid ' + 'content'); + } + } else { + warn('Embedded file specification does not have a content'); + } + return content; + }, + get serializable() { + return { + filename: this.filename, + content: this.content + }; + } + }; + return FileSpec; +}(); +var ObjectLoader = function () { + function mayHaveChildren(value) { + return isRef(value) || isDict(value) || isArray(value) || isStream(value); + } + function addChildren(node, nodesToVisit) { + var value; + if (isDict(node) || isStream(node)) { + var map; + if (isDict(node)) { + map = node.map; + } else { + map = node.dict.map; + } + for (var key in map) { + value = map[key]; + if (mayHaveChildren(value)) { + nodesToVisit.push(value); + } + } + } else if (isArray(node)) { + for (var i = 0, ii = node.length; i < ii; i++) { + value = node[i]; + if (mayHaveChildren(value)) { + nodesToVisit.push(value); + } + } + } + } + function ObjectLoader(obj, keys, xref) { + this.obj = obj; + this.keys = keys; + this.xref = xref; + this.refSet = null; + this.capability = null; + } + ObjectLoader.prototype = { + load: function ObjectLoader_load() { + var keys = this.keys; + this.capability = createPromiseCapability(); + if (!(this.xref.stream instanceof ChunkedStream) || this.xref.stream.getMissingChunks().length === 0) { + this.capability.resolve(); + return this.capability.promise; + } + this.refSet = new RefSet(); + var nodesToVisit = []; + for (var i = 0; i < keys.length; i++) { + nodesToVisit.push(this.obj[keys[i]]); + } + this._walk(nodesToVisit); + return this.capability.promise; + }, + _walk: function ObjectLoader_walk(nodesToVisit) { + var nodesToRevisit = []; + var pendingRequests = []; + while (nodesToVisit.length) { + var currentNode = nodesToVisit.pop(); + if (isRef(currentNode)) { + if (this.refSet.has(currentNode)) { + continue; + } + try { + var ref = currentNode; + this.refSet.put(ref); + currentNode = this.xref.fetch(currentNode); + } catch (e) { + if (!(e instanceof MissingDataException)) { + throw e; + } + nodesToRevisit.push(currentNode); + pendingRequests.push({ + begin: e.begin, + end: e.end + }); + } + } + if (currentNode && currentNode.getBaseStreams) { + var baseStreams = currentNode.getBaseStreams(); + var foundMissingData = false; + for (var i = 0; i < baseStreams.length; i++) { + var stream = baseStreams[i]; + if (stream.getMissingChunks && stream.getMissingChunks().length) { + foundMissingData = true; + pendingRequests.push({ + begin: stream.start, + end: stream.end + }); + } + } + if (foundMissingData) { + nodesToRevisit.push(currentNode); + } + } + addChildren(currentNode, nodesToVisit); + } + if (pendingRequests.length) { + this.xref.stream.manager.requestRanges(pendingRequests).then(function pendingRequestCallback() { + nodesToVisit = nodesToRevisit; + for (var i = 0; i < nodesToRevisit.length; i++) { + var node = nodesToRevisit[i]; + if (isRef(node)) { + this.refSet.remove(node); + } + } + this._walk(nodesToVisit); + }.bind(this), this.capability.reject); + return; + } + this.refSet = null; + this.capability.resolve(); + } + }; + return ObjectLoader; +}(); +exports.Catalog = Catalog; +exports.ObjectLoader = ObjectLoader; +exports.XRef = XRef; +exports.FileSpec = FileSpec; + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var getLookupTableFactory = sharedUtil.getLookupTableFactory; +var getStdFontMap = getLookupTableFactory(function (t) { + t['ArialNarrow'] = 'Helvetica'; + t['ArialNarrow-Bold'] = 'Helvetica-Bold'; + t['ArialNarrow-BoldItalic'] = 'Helvetica-BoldOblique'; + t['ArialNarrow-Italic'] = 'Helvetica-Oblique'; + t['ArialBlack'] = 'Helvetica'; + t['ArialBlack-Bold'] = 'Helvetica-Bold'; + t['ArialBlack-BoldItalic'] = 'Helvetica-BoldOblique'; + t['ArialBlack-Italic'] = 'Helvetica-Oblique'; + t['Arial-Black'] = 'Helvetica'; + t['Arial-Black-Bold'] = 'Helvetica-Bold'; + t['Arial-Black-BoldItalic'] = 'Helvetica-BoldOblique'; + t['Arial-Black-Italic'] = 'Helvetica-Oblique'; + t['Arial'] = 'Helvetica'; + t['Arial-Bold'] = 'Helvetica-Bold'; + t['Arial-BoldItalic'] = 'Helvetica-BoldOblique'; + t['Arial-Italic'] = 'Helvetica-Oblique'; + t['Arial-BoldItalicMT'] = 'Helvetica-BoldOblique'; + t['Arial-BoldMT'] = 'Helvetica-Bold'; + t['Arial-ItalicMT'] = 'Helvetica-Oblique'; + t['ArialMT'] = 'Helvetica'; + t['Courier-Bold'] = 'Courier-Bold'; + t['Courier-BoldItalic'] = 'Courier-BoldOblique'; + t['Courier-Italic'] = 'Courier-Oblique'; + t['CourierNew'] = 'Courier'; + t['CourierNew-Bold'] = 'Courier-Bold'; + t['CourierNew-BoldItalic'] = 'Courier-BoldOblique'; + t['CourierNew-Italic'] = 'Courier-Oblique'; + t['CourierNewPS-BoldItalicMT'] = 'Courier-BoldOblique'; + t['CourierNewPS-BoldMT'] = 'Courier-Bold'; + t['CourierNewPS-ItalicMT'] = 'Courier-Oblique'; + t['CourierNewPSMT'] = 'Courier'; + t['Helvetica'] = 'Helvetica'; + t['Helvetica-Bold'] = 'Helvetica-Bold'; + t['Helvetica-BoldItalic'] = 'Helvetica-BoldOblique'; + t['Helvetica-BoldOblique'] = 'Helvetica-BoldOblique'; + t['Helvetica-Italic'] = 'Helvetica-Oblique'; + t['Helvetica-Oblique'] = 'Helvetica-Oblique'; + t['Symbol-Bold'] = 'Symbol'; + t['Symbol-BoldItalic'] = 'Symbol'; + t['Symbol-Italic'] = 'Symbol'; + t['TimesNewRoman'] = 'Times-Roman'; + t['TimesNewRoman-Bold'] = 'Times-Bold'; + t['TimesNewRoman-BoldItalic'] = 'Times-BoldItalic'; + t['TimesNewRoman-Italic'] = 'Times-Italic'; + t['TimesNewRomanPS'] = 'Times-Roman'; + t['TimesNewRomanPS-Bold'] = 'Times-Bold'; + t['TimesNewRomanPS-BoldItalic'] = 'Times-BoldItalic'; + t['TimesNewRomanPS-BoldItalicMT'] = 'Times-BoldItalic'; + t['TimesNewRomanPS-BoldMT'] = 'Times-Bold'; + t['TimesNewRomanPS-Italic'] = 'Times-Italic'; + t['TimesNewRomanPS-ItalicMT'] = 'Times-Italic'; + t['TimesNewRomanPSMT'] = 'Times-Roman'; + t['TimesNewRomanPSMT-Bold'] = 'Times-Bold'; + t['TimesNewRomanPSMT-BoldItalic'] = 'Times-BoldItalic'; + t['TimesNewRomanPSMT-Italic'] = 'Times-Italic'; +}); +var getNonStdFontMap = getLookupTableFactory(function (t) { + t['CenturyGothic'] = 'Helvetica'; + t['CenturyGothic-Bold'] = 'Helvetica-Bold'; + t['CenturyGothic-BoldItalic'] = 'Helvetica-BoldOblique'; + t['CenturyGothic-Italic'] = 'Helvetica-Oblique'; + t['ComicSansMS'] = 'Comic Sans MS'; + t['ComicSansMS-Bold'] = 'Comic Sans MS-Bold'; + t['ComicSansMS-BoldItalic'] = 'Comic Sans MS-BoldItalic'; + t['ComicSansMS-Italic'] = 'Comic Sans MS-Italic'; + t['LucidaConsole'] = 'Courier'; + t['LucidaConsole-Bold'] = 'Courier-Bold'; + t['LucidaConsole-BoldItalic'] = 'Courier-BoldOblique'; + t['LucidaConsole-Italic'] = 'Courier-Oblique'; + t['MS-Gothic'] = 'MS Gothic'; + t['MS-Gothic-Bold'] = 'MS Gothic-Bold'; + t['MS-Gothic-BoldItalic'] = 'MS Gothic-BoldItalic'; + t['MS-Gothic-Italic'] = 'MS Gothic-Italic'; + t['MS-Mincho'] = 'MS Mincho'; + t['MS-Mincho-Bold'] = 'MS Mincho-Bold'; + t['MS-Mincho-BoldItalic'] = 'MS Mincho-BoldItalic'; + t['MS-Mincho-Italic'] = 'MS Mincho-Italic'; + t['MS-PGothic'] = 'MS PGothic'; + t['MS-PGothic-Bold'] = 'MS PGothic-Bold'; + t['MS-PGothic-BoldItalic'] = 'MS PGothic-BoldItalic'; + t['MS-PGothic-Italic'] = 'MS PGothic-Italic'; + t['MS-PMincho'] = 'MS PMincho'; + t['MS-PMincho-Bold'] = 'MS PMincho-Bold'; + t['MS-PMincho-BoldItalic'] = 'MS PMincho-BoldItalic'; + t['MS-PMincho-Italic'] = 'MS PMincho-Italic'; + t['NuptialScript'] = 'Times-Italic'; + t['Wingdings'] = 'ZapfDingbats'; +}); +var getSerifFonts = getLookupTableFactory(function (t) { + t['Adobe Jenson'] = true; + t['Adobe Text'] = true; + t['Albertus'] = true; + t['Aldus'] = true; + t['Alexandria'] = true; + t['Algerian'] = true; + t['American Typewriter'] = true; + t['Antiqua'] = true; + t['Apex'] = true; + t['Arno'] = true; + t['Aster'] = true; + t['Aurora'] = true; + t['Baskerville'] = true; + t['Bell'] = true; + t['Bembo'] = true; + t['Bembo Schoolbook'] = true; + t['Benguiat'] = true; + t['Berkeley Old Style'] = true; + t['Bernhard Modern'] = true; + t['Berthold City'] = true; + t['Bodoni'] = true; + t['Bauer Bodoni'] = true; + t['Book Antiqua'] = true; + t['Bookman'] = true; + t['Bordeaux Roman'] = true; + t['Californian FB'] = true; + t['Calisto'] = true; + t['Calvert'] = true; + t['Capitals'] = true; + t['Cambria'] = true; + t['Cartier'] = true; + t['Caslon'] = true; + t['Catull'] = true; + t['Centaur'] = true; + t['Century Old Style'] = true; + t['Century Schoolbook'] = true; + t['Chaparral'] = true; + t['Charis SIL'] = true; + t['Cheltenham'] = true; + t['Cholla Slab'] = true; + t['Clarendon'] = true; + t['Clearface'] = true; + t['Cochin'] = true; + t['Colonna'] = true; + t['Computer Modern'] = true; + t['Concrete Roman'] = true; + t['Constantia'] = true; + t['Cooper Black'] = true; + t['Corona'] = true; + t['Ecotype'] = true; + t['Egyptienne'] = true; + t['Elephant'] = true; + t['Excelsior'] = true; + t['Fairfield'] = true; + t['FF Scala'] = true; + t['Folkard'] = true; + t['Footlight'] = true; + t['FreeSerif'] = true; + t['Friz Quadrata'] = true; + t['Garamond'] = true; + t['Gentium'] = true; + t['Georgia'] = true; + t['Gloucester'] = true; + t['Goudy Old Style'] = true; + t['Goudy Schoolbook'] = true; + t['Goudy Pro Font'] = true; + t['Granjon'] = true; + t['Guardian Egyptian'] = true; + t['Heather'] = true; + t['Hercules'] = true; + t['High Tower Text'] = true; + t['Hiroshige'] = true; + t['Hoefler Text'] = true; + t['Humana Serif'] = true; + t['Imprint'] = true; + t['Ionic No. 5'] = true; + t['Janson'] = true; + t['Joanna'] = true; + t['Korinna'] = true; + t['Lexicon'] = true; + t['Liberation Serif'] = true; + t['Linux Libertine'] = true; + t['Literaturnaya'] = true; + t['Lucida'] = true; + t['Lucida Bright'] = true; + t['Melior'] = true; + t['Memphis'] = true; + t['Miller'] = true; + t['Minion'] = true; + t['Modern'] = true; + t['Mona Lisa'] = true; + t['Mrs Eaves'] = true; + t['MS Serif'] = true; + t['Museo Slab'] = true; + t['New York'] = true; + t['Nimbus Roman'] = true; + t['NPS Rawlinson Roadway'] = true; + t['NuptialScript'] = true; + t['Palatino'] = true; + t['Perpetua'] = true; + t['Plantin'] = true; + t['Plantin Schoolbook'] = true; + t['Playbill'] = true; + t['Poor Richard'] = true; + t['Rawlinson Roadway'] = true; + t['Renault'] = true; + t['Requiem'] = true; + t['Rockwell'] = true; + t['Roman'] = true; + t['Rotis Serif'] = true; + t['Sabon'] = true; + t['Scala'] = true; + t['Seagull'] = true; + t['Sistina'] = true; + t['Souvenir'] = true; + t['STIX'] = true; + t['Stone Informal'] = true; + t['Stone Serif'] = true; + t['Sylfaen'] = true; + t['Times'] = true; + t['Trajan'] = true; + t['Trinité'] = true; + t['Trump Mediaeval'] = true; + t['Utopia'] = true; + t['Vale Type'] = true; + t['Bitstream Vera'] = true; + t['Vera Serif'] = true; + t['Versailles'] = true; + t['Wanted'] = true; + t['Weiss'] = true; + t['Wide Latin'] = true; + t['Windsor'] = true; + t['XITS'] = true; +}); +var getSymbolsFonts = getLookupTableFactory(function (t) { + t['Dingbats'] = true; + t['Symbol'] = true; + t['ZapfDingbats'] = true; +}); +var getGlyphMapForStandardFonts = getLookupTableFactory(function (t) { + t[2] = 10; + t[3] = 32; + t[4] = 33; + t[5] = 34; + t[6] = 35; + t[7] = 36; + t[8] = 37; + t[9] = 38; + t[10] = 39; + t[11] = 40; + t[12] = 41; + t[13] = 42; + t[14] = 43; + t[15] = 44; + t[16] = 45; + t[17] = 46; + t[18] = 47; + t[19] = 48; + t[20] = 49; + t[21] = 50; + t[22] = 51; + t[23] = 52; + t[24] = 53; + t[25] = 54; + t[26] = 55; + t[27] = 56; + t[28] = 57; + t[29] = 58; + t[30] = 894; + t[31] = 60; + t[32] = 61; + t[33] = 62; + t[34] = 63; + t[35] = 64; + t[36] = 65; + t[37] = 66; + t[38] = 67; + t[39] = 68; + t[40] = 69; + t[41] = 70; + t[42] = 71; + t[43] = 72; + t[44] = 73; + t[45] = 74; + t[46] = 75; + t[47] = 76; + t[48] = 77; + t[49] = 78; + t[50] = 79; + t[51] = 80; + t[52] = 81; + t[53] = 82; + t[54] = 83; + t[55] = 84; + t[56] = 85; + t[57] = 86; + t[58] = 87; + t[59] = 88; + t[60] = 89; + t[61] = 90; + t[62] = 91; + t[63] = 92; + t[64] = 93; + t[65] = 94; + t[66] = 95; + t[67] = 96; + t[68] = 97; + t[69] = 98; + t[70] = 99; + t[71] = 100; + t[72] = 101; + t[73] = 102; + t[74] = 103; + t[75] = 104; + t[76] = 105; + t[77] = 106; + t[78] = 107; + t[79] = 108; + t[80] = 109; + t[81] = 110; + t[82] = 111; + t[83] = 112; + t[84] = 113; + t[85] = 114; + t[86] = 115; + t[87] = 116; + t[88] = 117; + t[89] = 118; + t[90] = 119; + t[91] = 120; + t[92] = 121; + t[93] = 122; + t[94] = 123; + t[95] = 124; + t[96] = 125; + t[97] = 126; + t[98] = 196; + t[99] = 197; + t[100] = 199; + t[101] = 201; + t[102] = 209; + t[103] = 214; + t[104] = 220; + t[105] = 225; + t[106] = 224; + t[107] = 226; + t[108] = 228; + t[109] = 227; + t[110] = 229; + t[111] = 231; + t[112] = 233; + t[113] = 232; + t[114] = 234; + t[115] = 235; + t[116] = 237; + t[117] = 236; + t[118] = 238; + t[119] = 239; + t[120] = 241; + t[121] = 243; + t[122] = 242; + t[123] = 244; + t[124] = 246; + t[125] = 245; + t[126] = 250; + t[127] = 249; + t[128] = 251; + t[129] = 252; + t[130] = 8224; + t[131] = 176; + t[132] = 162; + t[133] = 163; + t[134] = 167; + t[135] = 8226; + t[136] = 182; + t[137] = 223; + t[138] = 174; + t[139] = 169; + t[140] = 8482; + t[141] = 180; + t[142] = 168; + t[143] = 8800; + t[144] = 198; + t[145] = 216; + t[146] = 8734; + t[147] = 177; + t[148] = 8804; + t[149] = 8805; + t[150] = 165; + t[151] = 181; + t[152] = 8706; + t[153] = 8721; + t[154] = 8719; + t[156] = 8747; + t[157] = 170; + t[158] = 186; + t[159] = 8486; + t[160] = 230; + t[161] = 248; + t[162] = 191; + t[163] = 161; + t[164] = 172; + t[165] = 8730; + t[166] = 402; + t[167] = 8776; + t[168] = 8710; + t[169] = 171; + t[170] = 187; + t[171] = 8230; + t[210] = 218; + t[223] = 711; + t[224] = 321; + t[225] = 322; + t[227] = 353; + t[229] = 382; + t[234] = 253; + t[252] = 263; + t[253] = 268; + t[254] = 269; + t[258] = 258; + t[260] = 260; + t[261] = 261; + t[265] = 280; + t[266] = 281; + t[268] = 283; + t[269] = 313; + t[275] = 323; + t[276] = 324; + t[278] = 328; + t[284] = 345; + t[285] = 346; + t[286] = 347; + t[292] = 367; + t[295] = 377; + t[296] = 378; + t[298] = 380; + t[305] = 963; + t[306] = 964; + t[307] = 966; + t[308] = 8215; + t[309] = 8252; + t[310] = 8319; + t[311] = 8359; + t[312] = 8592; + t[313] = 8593; + t[337] = 9552; + t[493] = 1039; + t[494] = 1040; + t[705] = 1524; + t[706] = 8362; + t[710] = 64288; + t[711] = 64298; + t[759] = 1617; + t[761] = 1776; + t[763] = 1778; + t[775] = 1652; + t[777] = 1764; + t[778] = 1780; + t[779] = 1781; + t[780] = 1782; + t[782] = 771; + t[783] = 64726; + t[786] = 8363; + t[788] = 8532; + t[790] = 768; + t[791] = 769; + t[792] = 768; + t[795] = 803; + t[797] = 64336; + t[798] = 64337; + t[799] = 64342; + t[800] = 64343; + t[801] = 64344; + t[802] = 64345; + t[803] = 64362; + t[804] = 64363; + t[805] = 64364; + t[2424] = 7821; + t[2425] = 7822; + t[2426] = 7823; + t[2427] = 7824; + t[2428] = 7825; + t[2429] = 7826; + t[2430] = 7827; + t[2433] = 7682; + t[2678] = 8045; + t[2679] = 8046; + t[2830] = 1552; + t[2838] = 686; + t[2840] = 751; + t[2842] = 753; + t[2843] = 754; + t[2844] = 755; + t[2846] = 757; + t[2856] = 767; + t[2857] = 848; + t[2858] = 849; + t[2862] = 853; + t[2863] = 854; + t[2864] = 855; + t[2865] = 861; + t[2866] = 862; + t[2906] = 7460; + t[2908] = 7462; + t[2909] = 7463; + t[2910] = 7464; + t[2912] = 7466; + t[2913] = 7467; + t[2914] = 7468; + t[2916] = 7470; + t[2917] = 7471; + t[2918] = 7472; + t[2920] = 7474; + t[2921] = 7475; + t[2922] = 7476; + t[2924] = 7478; + t[2925] = 7479; + t[2926] = 7480; + t[2928] = 7482; + t[2929] = 7483; + t[2930] = 7484; + t[2932] = 7486; + t[2933] = 7487; + t[2934] = 7488; + t[2936] = 7490; + t[2937] = 7491; + t[2938] = 7492; + t[2940] = 7494; + t[2941] = 7495; + t[2942] = 7496; + t[2944] = 7498; + t[2946] = 7500; + t[2948] = 7502; + t[2950] = 7504; + t[2951] = 7505; + t[2952] = 7506; + t[2954] = 7508; + t[2955] = 7509; + t[2956] = 7510; + t[2958] = 7512; + t[2959] = 7513; + t[2960] = 7514; + t[2962] = 7516; + t[2963] = 7517; + t[2964] = 7518; + t[2966] = 7520; + t[2967] = 7521; + t[2968] = 7522; + t[2970] = 7524; + t[2971] = 7525; + t[2972] = 7526; + t[2974] = 7528; + t[2975] = 7529; + t[2976] = 7530; + t[2978] = 1537; + t[2979] = 1538; + t[2980] = 1539; + t[2982] = 1549; + t[2983] = 1551; + t[2984] = 1552; + t[2986] = 1554; + t[2987] = 1555; + t[2988] = 1556; + t[2990] = 1623; + t[2991] = 1624; + t[2995] = 1775; + t[2999] = 1791; + t[3002] = 64290; + t[3003] = 64291; + t[3004] = 64292; + t[3006] = 64294; + t[3007] = 64295; + t[3008] = 64296; + t[3011] = 1900; + t[3014] = 8223; + t[3015] = 8244; + t[3017] = 7532; + t[3018] = 7533; + t[3019] = 7534; + t[3075] = 7590; + t[3076] = 7591; + t[3079] = 7594; + t[3080] = 7595; + t[3083] = 7598; + t[3084] = 7599; + t[3087] = 7602; + t[3088] = 7603; + t[3091] = 7606; + t[3092] = 7607; + t[3095] = 7610; + t[3096] = 7611; + t[3099] = 7614; + t[3100] = 7615; + t[3103] = 7618; + t[3104] = 7619; + t[3107] = 8337; + t[3108] = 8338; + t[3116] = 1884; + t[3119] = 1885; + t[3120] = 1885; + t[3123] = 1886; + t[3124] = 1886; + t[3127] = 1887; + t[3128] = 1887; + t[3131] = 1888; + t[3132] = 1888; + t[3135] = 1889; + t[3136] = 1889; + t[3139] = 1890; + t[3140] = 1890; + t[3143] = 1891; + t[3144] = 1891; + t[3147] = 1892; + t[3148] = 1892; + t[3153] = 580; + t[3154] = 581; + t[3157] = 584; + t[3158] = 585; + t[3161] = 588; + t[3162] = 589; + t[3165] = 891; + t[3166] = 892; + t[3169] = 1274; + t[3170] = 1275; + t[3173] = 1278; + t[3174] = 1279; + t[3181] = 7622; + t[3182] = 7623; + t[3282] = 11799; + t[3316] = 578; + t[3379] = 42785; + t[3393] = 1159; + t[3416] = 8377; +}); +var getSupplementalGlyphMapForArialBlack = getLookupTableFactory(function (t) { + t[227] = 322; + t[264] = 261; + t[291] = 346; +}); +exports.getStdFontMap = getStdFontMap; +exports.getNonStdFontMap = getNonStdFontMap; +exports.getSerifFonts = getSerifFonts; +exports.getSymbolsFonts = getSymbolsFonts; +exports.getGlyphMapForStandardFonts = getGlyphMapForStandardFonts; +exports.getSupplementalGlyphMapForArialBlack = getSupplementalGlyphMapForArialBlack; + +/***/ }), +/* 18 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var getLookupTableFactory = sharedUtil.getLookupTableFactory; +var getSpecialPUASymbols = getLookupTableFactory(function (t) { + t[63721] = 0x00A9; + t[63193] = 0x00A9; + t[63720] = 0x00AE; + t[63194] = 0x00AE; + t[63722] = 0x2122; + t[63195] = 0x2122; + t[63729] = 0x23A7; + t[63730] = 0x23A8; + t[63731] = 0x23A9; + t[63740] = 0x23AB; + t[63741] = 0x23AC; + t[63742] = 0x23AD; + t[63726] = 0x23A1; + t[63727] = 0x23A2; + t[63728] = 0x23A3; + t[63737] = 0x23A4; + t[63738] = 0x23A5; + t[63739] = 0x23A6; + t[63723] = 0x239B; + t[63724] = 0x239C; + t[63725] = 0x239D; + t[63734] = 0x239E; + t[63735] = 0x239F; + t[63736] = 0x23A0; +}); +function mapSpecialUnicodeValues(code) { + if (code >= 0xFFF0 && code <= 0xFFFF) { + return 0; + } else if (code >= 0xF600 && code <= 0xF8FF) { + return getSpecialPUASymbols()[code] || code; + } + return code; +} +function getUnicodeForGlyph(name, glyphsUnicodeMap) { + var unicode = glyphsUnicodeMap[name]; + if (unicode !== undefined) { + return unicode; + } + if (!name) { + return -1; + } + if (name[0] === 'u') { + var nameLen = name.length, hexStr; + if (nameLen === 7 && name[1] === 'n' && name[2] === 'i') { + hexStr = name.substr(3); + } else if (nameLen >= 5 && nameLen <= 7) { + hexStr = name.substr(1); + } else { + return -1; + } + if (hexStr === hexStr.toUpperCase()) { + unicode = parseInt(hexStr, 16); + if (unicode >= 0) { + return unicode; + } + } + } + return -1; +} +var UnicodeRanges = [ + { + 'begin': 0x0000, + 'end': 0x007F + }, + { + 'begin': 0x0080, + 'end': 0x00FF + }, + { + 'begin': 0x0100, + 'end': 0x017F + }, + { + 'begin': 0x0180, + 'end': 0x024F + }, + { + 'begin': 0x0250, + 'end': 0x02AF + }, + { + 'begin': 0x02B0, + 'end': 0x02FF + }, + { + 'begin': 0x0300, + 'end': 0x036F + }, + { + 'begin': 0x0370, + 'end': 0x03FF + }, + { + 'begin': 0x2C80, + 'end': 0x2CFF + }, + { + 'begin': 0x0400, + 'end': 0x04FF + }, + { + 'begin': 0x0530, + 'end': 0x058F + }, + { + 'begin': 0x0590, + 'end': 0x05FF + }, + { + 'begin': 0xA500, + 'end': 0xA63F + }, + { + 'begin': 0x0600, + 'end': 0x06FF + }, + { + 'begin': 0x07C0, + 'end': 0x07FF + }, + { + 'begin': 0x0900, + 'end': 0x097F + }, + { + 'begin': 0x0980, + 'end': 0x09FF + }, + { + 'begin': 0x0A00, + 'end': 0x0A7F + }, + { + 'begin': 0x0A80, + 'end': 0x0AFF + }, + { + 'begin': 0x0B00, + 'end': 0x0B7F + }, + { + 'begin': 0x0B80, + 'end': 0x0BFF + }, + { + 'begin': 0x0C00, + 'end': 0x0C7F + }, + { + 'begin': 0x0C80, + 'end': 0x0CFF + }, + { + 'begin': 0x0D00, + 'end': 0x0D7F + }, + { + 'begin': 0x0E00, + 'end': 0x0E7F + }, + { + 'begin': 0x0E80, + 'end': 0x0EFF + }, + { + 'begin': 0x10A0, + 'end': 0x10FF + }, + { + 'begin': 0x1B00, + 'end': 0x1B7F + }, + { + 'begin': 0x1100, + 'end': 0x11FF + }, + { + 'begin': 0x1E00, + 'end': 0x1EFF + }, + { + 'begin': 0x1F00, + 'end': 0x1FFF + }, + { + 'begin': 0x2000, + 'end': 0x206F + }, + { + 'begin': 0x2070, + 'end': 0x209F + }, + { + 'begin': 0x20A0, + 'end': 0x20CF + }, + { + 'begin': 0x20D0, + 'end': 0x20FF + }, + { + 'begin': 0x2100, + 'end': 0x214F + }, + { + 'begin': 0x2150, + 'end': 0x218F + }, + { + 'begin': 0x2190, + 'end': 0x21FF + }, + { + 'begin': 0x2200, + 'end': 0x22FF + }, + { + 'begin': 0x2300, + 'end': 0x23FF + }, + { + 'begin': 0x2400, + 'end': 0x243F + }, + { + 'begin': 0x2440, + 'end': 0x245F + }, + { + 'begin': 0x2460, + 'end': 0x24FF + }, + { + 'begin': 0x2500, + 'end': 0x257F + }, + { + 'begin': 0x2580, + 'end': 0x259F + }, + { + 'begin': 0x25A0, + 'end': 0x25FF + }, + { + 'begin': 0x2600, + 'end': 0x26FF + }, + { + 'begin': 0x2700, + 'end': 0x27BF + }, + { + 'begin': 0x3000, + 'end': 0x303F + }, + { + 'begin': 0x3040, + 'end': 0x309F + }, + { + 'begin': 0x30A0, + 'end': 0x30FF + }, + { + 'begin': 0x3100, + 'end': 0x312F + }, + { + 'begin': 0x3130, + 'end': 0x318F + }, + { + 'begin': 0xA840, + 'end': 0xA87F + }, + { + 'begin': 0x3200, + 'end': 0x32FF + }, + { + 'begin': 0x3300, + 'end': 0x33FF + }, + { + 'begin': 0xAC00, + 'end': 0xD7AF + }, + { + 'begin': 0xD800, + 'end': 0xDFFF + }, + { + 'begin': 0x10900, + 'end': 0x1091F + }, + { + 'begin': 0x4E00, + 'end': 0x9FFF + }, + { + 'begin': 0xE000, + 'end': 0xF8FF + }, + { + 'begin': 0x31C0, + 'end': 0x31EF + }, + { + 'begin': 0xFB00, + 'end': 0xFB4F + }, + { + 'begin': 0xFB50, + 'end': 0xFDFF + }, + { + 'begin': 0xFE20, + 'end': 0xFE2F + }, + { + 'begin': 0xFE10, + 'end': 0xFE1F + }, + { + 'begin': 0xFE50, + 'end': 0xFE6F + }, + { + 'begin': 0xFE70, + 'end': 0xFEFF + }, + { + 'begin': 0xFF00, + 'end': 0xFFEF + }, + { + 'begin': 0xFFF0, + 'end': 0xFFFF + }, + { + 'begin': 0x0F00, + 'end': 0x0FFF + }, + { + 'begin': 0x0700, + 'end': 0x074F + }, + { + 'begin': 0x0780, + 'end': 0x07BF + }, + { + 'begin': 0x0D80, + 'end': 0x0DFF + }, + { + 'begin': 0x1000, + 'end': 0x109F + }, + { + 'begin': 0x1200, + 'end': 0x137F + }, + { + 'begin': 0x13A0, + 'end': 0x13FF + }, + { + 'begin': 0x1400, + 'end': 0x167F + }, + { + 'begin': 0x1680, + 'end': 0x169F + }, + { + 'begin': 0x16A0, + 'end': 0x16FF + }, + { + 'begin': 0x1780, + 'end': 0x17FF + }, + { + 'begin': 0x1800, + 'end': 0x18AF + }, + { + 'begin': 0x2800, + 'end': 0x28FF + }, + { + 'begin': 0xA000, + 'end': 0xA48F + }, + { + 'begin': 0x1700, + 'end': 0x171F + }, + { + 'begin': 0x10300, + 'end': 0x1032F + }, + { + 'begin': 0x10330, + 'end': 0x1034F + }, + { + 'begin': 0x10400, + 'end': 0x1044F + }, + { + 'begin': 0x1D000, + 'end': 0x1D0FF + }, + { + 'begin': 0x1D400, + 'end': 0x1D7FF + }, + { + 'begin': 0xFF000, + 'end': 0xFFFFD + }, + { + 'begin': 0xFE00, + 'end': 0xFE0F + }, + { + 'begin': 0xE0000, + 'end': 0xE007F + }, + { + 'begin': 0x1900, + 'end': 0x194F + }, + { + 'begin': 0x1950, + 'end': 0x197F + }, + { + 'begin': 0x1980, + 'end': 0x19DF + }, + { + 'begin': 0x1A00, + 'end': 0x1A1F + }, + { + 'begin': 0x2C00, + 'end': 0x2C5F + }, + { + 'begin': 0x2D30, + 'end': 0x2D7F + }, + { + 'begin': 0x4DC0, + 'end': 0x4DFF + }, + { + 'begin': 0xA800, + 'end': 0xA82F + }, + { + 'begin': 0x10000, + 'end': 0x1007F + }, + { + 'begin': 0x10140, + 'end': 0x1018F + }, + { + 'begin': 0x10380, + 'end': 0x1039F + }, + { + 'begin': 0x103A0, + 'end': 0x103DF + }, + { + 'begin': 0x10450, + 'end': 0x1047F + }, + { + 'begin': 0x10480, + 'end': 0x104AF + }, + { + 'begin': 0x10800, + 'end': 0x1083F + }, + { + 'begin': 0x10A00, + 'end': 0x10A5F + }, + { + 'begin': 0x1D300, + 'end': 0x1D35F + }, + { + 'begin': 0x12000, + 'end': 0x123FF + }, + { + 'begin': 0x1D360, + 'end': 0x1D37F + }, + { + 'begin': 0x1B80, + 'end': 0x1BBF + }, + { + 'begin': 0x1C00, + 'end': 0x1C4F + }, + { + 'begin': 0x1C50, + 'end': 0x1C7F + }, + { + 'begin': 0xA880, + 'end': 0xA8DF + }, + { + 'begin': 0xA900, + 'end': 0xA92F + }, + { + 'begin': 0xA930, + 'end': 0xA95F + }, + { + 'begin': 0xAA00, + 'end': 0xAA5F + }, + { + 'begin': 0x10190, + 'end': 0x101CF + }, + { + 'begin': 0x101D0, + 'end': 0x101FF + }, + { + 'begin': 0x102A0, + 'end': 0x102DF + }, + { + 'begin': 0x1F030, + 'end': 0x1F09F + } +]; +function getUnicodeRangeFor(value) { + for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) { + var range = UnicodeRanges[i]; + if (value >= range.begin && value < range.end) { + return i; + } + } + return -1; +} +function isRTLRangeFor(value) { + var range = UnicodeRanges[13]; + if (value >= range.begin && value < range.end) { + return true; + } + range = UnicodeRanges[11]; + if (value >= range.begin && value < range.end) { + return true; + } + return false; +} +var getNormalizedUnicodes = getLookupTableFactory(function (t) { + t['\u00A8'] = '\u0020\u0308'; + t['\u00AF'] = '\u0020\u0304'; + t['\u00B4'] = '\u0020\u0301'; + t['\u00B5'] = '\u03BC'; + t['\u00B8'] = '\u0020\u0327'; + t['\u0132'] = '\u0049\u004A'; + t['\u0133'] = '\u0069\u006A'; + t['\u013F'] = '\u004C\u00B7'; + t['\u0140'] = '\u006C\u00B7'; + t['\u0149'] = '\u02BC\u006E'; + t['\u017F'] = '\u0073'; + t['\u01C4'] = '\u0044\u017D'; + t['\u01C5'] = '\u0044\u017E'; + t['\u01C6'] = '\u0064\u017E'; + t['\u01C7'] = '\u004C\u004A'; + t['\u01C8'] = '\u004C\u006A'; + t['\u01C9'] = '\u006C\u006A'; + t['\u01CA'] = '\u004E\u004A'; + t['\u01CB'] = '\u004E\u006A'; + t['\u01CC'] = '\u006E\u006A'; + t['\u01F1'] = '\u0044\u005A'; + t['\u01F2'] = '\u0044\u007A'; + t['\u01F3'] = '\u0064\u007A'; + t['\u02D8'] = '\u0020\u0306'; + t['\u02D9'] = '\u0020\u0307'; + t['\u02DA'] = '\u0020\u030A'; + t['\u02DB'] = '\u0020\u0328'; + t['\u02DC'] = '\u0020\u0303'; + t['\u02DD'] = '\u0020\u030B'; + t['\u037A'] = '\u0020\u0345'; + t['\u0384'] = '\u0020\u0301'; + t['\u03D0'] = '\u03B2'; + t['\u03D1'] = '\u03B8'; + t['\u03D2'] = '\u03A5'; + t['\u03D5'] = '\u03C6'; + t['\u03D6'] = '\u03C0'; + t['\u03F0'] = '\u03BA'; + t['\u03F1'] = '\u03C1'; + t['\u03F2'] = '\u03C2'; + t['\u03F4'] = '\u0398'; + t['\u03F5'] = '\u03B5'; + t['\u03F9'] = '\u03A3'; + t['\u0587'] = '\u0565\u0582'; + t['\u0675'] = '\u0627\u0674'; + t['\u0676'] = '\u0648\u0674'; + t['\u0677'] = '\u06C7\u0674'; + t['\u0678'] = '\u064A\u0674'; + t['\u0E33'] = '\u0E4D\u0E32'; + t['\u0EB3'] = '\u0ECD\u0EB2'; + t['\u0EDC'] = '\u0EAB\u0E99'; + t['\u0EDD'] = '\u0EAB\u0EA1'; + t['\u0F77'] = '\u0FB2\u0F81'; + t['\u0F79'] = '\u0FB3\u0F81'; + t['\u1E9A'] = '\u0061\u02BE'; + t['\u1FBD'] = '\u0020\u0313'; + t['\u1FBF'] = '\u0020\u0313'; + t['\u1FC0'] = '\u0020\u0342'; + t['\u1FFE'] = '\u0020\u0314'; + t['\u2002'] = '\u0020'; + t['\u2003'] = '\u0020'; + t['\u2004'] = '\u0020'; + t['\u2005'] = '\u0020'; + t['\u2006'] = '\u0020'; + t['\u2008'] = '\u0020'; + t['\u2009'] = '\u0020'; + t['\u200A'] = '\u0020'; + t['\u2017'] = '\u0020\u0333'; + t['\u2024'] = '\u002E'; + t['\u2025'] = '\u002E\u002E'; + t['\u2026'] = '\u002E\u002E\u002E'; + t['\u2033'] = '\u2032\u2032'; + t['\u2034'] = '\u2032\u2032\u2032'; + t['\u2036'] = '\u2035\u2035'; + t['\u2037'] = '\u2035\u2035\u2035'; + t['\u203C'] = '\u0021\u0021'; + t['\u203E'] = '\u0020\u0305'; + t['\u2047'] = '\u003F\u003F'; + t['\u2048'] = '\u003F\u0021'; + t['\u2049'] = '\u0021\u003F'; + t['\u2057'] = '\u2032\u2032\u2032\u2032'; + t['\u205F'] = '\u0020'; + t['\u20A8'] = '\u0052\u0073'; + t['\u2100'] = '\u0061\u002F\u0063'; + t['\u2101'] = '\u0061\u002F\u0073'; + t['\u2103'] = '\u00B0\u0043'; + t['\u2105'] = '\u0063\u002F\u006F'; + t['\u2106'] = '\u0063\u002F\u0075'; + t['\u2107'] = '\u0190'; + t['\u2109'] = '\u00B0\u0046'; + t['\u2116'] = '\u004E\u006F'; + t['\u2121'] = '\u0054\u0045\u004C'; + t['\u2135'] = '\u05D0'; + t['\u2136'] = '\u05D1'; + t['\u2137'] = '\u05D2'; + t['\u2138'] = '\u05D3'; + t['\u213B'] = '\u0046\u0041\u0058'; + t['\u2160'] = '\u0049'; + t['\u2161'] = '\u0049\u0049'; + t['\u2162'] = '\u0049\u0049\u0049'; + t['\u2163'] = '\u0049\u0056'; + t['\u2164'] = '\u0056'; + t['\u2165'] = '\u0056\u0049'; + t['\u2166'] = '\u0056\u0049\u0049'; + t['\u2167'] = '\u0056\u0049\u0049\u0049'; + t['\u2168'] = '\u0049\u0058'; + t['\u2169'] = '\u0058'; + t['\u216A'] = '\u0058\u0049'; + t['\u216B'] = '\u0058\u0049\u0049'; + t['\u216C'] = '\u004C'; + t['\u216D'] = '\u0043'; + t['\u216E'] = '\u0044'; + t['\u216F'] = '\u004D'; + t['\u2170'] = '\u0069'; + t['\u2171'] = '\u0069\u0069'; + t['\u2172'] = '\u0069\u0069\u0069'; + t['\u2173'] = '\u0069\u0076'; + t['\u2174'] = '\u0076'; + t['\u2175'] = '\u0076\u0069'; + t['\u2176'] = '\u0076\u0069\u0069'; + t['\u2177'] = '\u0076\u0069\u0069\u0069'; + t['\u2178'] = '\u0069\u0078'; + t['\u2179'] = '\u0078'; + t['\u217A'] = '\u0078\u0069'; + t['\u217B'] = '\u0078\u0069\u0069'; + t['\u217C'] = '\u006C'; + t['\u217D'] = '\u0063'; + t['\u217E'] = '\u0064'; + t['\u217F'] = '\u006D'; + t['\u222C'] = '\u222B\u222B'; + t['\u222D'] = '\u222B\u222B\u222B'; + t['\u222F'] = '\u222E\u222E'; + t['\u2230'] = '\u222E\u222E\u222E'; + t['\u2474'] = '\u0028\u0031\u0029'; + t['\u2475'] = '\u0028\u0032\u0029'; + t['\u2476'] = '\u0028\u0033\u0029'; + t['\u2477'] = '\u0028\u0034\u0029'; + t['\u2478'] = '\u0028\u0035\u0029'; + t['\u2479'] = '\u0028\u0036\u0029'; + t['\u247A'] = '\u0028\u0037\u0029'; + t['\u247B'] = '\u0028\u0038\u0029'; + t['\u247C'] = '\u0028\u0039\u0029'; + t['\u247D'] = '\u0028\u0031\u0030\u0029'; + t['\u247E'] = '\u0028\u0031\u0031\u0029'; + t['\u247F'] = '\u0028\u0031\u0032\u0029'; + t['\u2480'] = '\u0028\u0031\u0033\u0029'; + t['\u2481'] = '\u0028\u0031\u0034\u0029'; + t['\u2482'] = '\u0028\u0031\u0035\u0029'; + t['\u2483'] = '\u0028\u0031\u0036\u0029'; + t['\u2484'] = '\u0028\u0031\u0037\u0029'; + t['\u2485'] = '\u0028\u0031\u0038\u0029'; + t['\u2486'] = '\u0028\u0031\u0039\u0029'; + t['\u2487'] = '\u0028\u0032\u0030\u0029'; + t['\u2488'] = '\u0031\u002E'; + t['\u2489'] = '\u0032\u002E'; + t['\u248A'] = '\u0033\u002E'; + t['\u248B'] = '\u0034\u002E'; + t['\u248C'] = '\u0035\u002E'; + t['\u248D'] = '\u0036\u002E'; + t['\u248E'] = '\u0037\u002E'; + t['\u248F'] = '\u0038\u002E'; + t['\u2490'] = '\u0039\u002E'; + t['\u2491'] = '\u0031\u0030\u002E'; + t['\u2492'] = '\u0031\u0031\u002E'; + t['\u2493'] = '\u0031\u0032\u002E'; + t['\u2494'] = '\u0031\u0033\u002E'; + t['\u2495'] = '\u0031\u0034\u002E'; + t['\u2496'] = '\u0031\u0035\u002E'; + t['\u2497'] = '\u0031\u0036\u002E'; + t['\u2498'] = '\u0031\u0037\u002E'; + t['\u2499'] = '\u0031\u0038\u002E'; + t['\u249A'] = '\u0031\u0039\u002E'; + t['\u249B'] = '\u0032\u0030\u002E'; + t['\u249C'] = '\u0028\u0061\u0029'; + t['\u249D'] = '\u0028\u0062\u0029'; + t['\u249E'] = '\u0028\u0063\u0029'; + t['\u249F'] = '\u0028\u0064\u0029'; + t['\u24A0'] = '\u0028\u0065\u0029'; + t['\u24A1'] = '\u0028\u0066\u0029'; + t['\u24A2'] = '\u0028\u0067\u0029'; + t['\u24A3'] = '\u0028\u0068\u0029'; + t['\u24A4'] = '\u0028\u0069\u0029'; + t['\u24A5'] = '\u0028\u006A\u0029'; + t['\u24A6'] = '\u0028\u006B\u0029'; + t['\u24A7'] = '\u0028\u006C\u0029'; + t['\u24A8'] = '\u0028\u006D\u0029'; + t['\u24A9'] = '\u0028\u006E\u0029'; + t['\u24AA'] = '\u0028\u006F\u0029'; + t['\u24AB'] = '\u0028\u0070\u0029'; + t['\u24AC'] = '\u0028\u0071\u0029'; + t['\u24AD'] = '\u0028\u0072\u0029'; + t['\u24AE'] = '\u0028\u0073\u0029'; + t['\u24AF'] = '\u0028\u0074\u0029'; + t['\u24B0'] = '\u0028\u0075\u0029'; + t['\u24B1'] = '\u0028\u0076\u0029'; + t['\u24B2'] = '\u0028\u0077\u0029'; + t['\u24B3'] = '\u0028\u0078\u0029'; + t['\u24B4'] = '\u0028\u0079\u0029'; + t['\u24B5'] = '\u0028\u007A\u0029'; + t['\u2A0C'] = '\u222B\u222B\u222B\u222B'; + t['\u2A74'] = '\u003A\u003A\u003D'; + t['\u2A75'] = '\u003D\u003D'; + t['\u2A76'] = '\u003D\u003D\u003D'; + t['\u2E9F'] = '\u6BCD'; + t['\u2EF3'] = '\u9F9F'; + t['\u2F00'] = '\u4E00'; + t['\u2F01'] = '\u4E28'; + t['\u2F02'] = '\u4E36'; + t['\u2F03'] = '\u4E3F'; + t['\u2F04'] = '\u4E59'; + t['\u2F05'] = '\u4E85'; + t['\u2F06'] = '\u4E8C'; + t['\u2F07'] = '\u4EA0'; + t['\u2F08'] = '\u4EBA'; + t['\u2F09'] = '\u513F'; + t['\u2F0A'] = '\u5165'; + t['\u2F0B'] = '\u516B'; + t['\u2F0C'] = '\u5182'; + t['\u2F0D'] = '\u5196'; + t['\u2F0E'] = '\u51AB'; + t['\u2F0F'] = '\u51E0'; + t['\u2F10'] = '\u51F5'; + t['\u2F11'] = '\u5200'; + t['\u2F12'] = '\u529B'; + t['\u2F13'] = '\u52F9'; + t['\u2F14'] = '\u5315'; + t['\u2F15'] = '\u531A'; + t['\u2F16'] = '\u5338'; + t['\u2F17'] = '\u5341'; + t['\u2F18'] = '\u535C'; + t['\u2F19'] = '\u5369'; + t['\u2F1A'] = '\u5382'; + t['\u2F1B'] = '\u53B6'; + t['\u2F1C'] = '\u53C8'; + t['\u2F1D'] = '\u53E3'; + t['\u2F1E'] = '\u56D7'; + t['\u2F1F'] = '\u571F'; + t['\u2F20'] = '\u58EB'; + t['\u2F21'] = '\u5902'; + t['\u2F22'] = '\u590A'; + t['\u2F23'] = '\u5915'; + t['\u2F24'] = '\u5927'; + t['\u2F25'] = '\u5973'; + t['\u2F26'] = '\u5B50'; + t['\u2F27'] = '\u5B80'; + t['\u2F28'] = '\u5BF8'; + t['\u2F29'] = '\u5C0F'; + t['\u2F2A'] = '\u5C22'; + t['\u2F2B'] = '\u5C38'; + t['\u2F2C'] = '\u5C6E'; + t['\u2F2D'] = '\u5C71'; + t['\u2F2E'] = '\u5DDB'; + t['\u2F2F'] = '\u5DE5'; + t['\u2F30'] = '\u5DF1'; + t['\u2F31'] = '\u5DFE'; + t['\u2F32'] = '\u5E72'; + t['\u2F33'] = '\u5E7A'; + t['\u2F34'] = '\u5E7F'; + t['\u2F35'] = '\u5EF4'; + t['\u2F36'] = '\u5EFE'; + t['\u2F37'] = '\u5F0B'; + t['\u2F38'] = '\u5F13'; + t['\u2F39'] = '\u5F50'; + t['\u2F3A'] = '\u5F61'; + t['\u2F3B'] = '\u5F73'; + t['\u2F3C'] = '\u5FC3'; + t['\u2F3D'] = '\u6208'; + t['\u2F3E'] = '\u6236'; + t['\u2F3F'] = '\u624B'; + t['\u2F40'] = '\u652F'; + t['\u2F41'] = '\u6534'; + t['\u2F42'] = '\u6587'; + t['\u2F43'] = '\u6597'; + t['\u2F44'] = '\u65A4'; + t['\u2F45'] = '\u65B9'; + t['\u2F46'] = '\u65E0'; + t['\u2F47'] = '\u65E5'; + t['\u2F48'] = '\u66F0'; + t['\u2F49'] = '\u6708'; + t['\u2F4A'] = '\u6728'; + t['\u2F4B'] = '\u6B20'; + t['\u2F4C'] = '\u6B62'; + t['\u2F4D'] = '\u6B79'; + t['\u2F4E'] = '\u6BB3'; + t['\u2F4F'] = '\u6BCB'; + t['\u2F50'] = '\u6BD4'; + t['\u2F51'] = '\u6BDB'; + t['\u2F52'] = '\u6C0F'; + t['\u2F53'] = '\u6C14'; + t['\u2F54'] = '\u6C34'; + t['\u2F55'] = '\u706B'; + t['\u2F56'] = '\u722A'; + t['\u2F57'] = '\u7236'; + t['\u2F58'] = '\u723B'; + t['\u2F59'] = '\u723F'; + t['\u2F5A'] = '\u7247'; + t['\u2F5B'] = '\u7259'; + t['\u2F5C'] = '\u725B'; + t['\u2F5D'] = '\u72AC'; + t['\u2F5E'] = '\u7384'; + t['\u2F5F'] = '\u7389'; + t['\u2F60'] = '\u74DC'; + t['\u2F61'] = '\u74E6'; + t['\u2F62'] = '\u7518'; + t['\u2F63'] = '\u751F'; + t['\u2F64'] = '\u7528'; + t['\u2F65'] = '\u7530'; + t['\u2F66'] = '\u758B'; + t['\u2F67'] = '\u7592'; + t['\u2F68'] = '\u7676'; + t['\u2F69'] = '\u767D'; + t['\u2F6A'] = '\u76AE'; + t['\u2F6B'] = '\u76BF'; + t['\u2F6C'] = '\u76EE'; + t['\u2F6D'] = '\u77DB'; + t['\u2F6E'] = '\u77E2'; + t['\u2F6F'] = '\u77F3'; + t['\u2F70'] = '\u793A'; + t['\u2F71'] = '\u79B8'; + t['\u2F72'] = '\u79BE'; + t['\u2F73'] = '\u7A74'; + t['\u2F74'] = '\u7ACB'; + t['\u2F75'] = '\u7AF9'; + t['\u2F76'] = '\u7C73'; + t['\u2F77'] = '\u7CF8'; + t['\u2F78'] = '\u7F36'; + t['\u2F79'] = '\u7F51'; + t['\u2F7A'] = '\u7F8A'; + t['\u2F7B'] = '\u7FBD'; + t['\u2F7C'] = '\u8001'; + t['\u2F7D'] = '\u800C'; + t['\u2F7E'] = '\u8012'; + t['\u2F7F'] = '\u8033'; + t['\u2F80'] = '\u807F'; + t['\u2F81'] = '\u8089'; + t['\u2F82'] = '\u81E3'; + t['\u2F83'] = '\u81EA'; + t['\u2F84'] = '\u81F3'; + t['\u2F85'] = '\u81FC'; + t['\u2F86'] = '\u820C'; + t['\u2F87'] = '\u821B'; + t['\u2F88'] = '\u821F'; + t['\u2F89'] = '\u826E'; + t['\u2F8A'] = '\u8272'; + t['\u2F8B'] = '\u8278'; + t['\u2F8C'] = '\u864D'; + t['\u2F8D'] = '\u866B'; + t['\u2F8E'] = '\u8840'; + t['\u2F8F'] = '\u884C'; + t['\u2F90'] = '\u8863'; + t['\u2F91'] = '\u897E'; + t['\u2F92'] = '\u898B'; + t['\u2F93'] = '\u89D2'; + t['\u2F94'] = '\u8A00'; + t['\u2F95'] = '\u8C37'; + t['\u2F96'] = '\u8C46'; + t['\u2F97'] = '\u8C55'; + t['\u2F98'] = '\u8C78'; + t['\u2F99'] = '\u8C9D'; + t['\u2F9A'] = '\u8D64'; + t['\u2F9B'] = '\u8D70'; + t['\u2F9C'] = '\u8DB3'; + t['\u2F9D'] = '\u8EAB'; + t['\u2F9E'] = '\u8ECA'; + t['\u2F9F'] = '\u8F9B'; + t['\u2FA0'] = '\u8FB0'; + t['\u2FA1'] = '\u8FB5'; + t['\u2FA2'] = '\u9091'; + t['\u2FA3'] = '\u9149'; + t['\u2FA4'] = '\u91C6'; + t['\u2FA5'] = '\u91CC'; + t['\u2FA6'] = '\u91D1'; + t['\u2FA7'] = '\u9577'; + t['\u2FA8'] = '\u9580'; + t['\u2FA9'] = '\u961C'; + t['\u2FAA'] = '\u96B6'; + t['\u2FAB'] = '\u96B9'; + t['\u2FAC'] = '\u96E8'; + t['\u2FAD'] = '\u9751'; + t['\u2FAE'] = '\u975E'; + t['\u2FAF'] = '\u9762'; + t['\u2FB0'] = '\u9769'; + t['\u2FB1'] = '\u97CB'; + t['\u2FB2'] = '\u97ED'; + t['\u2FB3'] = '\u97F3'; + t['\u2FB4'] = '\u9801'; + t['\u2FB5'] = '\u98A8'; + t['\u2FB6'] = '\u98DB'; + t['\u2FB7'] = '\u98DF'; + t['\u2FB8'] = '\u9996'; + t['\u2FB9'] = '\u9999'; + t['\u2FBA'] = '\u99AC'; + t['\u2FBB'] = '\u9AA8'; + t['\u2FBC'] = '\u9AD8'; + t['\u2FBD'] = '\u9ADF'; + t['\u2FBE'] = '\u9B25'; + t['\u2FBF'] = '\u9B2F'; + t['\u2FC0'] = '\u9B32'; + t['\u2FC1'] = '\u9B3C'; + t['\u2FC2'] = '\u9B5A'; + t['\u2FC3'] = '\u9CE5'; + t['\u2FC4'] = '\u9E75'; + t['\u2FC5'] = '\u9E7F'; + t['\u2FC6'] = '\u9EA5'; + t['\u2FC7'] = '\u9EBB'; + t['\u2FC8'] = '\u9EC3'; + t['\u2FC9'] = '\u9ECD'; + t['\u2FCA'] = '\u9ED1'; + t['\u2FCB'] = '\u9EF9'; + t['\u2FCC'] = '\u9EFD'; + t['\u2FCD'] = '\u9F0E'; + t['\u2FCE'] = '\u9F13'; + t['\u2FCF'] = '\u9F20'; + t['\u2FD0'] = '\u9F3B'; + t['\u2FD1'] = '\u9F4A'; + t['\u2FD2'] = '\u9F52'; + t['\u2FD3'] = '\u9F8D'; + t['\u2FD4'] = '\u9F9C'; + t['\u2FD5'] = '\u9FA0'; + t['\u3036'] = '\u3012'; + t['\u3038'] = '\u5341'; + t['\u3039'] = '\u5344'; + t['\u303A'] = '\u5345'; + t['\u309B'] = '\u0020\u3099'; + t['\u309C'] = '\u0020\u309A'; + t['\u3131'] = '\u1100'; + t['\u3132'] = '\u1101'; + t['\u3133'] = '\u11AA'; + t['\u3134'] = '\u1102'; + t['\u3135'] = '\u11AC'; + t['\u3136'] = '\u11AD'; + t['\u3137'] = '\u1103'; + t['\u3138'] = '\u1104'; + t['\u3139'] = '\u1105'; + t['\u313A'] = '\u11B0'; + t['\u313B'] = '\u11B1'; + t['\u313C'] = '\u11B2'; + t['\u313D'] = '\u11B3'; + t['\u313E'] = '\u11B4'; + t['\u313F'] = '\u11B5'; + t['\u3140'] = '\u111A'; + t['\u3141'] = '\u1106'; + t['\u3142'] = '\u1107'; + t['\u3143'] = '\u1108'; + t['\u3144'] = '\u1121'; + t['\u3145'] = '\u1109'; + t['\u3146'] = '\u110A'; + t['\u3147'] = '\u110B'; + t['\u3148'] = '\u110C'; + t['\u3149'] = '\u110D'; + t['\u314A'] = '\u110E'; + t['\u314B'] = '\u110F'; + t['\u314C'] = '\u1110'; + t['\u314D'] = '\u1111'; + t['\u314E'] = '\u1112'; + t['\u314F'] = '\u1161'; + t['\u3150'] = '\u1162'; + t['\u3151'] = '\u1163'; + t['\u3152'] = '\u1164'; + t['\u3153'] = '\u1165'; + t['\u3154'] = '\u1166'; + t['\u3155'] = '\u1167'; + t['\u3156'] = '\u1168'; + t['\u3157'] = '\u1169'; + t['\u3158'] = '\u116A'; + t['\u3159'] = '\u116B'; + t['\u315A'] = '\u116C'; + t['\u315B'] = '\u116D'; + t['\u315C'] = '\u116E'; + t['\u315D'] = '\u116F'; + t['\u315E'] = '\u1170'; + t['\u315F'] = '\u1171'; + t['\u3160'] = '\u1172'; + t['\u3161'] = '\u1173'; + t['\u3162'] = '\u1174'; + t['\u3163'] = '\u1175'; + t['\u3164'] = '\u1160'; + t['\u3165'] = '\u1114'; + t['\u3166'] = '\u1115'; + t['\u3167'] = '\u11C7'; + t['\u3168'] = '\u11C8'; + t['\u3169'] = '\u11CC'; + t['\u316A'] = '\u11CE'; + t['\u316B'] = '\u11D3'; + t['\u316C'] = '\u11D7'; + t['\u316D'] = '\u11D9'; + t['\u316E'] = '\u111C'; + t['\u316F'] = '\u11DD'; + t['\u3170'] = '\u11DF'; + t['\u3171'] = '\u111D'; + t['\u3172'] = '\u111E'; + t['\u3173'] = '\u1120'; + t['\u3174'] = '\u1122'; + t['\u3175'] = '\u1123'; + t['\u3176'] = '\u1127'; + t['\u3177'] = '\u1129'; + t['\u3178'] = '\u112B'; + t['\u3179'] = '\u112C'; + t['\u317A'] = '\u112D'; + t['\u317B'] = '\u112E'; + t['\u317C'] = '\u112F'; + t['\u317D'] = '\u1132'; + t['\u317E'] = '\u1136'; + t['\u317F'] = '\u1140'; + t['\u3180'] = '\u1147'; + t['\u3181'] = '\u114C'; + t['\u3182'] = '\u11F1'; + t['\u3183'] = '\u11F2'; + t['\u3184'] = '\u1157'; + t['\u3185'] = '\u1158'; + t['\u3186'] = '\u1159'; + t['\u3187'] = '\u1184'; + t['\u3188'] = '\u1185'; + t['\u3189'] = '\u1188'; + t['\u318A'] = '\u1191'; + t['\u318B'] = '\u1192'; + t['\u318C'] = '\u1194'; + t['\u318D'] = '\u119E'; + t['\u318E'] = '\u11A1'; + t['\u3200'] = '\u0028\u1100\u0029'; + t['\u3201'] = '\u0028\u1102\u0029'; + t['\u3202'] = '\u0028\u1103\u0029'; + t['\u3203'] = '\u0028\u1105\u0029'; + t['\u3204'] = '\u0028\u1106\u0029'; + t['\u3205'] = '\u0028\u1107\u0029'; + t['\u3206'] = '\u0028\u1109\u0029'; + t['\u3207'] = '\u0028\u110B\u0029'; + t['\u3208'] = '\u0028\u110C\u0029'; + t['\u3209'] = '\u0028\u110E\u0029'; + t['\u320A'] = '\u0028\u110F\u0029'; + t['\u320B'] = '\u0028\u1110\u0029'; + t['\u320C'] = '\u0028\u1111\u0029'; + t['\u320D'] = '\u0028\u1112\u0029'; + t['\u320E'] = '\u0028\u1100\u1161\u0029'; + t['\u320F'] = '\u0028\u1102\u1161\u0029'; + t['\u3210'] = '\u0028\u1103\u1161\u0029'; + t['\u3211'] = '\u0028\u1105\u1161\u0029'; + t['\u3212'] = '\u0028\u1106\u1161\u0029'; + t['\u3213'] = '\u0028\u1107\u1161\u0029'; + t['\u3214'] = '\u0028\u1109\u1161\u0029'; + t['\u3215'] = '\u0028\u110B\u1161\u0029'; + t['\u3216'] = '\u0028\u110C\u1161\u0029'; + t['\u3217'] = '\u0028\u110E\u1161\u0029'; + t['\u3218'] = '\u0028\u110F\u1161\u0029'; + t['\u3219'] = '\u0028\u1110\u1161\u0029'; + t['\u321A'] = '\u0028\u1111\u1161\u0029'; + t['\u321B'] = '\u0028\u1112\u1161\u0029'; + t['\u321C'] = '\u0028\u110C\u116E\u0029'; + t['\u321D'] = '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029'; + t['\u321E'] = '\u0028\u110B\u1169\u1112\u116E\u0029'; + t['\u3220'] = '\u0028\u4E00\u0029'; + t['\u3221'] = '\u0028\u4E8C\u0029'; + t['\u3222'] = '\u0028\u4E09\u0029'; + t['\u3223'] = '\u0028\u56DB\u0029'; + t['\u3224'] = '\u0028\u4E94\u0029'; + t['\u3225'] = '\u0028\u516D\u0029'; + t['\u3226'] = '\u0028\u4E03\u0029'; + t['\u3227'] = '\u0028\u516B\u0029'; + t['\u3228'] = '\u0028\u4E5D\u0029'; + t['\u3229'] = '\u0028\u5341\u0029'; + t['\u322A'] = '\u0028\u6708\u0029'; + t['\u322B'] = '\u0028\u706B\u0029'; + t['\u322C'] = '\u0028\u6C34\u0029'; + t['\u322D'] = '\u0028\u6728\u0029'; + t['\u322E'] = '\u0028\u91D1\u0029'; + t['\u322F'] = '\u0028\u571F\u0029'; + t['\u3230'] = '\u0028\u65E5\u0029'; + t['\u3231'] = '\u0028\u682A\u0029'; + t['\u3232'] = '\u0028\u6709\u0029'; + t['\u3233'] = '\u0028\u793E\u0029'; + t['\u3234'] = '\u0028\u540D\u0029'; + t['\u3235'] = '\u0028\u7279\u0029'; + t['\u3236'] = '\u0028\u8CA1\u0029'; + t['\u3237'] = '\u0028\u795D\u0029'; + t['\u3238'] = '\u0028\u52B4\u0029'; + t['\u3239'] = '\u0028\u4EE3\u0029'; + t['\u323A'] = '\u0028\u547C\u0029'; + t['\u323B'] = '\u0028\u5B66\u0029'; + t['\u323C'] = '\u0028\u76E3\u0029'; + t['\u323D'] = '\u0028\u4F01\u0029'; + t['\u323E'] = '\u0028\u8CC7\u0029'; + t['\u323F'] = '\u0028\u5354\u0029'; + t['\u3240'] = '\u0028\u796D\u0029'; + t['\u3241'] = '\u0028\u4F11\u0029'; + t['\u3242'] = '\u0028\u81EA\u0029'; + t['\u3243'] = '\u0028\u81F3\u0029'; + t['\u32C0'] = '\u0031\u6708'; + t['\u32C1'] = '\u0032\u6708'; + t['\u32C2'] = '\u0033\u6708'; + t['\u32C3'] = '\u0034\u6708'; + t['\u32C4'] = '\u0035\u6708'; + t['\u32C5'] = '\u0036\u6708'; + t['\u32C6'] = '\u0037\u6708'; + t['\u32C7'] = '\u0038\u6708'; + t['\u32C8'] = '\u0039\u6708'; + t['\u32C9'] = '\u0031\u0030\u6708'; + t['\u32CA'] = '\u0031\u0031\u6708'; + t['\u32CB'] = '\u0031\u0032\u6708'; + t['\u3358'] = '\u0030\u70B9'; + t['\u3359'] = '\u0031\u70B9'; + t['\u335A'] = '\u0032\u70B9'; + t['\u335B'] = '\u0033\u70B9'; + t['\u335C'] = '\u0034\u70B9'; + t['\u335D'] = '\u0035\u70B9'; + t['\u335E'] = '\u0036\u70B9'; + t['\u335F'] = '\u0037\u70B9'; + t['\u3360'] = '\u0038\u70B9'; + t['\u3361'] = '\u0039\u70B9'; + t['\u3362'] = '\u0031\u0030\u70B9'; + t['\u3363'] = '\u0031\u0031\u70B9'; + t['\u3364'] = '\u0031\u0032\u70B9'; + t['\u3365'] = '\u0031\u0033\u70B9'; + t['\u3366'] = '\u0031\u0034\u70B9'; + t['\u3367'] = '\u0031\u0035\u70B9'; + t['\u3368'] = '\u0031\u0036\u70B9'; + t['\u3369'] = '\u0031\u0037\u70B9'; + t['\u336A'] = '\u0031\u0038\u70B9'; + t['\u336B'] = '\u0031\u0039\u70B9'; + t['\u336C'] = '\u0032\u0030\u70B9'; + t['\u336D'] = '\u0032\u0031\u70B9'; + t['\u336E'] = '\u0032\u0032\u70B9'; + t['\u336F'] = '\u0032\u0033\u70B9'; + t['\u3370'] = '\u0032\u0034\u70B9'; + t['\u33E0'] = '\u0031\u65E5'; + t['\u33E1'] = '\u0032\u65E5'; + t['\u33E2'] = '\u0033\u65E5'; + t['\u33E3'] = '\u0034\u65E5'; + t['\u33E4'] = '\u0035\u65E5'; + t['\u33E5'] = '\u0036\u65E5'; + t['\u33E6'] = '\u0037\u65E5'; + t['\u33E7'] = '\u0038\u65E5'; + t['\u33E8'] = '\u0039\u65E5'; + t['\u33E9'] = '\u0031\u0030\u65E5'; + t['\u33EA'] = '\u0031\u0031\u65E5'; + t['\u33EB'] = '\u0031\u0032\u65E5'; + t['\u33EC'] = '\u0031\u0033\u65E5'; + t['\u33ED'] = '\u0031\u0034\u65E5'; + t['\u33EE'] = '\u0031\u0035\u65E5'; + t['\u33EF'] = '\u0031\u0036\u65E5'; + t['\u33F0'] = '\u0031\u0037\u65E5'; + t['\u33F1'] = '\u0031\u0038\u65E5'; + t['\u33F2'] = '\u0031\u0039\u65E5'; + t['\u33F3'] = '\u0032\u0030\u65E5'; + t['\u33F4'] = '\u0032\u0031\u65E5'; + t['\u33F5'] = '\u0032\u0032\u65E5'; + t['\u33F6'] = '\u0032\u0033\u65E5'; + t['\u33F7'] = '\u0032\u0034\u65E5'; + t['\u33F8'] = '\u0032\u0035\u65E5'; + t['\u33F9'] = '\u0032\u0036\u65E5'; + t['\u33FA'] = '\u0032\u0037\u65E5'; + t['\u33FB'] = '\u0032\u0038\u65E5'; + t['\u33FC'] = '\u0032\u0039\u65E5'; + t['\u33FD'] = '\u0033\u0030\u65E5'; + t['\u33FE'] = '\u0033\u0031\u65E5'; + t['\uFB00'] = '\u0066\u0066'; + t['\uFB01'] = '\u0066\u0069'; + t['\uFB02'] = '\u0066\u006C'; + t['\uFB03'] = '\u0066\u0066\u0069'; + t['\uFB04'] = '\u0066\u0066\u006C'; + t['\uFB05'] = '\u017F\u0074'; + t['\uFB06'] = '\u0073\u0074'; + t['\uFB13'] = '\u0574\u0576'; + t['\uFB14'] = '\u0574\u0565'; + t['\uFB15'] = '\u0574\u056B'; + t['\uFB16'] = '\u057E\u0576'; + t['\uFB17'] = '\u0574\u056D'; + t['\uFB4F'] = '\u05D0\u05DC'; + t['\uFB50'] = '\u0671'; + t['\uFB51'] = '\u0671'; + t['\uFB52'] = '\u067B'; + t['\uFB53'] = '\u067B'; + t['\uFB54'] = '\u067B'; + t['\uFB55'] = '\u067B'; + t['\uFB56'] = '\u067E'; + t['\uFB57'] = '\u067E'; + t['\uFB58'] = '\u067E'; + t['\uFB59'] = '\u067E'; + t['\uFB5A'] = '\u0680'; + t['\uFB5B'] = '\u0680'; + t['\uFB5C'] = '\u0680'; + t['\uFB5D'] = '\u0680'; + t['\uFB5E'] = '\u067A'; + t['\uFB5F'] = '\u067A'; + t['\uFB60'] = '\u067A'; + t['\uFB61'] = '\u067A'; + t['\uFB62'] = '\u067F'; + t['\uFB63'] = '\u067F'; + t['\uFB64'] = '\u067F'; + t['\uFB65'] = '\u067F'; + t['\uFB66'] = '\u0679'; + t['\uFB67'] = '\u0679'; + t['\uFB68'] = '\u0679'; + t['\uFB69'] = '\u0679'; + t['\uFB6A'] = '\u06A4'; + t['\uFB6B'] = '\u06A4'; + t['\uFB6C'] = '\u06A4'; + t['\uFB6D'] = '\u06A4'; + t['\uFB6E'] = '\u06A6'; + t['\uFB6F'] = '\u06A6'; + t['\uFB70'] = '\u06A6'; + t['\uFB71'] = '\u06A6'; + t['\uFB72'] = '\u0684'; + t['\uFB73'] = '\u0684'; + t['\uFB74'] = '\u0684'; + t['\uFB75'] = '\u0684'; + t['\uFB76'] = '\u0683'; + t['\uFB77'] = '\u0683'; + t['\uFB78'] = '\u0683'; + t['\uFB79'] = '\u0683'; + t['\uFB7A'] = '\u0686'; + t['\uFB7B'] = '\u0686'; + t['\uFB7C'] = '\u0686'; + t['\uFB7D'] = '\u0686'; + t['\uFB7E'] = '\u0687'; + t['\uFB7F'] = '\u0687'; + t['\uFB80'] = '\u0687'; + t['\uFB81'] = '\u0687'; + t['\uFB82'] = '\u068D'; + t['\uFB83'] = '\u068D'; + t['\uFB84'] = '\u068C'; + t['\uFB85'] = '\u068C'; + t['\uFB86'] = '\u068E'; + t['\uFB87'] = '\u068E'; + t['\uFB88'] = '\u0688'; + t['\uFB89'] = '\u0688'; + t['\uFB8A'] = '\u0698'; + t['\uFB8B'] = '\u0698'; + t['\uFB8C'] = '\u0691'; + t['\uFB8D'] = '\u0691'; + t['\uFB8E'] = '\u06A9'; + t['\uFB8F'] = '\u06A9'; + t['\uFB90'] = '\u06A9'; + t['\uFB91'] = '\u06A9'; + t['\uFB92'] = '\u06AF'; + t['\uFB93'] = '\u06AF'; + t['\uFB94'] = '\u06AF'; + t['\uFB95'] = '\u06AF'; + t['\uFB96'] = '\u06B3'; + t['\uFB97'] = '\u06B3'; + t['\uFB98'] = '\u06B3'; + t['\uFB99'] = '\u06B3'; + t['\uFB9A'] = '\u06B1'; + t['\uFB9B'] = '\u06B1'; + t['\uFB9C'] = '\u06B1'; + t['\uFB9D'] = '\u06B1'; + t['\uFB9E'] = '\u06BA'; + t['\uFB9F'] = '\u06BA'; + t['\uFBA0'] = '\u06BB'; + t['\uFBA1'] = '\u06BB'; + t['\uFBA2'] = '\u06BB'; + t['\uFBA3'] = '\u06BB'; + t['\uFBA4'] = '\u06C0'; + t['\uFBA5'] = '\u06C0'; + t['\uFBA6'] = '\u06C1'; + t['\uFBA7'] = '\u06C1'; + t['\uFBA8'] = '\u06C1'; + t['\uFBA9'] = '\u06C1'; + t['\uFBAA'] = '\u06BE'; + t['\uFBAB'] = '\u06BE'; + t['\uFBAC'] = '\u06BE'; + t['\uFBAD'] = '\u06BE'; + t['\uFBAE'] = '\u06D2'; + t['\uFBAF'] = '\u06D2'; + t['\uFBB0'] = '\u06D3'; + t['\uFBB1'] = '\u06D3'; + t['\uFBD3'] = '\u06AD'; + t['\uFBD4'] = '\u06AD'; + t['\uFBD5'] = '\u06AD'; + t['\uFBD6'] = '\u06AD'; + t['\uFBD7'] = '\u06C7'; + t['\uFBD8'] = '\u06C7'; + t['\uFBD9'] = '\u06C6'; + t['\uFBDA'] = '\u06C6'; + t['\uFBDB'] = '\u06C8'; + t['\uFBDC'] = '\u06C8'; + t['\uFBDD'] = '\u0677'; + t['\uFBDE'] = '\u06CB'; + t['\uFBDF'] = '\u06CB'; + t['\uFBE0'] = '\u06C5'; + t['\uFBE1'] = '\u06C5'; + t['\uFBE2'] = '\u06C9'; + t['\uFBE3'] = '\u06C9'; + t['\uFBE4'] = '\u06D0'; + t['\uFBE5'] = '\u06D0'; + t['\uFBE6'] = '\u06D0'; + t['\uFBE7'] = '\u06D0'; + t['\uFBE8'] = '\u0649'; + t['\uFBE9'] = '\u0649'; + t['\uFBEA'] = '\u0626\u0627'; + t['\uFBEB'] = '\u0626\u0627'; + t['\uFBEC'] = '\u0626\u06D5'; + t['\uFBED'] = '\u0626\u06D5'; + t['\uFBEE'] = '\u0626\u0648'; + t['\uFBEF'] = '\u0626\u0648'; + t['\uFBF0'] = '\u0626\u06C7'; + t['\uFBF1'] = '\u0626\u06C7'; + t['\uFBF2'] = '\u0626\u06C6'; + t['\uFBF3'] = '\u0626\u06C6'; + t['\uFBF4'] = '\u0626\u06C8'; + t['\uFBF5'] = '\u0626\u06C8'; + t['\uFBF6'] = '\u0626\u06D0'; + t['\uFBF7'] = '\u0626\u06D0'; + t['\uFBF8'] = '\u0626\u06D0'; + t['\uFBF9'] = '\u0626\u0649'; + t['\uFBFA'] = '\u0626\u0649'; + t['\uFBFB'] = '\u0626\u0649'; + t['\uFBFC'] = '\u06CC'; + t['\uFBFD'] = '\u06CC'; + t['\uFBFE'] = '\u06CC'; + t['\uFBFF'] = '\u06CC'; + t['\uFC00'] = '\u0626\u062C'; + t['\uFC01'] = '\u0626\u062D'; + t['\uFC02'] = '\u0626\u0645'; + t['\uFC03'] = '\u0626\u0649'; + t['\uFC04'] = '\u0626\u064A'; + t['\uFC05'] = '\u0628\u062C'; + t['\uFC06'] = '\u0628\u062D'; + t['\uFC07'] = '\u0628\u062E'; + t['\uFC08'] = '\u0628\u0645'; + t['\uFC09'] = '\u0628\u0649'; + t['\uFC0A'] = '\u0628\u064A'; + t['\uFC0B'] = '\u062A\u062C'; + t['\uFC0C'] = '\u062A\u062D'; + t['\uFC0D'] = '\u062A\u062E'; + t['\uFC0E'] = '\u062A\u0645'; + t['\uFC0F'] = '\u062A\u0649'; + t['\uFC10'] = '\u062A\u064A'; + t['\uFC11'] = '\u062B\u062C'; + t['\uFC12'] = '\u062B\u0645'; + t['\uFC13'] = '\u062B\u0649'; + t['\uFC14'] = '\u062B\u064A'; + t['\uFC15'] = '\u062C\u062D'; + t['\uFC16'] = '\u062C\u0645'; + t['\uFC17'] = '\u062D\u062C'; + t['\uFC18'] = '\u062D\u0645'; + t['\uFC19'] = '\u062E\u062C'; + t['\uFC1A'] = '\u062E\u062D'; + t['\uFC1B'] = '\u062E\u0645'; + t['\uFC1C'] = '\u0633\u062C'; + t['\uFC1D'] = '\u0633\u062D'; + t['\uFC1E'] = '\u0633\u062E'; + t['\uFC1F'] = '\u0633\u0645'; + t['\uFC20'] = '\u0635\u062D'; + t['\uFC21'] = '\u0635\u0645'; + t['\uFC22'] = '\u0636\u062C'; + t['\uFC23'] = '\u0636\u062D'; + t['\uFC24'] = '\u0636\u062E'; + t['\uFC25'] = '\u0636\u0645'; + t['\uFC26'] = '\u0637\u062D'; + t['\uFC27'] = '\u0637\u0645'; + t['\uFC28'] = '\u0638\u0645'; + t['\uFC29'] = '\u0639\u062C'; + t['\uFC2A'] = '\u0639\u0645'; + t['\uFC2B'] = '\u063A\u062C'; + t['\uFC2C'] = '\u063A\u0645'; + t['\uFC2D'] = '\u0641\u062C'; + t['\uFC2E'] = '\u0641\u062D'; + t['\uFC2F'] = '\u0641\u062E'; + t['\uFC30'] = '\u0641\u0645'; + t['\uFC31'] = '\u0641\u0649'; + t['\uFC32'] = '\u0641\u064A'; + t['\uFC33'] = '\u0642\u062D'; + t['\uFC34'] = '\u0642\u0645'; + t['\uFC35'] = '\u0642\u0649'; + t['\uFC36'] = '\u0642\u064A'; + t['\uFC37'] = '\u0643\u0627'; + t['\uFC38'] = '\u0643\u062C'; + t['\uFC39'] = '\u0643\u062D'; + t['\uFC3A'] = '\u0643\u062E'; + t['\uFC3B'] = '\u0643\u0644'; + t['\uFC3C'] = '\u0643\u0645'; + t['\uFC3D'] = '\u0643\u0649'; + t['\uFC3E'] = '\u0643\u064A'; + t['\uFC3F'] = '\u0644\u062C'; + t['\uFC40'] = '\u0644\u062D'; + t['\uFC41'] = '\u0644\u062E'; + t['\uFC42'] = '\u0644\u0645'; + t['\uFC43'] = '\u0644\u0649'; + t['\uFC44'] = '\u0644\u064A'; + t['\uFC45'] = '\u0645\u062C'; + t['\uFC46'] = '\u0645\u062D'; + t['\uFC47'] = '\u0645\u062E'; + t['\uFC48'] = '\u0645\u0645'; + t['\uFC49'] = '\u0645\u0649'; + t['\uFC4A'] = '\u0645\u064A'; + t['\uFC4B'] = '\u0646\u062C'; + t['\uFC4C'] = '\u0646\u062D'; + t['\uFC4D'] = '\u0646\u062E'; + t['\uFC4E'] = '\u0646\u0645'; + t['\uFC4F'] = '\u0646\u0649'; + t['\uFC50'] = '\u0646\u064A'; + t['\uFC51'] = '\u0647\u062C'; + t['\uFC52'] = '\u0647\u0645'; + t['\uFC53'] = '\u0647\u0649'; + t['\uFC54'] = '\u0647\u064A'; + t['\uFC55'] = '\u064A\u062C'; + t['\uFC56'] = '\u064A\u062D'; + t['\uFC57'] = '\u064A\u062E'; + t['\uFC58'] = '\u064A\u0645'; + t['\uFC59'] = '\u064A\u0649'; + t['\uFC5A'] = '\u064A\u064A'; + t['\uFC5B'] = '\u0630\u0670'; + t['\uFC5C'] = '\u0631\u0670'; + t['\uFC5D'] = '\u0649\u0670'; + t['\uFC5E'] = '\u0020\u064C\u0651'; + t['\uFC5F'] = '\u0020\u064D\u0651'; + t['\uFC60'] = '\u0020\u064E\u0651'; + t['\uFC61'] = '\u0020\u064F\u0651'; + t['\uFC62'] = '\u0020\u0650\u0651'; + t['\uFC63'] = '\u0020\u0651\u0670'; + t['\uFC64'] = '\u0626\u0631'; + t['\uFC65'] = '\u0626\u0632'; + t['\uFC66'] = '\u0626\u0645'; + t['\uFC67'] = '\u0626\u0646'; + t['\uFC68'] = '\u0626\u0649'; + t['\uFC69'] = '\u0626\u064A'; + t['\uFC6A'] = '\u0628\u0631'; + t['\uFC6B'] = '\u0628\u0632'; + t['\uFC6C'] = '\u0628\u0645'; + t['\uFC6D'] = '\u0628\u0646'; + t['\uFC6E'] = '\u0628\u0649'; + t['\uFC6F'] = '\u0628\u064A'; + t['\uFC70'] = '\u062A\u0631'; + t['\uFC71'] = '\u062A\u0632'; + t['\uFC72'] = '\u062A\u0645'; + t['\uFC73'] = '\u062A\u0646'; + t['\uFC74'] = '\u062A\u0649'; + t['\uFC75'] = '\u062A\u064A'; + t['\uFC76'] = '\u062B\u0631'; + t['\uFC77'] = '\u062B\u0632'; + t['\uFC78'] = '\u062B\u0645'; + t['\uFC79'] = '\u062B\u0646'; + t['\uFC7A'] = '\u062B\u0649'; + t['\uFC7B'] = '\u062B\u064A'; + t['\uFC7C'] = '\u0641\u0649'; + t['\uFC7D'] = '\u0641\u064A'; + t['\uFC7E'] = '\u0642\u0649'; + t['\uFC7F'] = '\u0642\u064A'; + t['\uFC80'] = '\u0643\u0627'; + t['\uFC81'] = '\u0643\u0644'; + t['\uFC82'] = '\u0643\u0645'; + t['\uFC83'] = '\u0643\u0649'; + t['\uFC84'] = '\u0643\u064A'; + t['\uFC85'] = '\u0644\u0645'; + t['\uFC86'] = '\u0644\u0649'; + t['\uFC87'] = '\u0644\u064A'; + t['\uFC88'] = '\u0645\u0627'; + t['\uFC89'] = '\u0645\u0645'; + t['\uFC8A'] = '\u0646\u0631'; + t['\uFC8B'] = '\u0646\u0632'; + t['\uFC8C'] = '\u0646\u0645'; + t['\uFC8D'] = '\u0646\u0646'; + t['\uFC8E'] = '\u0646\u0649'; + t['\uFC8F'] = '\u0646\u064A'; + t['\uFC90'] = '\u0649\u0670'; + t['\uFC91'] = '\u064A\u0631'; + t['\uFC92'] = '\u064A\u0632'; + t['\uFC93'] = '\u064A\u0645'; + t['\uFC94'] = '\u064A\u0646'; + t['\uFC95'] = '\u064A\u0649'; + t['\uFC96'] = '\u064A\u064A'; + t['\uFC97'] = '\u0626\u062C'; + t['\uFC98'] = '\u0626\u062D'; + t['\uFC99'] = '\u0626\u062E'; + t['\uFC9A'] = '\u0626\u0645'; + t['\uFC9B'] = '\u0626\u0647'; + t['\uFC9C'] = '\u0628\u062C'; + t['\uFC9D'] = '\u0628\u062D'; + t['\uFC9E'] = '\u0628\u062E'; + t['\uFC9F'] = '\u0628\u0645'; + t['\uFCA0'] = '\u0628\u0647'; + t['\uFCA1'] = '\u062A\u062C'; + t['\uFCA2'] = '\u062A\u062D'; + t['\uFCA3'] = '\u062A\u062E'; + t['\uFCA4'] = '\u062A\u0645'; + t['\uFCA5'] = '\u062A\u0647'; + t['\uFCA6'] = '\u062B\u0645'; + t['\uFCA7'] = '\u062C\u062D'; + t['\uFCA8'] = '\u062C\u0645'; + t['\uFCA9'] = '\u062D\u062C'; + t['\uFCAA'] = '\u062D\u0645'; + t['\uFCAB'] = '\u062E\u062C'; + t['\uFCAC'] = '\u062E\u0645'; + t['\uFCAD'] = '\u0633\u062C'; + t['\uFCAE'] = '\u0633\u062D'; + t['\uFCAF'] = '\u0633\u062E'; + t['\uFCB0'] = '\u0633\u0645'; + t['\uFCB1'] = '\u0635\u062D'; + t['\uFCB2'] = '\u0635\u062E'; + t['\uFCB3'] = '\u0635\u0645'; + t['\uFCB4'] = '\u0636\u062C'; + t['\uFCB5'] = '\u0636\u062D'; + t['\uFCB6'] = '\u0636\u062E'; + t['\uFCB7'] = '\u0636\u0645'; + t['\uFCB8'] = '\u0637\u062D'; + t['\uFCB9'] = '\u0638\u0645'; + t['\uFCBA'] = '\u0639\u062C'; + t['\uFCBB'] = '\u0639\u0645'; + t['\uFCBC'] = '\u063A\u062C'; + t['\uFCBD'] = '\u063A\u0645'; + t['\uFCBE'] = '\u0641\u062C'; + t['\uFCBF'] = '\u0641\u062D'; + t['\uFCC0'] = '\u0641\u062E'; + t['\uFCC1'] = '\u0641\u0645'; + t['\uFCC2'] = '\u0642\u062D'; + t['\uFCC3'] = '\u0642\u0645'; + t['\uFCC4'] = '\u0643\u062C'; + t['\uFCC5'] = '\u0643\u062D'; + t['\uFCC6'] = '\u0643\u062E'; + t['\uFCC7'] = '\u0643\u0644'; + t['\uFCC8'] = '\u0643\u0645'; + t['\uFCC9'] = '\u0644\u062C'; + t['\uFCCA'] = '\u0644\u062D'; + t['\uFCCB'] = '\u0644\u062E'; + t['\uFCCC'] = '\u0644\u0645'; + t['\uFCCD'] = '\u0644\u0647'; + t['\uFCCE'] = '\u0645\u062C'; + t['\uFCCF'] = '\u0645\u062D'; + t['\uFCD0'] = '\u0645\u062E'; + t['\uFCD1'] = '\u0645\u0645'; + t['\uFCD2'] = '\u0646\u062C'; + t['\uFCD3'] = '\u0646\u062D'; + t['\uFCD4'] = '\u0646\u062E'; + t['\uFCD5'] = '\u0646\u0645'; + t['\uFCD6'] = '\u0646\u0647'; + t['\uFCD7'] = '\u0647\u062C'; + t['\uFCD8'] = '\u0647\u0645'; + t['\uFCD9'] = '\u0647\u0670'; + t['\uFCDA'] = '\u064A\u062C'; + t['\uFCDB'] = '\u064A\u062D'; + t['\uFCDC'] = '\u064A\u062E'; + t['\uFCDD'] = '\u064A\u0645'; + t['\uFCDE'] = '\u064A\u0647'; + t['\uFCDF'] = '\u0626\u0645'; + t['\uFCE0'] = '\u0626\u0647'; + t['\uFCE1'] = '\u0628\u0645'; + t['\uFCE2'] = '\u0628\u0647'; + t['\uFCE3'] = '\u062A\u0645'; + t['\uFCE4'] = '\u062A\u0647'; + t['\uFCE5'] = '\u062B\u0645'; + t['\uFCE6'] = '\u062B\u0647'; + t['\uFCE7'] = '\u0633\u0645'; + t['\uFCE8'] = '\u0633\u0647'; + t['\uFCE9'] = '\u0634\u0645'; + t['\uFCEA'] = '\u0634\u0647'; + t['\uFCEB'] = '\u0643\u0644'; + t['\uFCEC'] = '\u0643\u0645'; + t['\uFCED'] = '\u0644\u0645'; + t['\uFCEE'] = '\u0646\u0645'; + t['\uFCEF'] = '\u0646\u0647'; + t['\uFCF0'] = '\u064A\u0645'; + t['\uFCF1'] = '\u064A\u0647'; + t['\uFCF2'] = '\u0640\u064E\u0651'; + t['\uFCF3'] = '\u0640\u064F\u0651'; + t['\uFCF4'] = '\u0640\u0650\u0651'; + t['\uFCF5'] = '\u0637\u0649'; + t['\uFCF6'] = '\u0637\u064A'; + t['\uFCF7'] = '\u0639\u0649'; + t['\uFCF8'] = '\u0639\u064A'; + t['\uFCF9'] = '\u063A\u0649'; + t['\uFCFA'] = '\u063A\u064A'; + t['\uFCFB'] = '\u0633\u0649'; + t['\uFCFC'] = '\u0633\u064A'; + t['\uFCFD'] = '\u0634\u0649'; + t['\uFCFE'] = '\u0634\u064A'; + t['\uFCFF'] = '\u062D\u0649'; + t['\uFD00'] = '\u062D\u064A'; + t['\uFD01'] = '\u062C\u0649'; + t['\uFD02'] = '\u062C\u064A'; + t['\uFD03'] = '\u062E\u0649'; + t['\uFD04'] = '\u062E\u064A'; + t['\uFD05'] = '\u0635\u0649'; + t['\uFD06'] = '\u0635\u064A'; + t['\uFD07'] = '\u0636\u0649'; + t['\uFD08'] = '\u0636\u064A'; + t['\uFD09'] = '\u0634\u062C'; + t['\uFD0A'] = '\u0634\u062D'; + t['\uFD0B'] = '\u0634\u062E'; + t['\uFD0C'] = '\u0634\u0645'; + t['\uFD0D'] = '\u0634\u0631'; + t['\uFD0E'] = '\u0633\u0631'; + t['\uFD0F'] = '\u0635\u0631'; + t['\uFD10'] = '\u0636\u0631'; + t['\uFD11'] = '\u0637\u0649'; + t['\uFD12'] = '\u0637\u064A'; + t['\uFD13'] = '\u0639\u0649'; + t['\uFD14'] = '\u0639\u064A'; + t['\uFD15'] = '\u063A\u0649'; + t['\uFD16'] = '\u063A\u064A'; + t['\uFD17'] = '\u0633\u0649'; + t['\uFD18'] = '\u0633\u064A'; + t['\uFD19'] = '\u0634\u0649'; + t['\uFD1A'] = '\u0634\u064A'; + t['\uFD1B'] = '\u062D\u0649'; + t['\uFD1C'] = '\u062D\u064A'; + t['\uFD1D'] = '\u062C\u0649'; + t['\uFD1E'] = '\u062C\u064A'; + t['\uFD1F'] = '\u062E\u0649'; + t['\uFD20'] = '\u062E\u064A'; + t['\uFD21'] = '\u0635\u0649'; + t['\uFD22'] = '\u0635\u064A'; + t['\uFD23'] = '\u0636\u0649'; + t['\uFD24'] = '\u0636\u064A'; + t['\uFD25'] = '\u0634\u062C'; + t['\uFD26'] = '\u0634\u062D'; + t['\uFD27'] = '\u0634\u062E'; + t['\uFD28'] = '\u0634\u0645'; + t['\uFD29'] = '\u0634\u0631'; + t['\uFD2A'] = '\u0633\u0631'; + t['\uFD2B'] = '\u0635\u0631'; + t['\uFD2C'] = '\u0636\u0631'; + t['\uFD2D'] = '\u0634\u062C'; + t['\uFD2E'] = '\u0634\u062D'; + t['\uFD2F'] = '\u0634\u062E'; + t['\uFD30'] = '\u0634\u0645'; + t['\uFD31'] = '\u0633\u0647'; + t['\uFD32'] = '\u0634\u0647'; + t['\uFD33'] = '\u0637\u0645'; + t['\uFD34'] = '\u0633\u062C'; + t['\uFD35'] = '\u0633\u062D'; + t['\uFD36'] = '\u0633\u062E'; + t['\uFD37'] = '\u0634\u062C'; + t['\uFD38'] = '\u0634\u062D'; + t['\uFD39'] = '\u0634\u062E'; + t['\uFD3A'] = '\u0637\u0645'; + t['\uFD3B'] = '\u0638\u0645'; + t['\uFD3C'] = '\u0627\u064B'; + t['\uFD3D'] = '\u0627\u064B'; + t['\uFD50'] = '\u062A\u062C\u0645'; + t['\uFD51'] = '\u062A\u062D\u062C'; + t['\uFD52'] = '\u062A\u062D\u062C'; + t['\uFD53'] = '\u062A\u062D\u0645'; + t['\uFD54'] = '\u062A\u062E\u0645'; + t['\uFD55'] = '\u062A\u0645\u062C'; + t['\uFD56'] = '\u062A\u0645\u062D'; + t['\uFD57'] = '\u062A\u0645\u062E'; + t['\uFD58'] = '\u062C\u0645\u062D'; + t['\uFD59'] = '\u062C\u0645\u062D'; + t['\uFD5A'] = '\u062D\u0645\u064A'; + t['\uFD5B'] = '\u062D\u0645\u0649'; + t['\uFD5C'] = '\u0633\u062D\u062C'; + t['\uFD5D'] = '\u0633\u062C\u062D'; + t['\uFD5E'] = '\u0633\u062C\u0649'; + t['\uFD5F'] = '\u0633\u0645\u062D'; + t['\uFD60'] = '\u0633\u0645\u062D'; + t['\uFD61'] = '\u0633\u0645\u062C'; + t['\uFD62'] = '\u0633\u0645\u0645'; + t['\uFD63'] = '\u0633\u0645\u0645'; + t['\uFD64'] = '\u0635\u062D\u062D'; + t['\uFD65'] = '\u0635\u062D\u062D'; + t['\uFD66'] = '\u0635\u0645\u0645'; + t['\uFD67'] = '\u0634\u062D\u0645'; + t['\uFD68'] = '\u0634\u062D\u0645'; + t['\uFD69'] = '\u0634\u062C\u064A'; + t['\uFD6A'] = '\u0634\u0645\u062E'; + t['\uFD6B'] = '\u0634\u0645\u062E'; + t['\uFD6C'] = '\u0634\u0645\u0645'; + t['\uFD6D'] = '\u0634\u0645\u0645'; + t['\uFD6E'] = '\u0636\u062D\u0649'; + t['\uFD6F'] = '\u0636\u062E\u0645'; + t['\uFD70'] = '\u0636\u062E\u0645'; + t['\uFD71'] = '\u0637\u0645\u062D'; + t['\uFD72'] = '\u0637\u0645\u062D'; + t['\uFD73'] = '\u0637\u0645\u0645'; + t['\uFD74'] = '\u0637\u0645\u064A'; + t['\uFD75'] = '\u0639\u062C\u0645'; + t['\uFD76'] = '\u0639\u0645\u0645'; + t['\uFD77'] = '\u0639\u0645\u0645'; + t['\uFD78'] = '\u0639\u0645\u0649'; + t['\uFD79'] = '\u063A\u0645\u0645'; + t['\uFD7A'] = '\u063A\u0645\u064A'; + t['\uFD7B'] = '\u063A\u0645\u0649'; + t['\uFD7C'] = '\u0641\u062E\u0645'; + t['\uFD7D'] = '\u0641\u062E\u0645'; + t['\uFD7E'] = '\u0642\u0645\u062D'; + t['\uFD7F'] = '\u0642\u0645\u0645'; + t['\uFD80'] = '\u0644\u062D\u0645'; + t['\uFD81'] = '\u0644\u062D\u064A'; + t['\uFD82'] = '\u0644\u062D\u0649'; + t['\uFD83'] = '\u0644\u062C\u062C'; + t['\uFD84'] = '\u0644\u062C\u062C'; + t['\uFD85'] = '\u0644\u062E\u0645'; + t['\uFD86'] = '\u0644\u062E\u0645'; + t['\uFD87'] = '\u0644\u0645\u062D'; + t['\uFD88'] = '\u0644\u0645\u062D'; + t['\uFD89'] = '\u0645\u062D\u062C'; + t['\uFD8A'] = '\u0645\u062D\u0645'; + t['\uFD8B'] = '\u0645\u062D\u064A'; + t['\uFD8C'] = '\u0645\u062C\u062D'; + t['\uFD8D'] = '\u0645\u062C\u0645'; + t['\uFD8E'] = '\u0645\u062E\u062C'; + t['\uFD8F'] = '\u0645\u062E\u0645'; + t['\uFD92'] = '\u0645\u062C\u062E'; + t['\uFD93'] = '\u0647\u0645\u062C'; + t['\uFD94'] = '\u0647\u0645\u0645'; + t['\uFD95'] = '\u0646\u062D\u0645'; + t['\uFD96'] = '\u0646\u062D\u0649'; + t['\uFD97'] = '\u0646\u062C\u0645'; + t['\uFD98'] = '\u0646\u062C\u0645'; + t['\uFD99'] = '\u0646\u062C\u0649'; + t['\uFD9A'] = '\u0646\u0645\u064A'; + t['\uFD9B'] = '\u0646\u0645\u0649'; + t['\uFD9C'] = '\u064A\u0645\u0645'; + t['\uFD9D'] = '\u064A\u0645\u0645'; + t['\uFD9E'] = '\u0628\u062E\u064A'; + t['\uFD9F'] = '\u062A\u062C\u064A'; + t['\uFDA0'] = '\u062A\u062C\u0649'; + t['\uFDA1'] = '\u062A\u062E\u064A'; + t['\uFDA2'] = '\u062A\u062E\u0649'; + t['\uFDA3'] = '\u062A\u0645\u064A'; + t['\uFDA4'] = '\u062A\u0645\u0649'; + t['\uFDA5'] = '\u062C\u0645\u064A'; + t['\uFDA6'] = '\u062C\u062D\u0649'; + t['\uFDA7'] = '\u062C\u0645\u0649'; + t['\uFDA8'] = '\u0633\u062E\u0649'; + t['\uFDA9'] = '\u0635\u062D\u064A'; + t['\uFDAA'] = '\u0634\u062D\u064A'; + t['\uFDAB'] = '\u0636\u062D\u064A'; + t['\uFDAC'] = '\u0644\u062C\u064A'; + t['\uFDAD'] = '\u0644\u0645\u064A'; + t['\uFDAE'] = '\u064A\u062D\u064A'; + t['\uFDAF'] = '\u064A\u062C\u064A'; + t['\uFDB0'] = '\u064A\u0645\u064A'; + t['\uFDB1'] = '\u0645\u0645\u064A'; + t['\uFDB2'] = '\u0642\u0645\u064A'; + t['\uFDB3'] = '\u0646\u062D\u064A'; + t['\uFDB4'] = '\u0642\u0645\u062D'; + t['\uFDB5'] = '\u0644\u062D\u0645'; + t['\uFDB6'] = '\u0639\u0645\u064A'; + t['\uFDB7'] = '\u0643\u0645\u064A'; + t['\uFDB8'] = '\u0646\u062C\u062D'; + t['\uFDB9'] = '\u0645\u062E\u064A'; + t['\uFDBA'] = '\u0644\u062C\u0645'; + t['\uFDBB'] = '\u0643\u0645\u0645'; + t['\uFDBC'] = '\u0644\u062C\u0645'; + t['\uFDBD'] = '\u0646\u062C\u062D'; + t['\uFDBE'] = '\u062C\u062D\u064A'; + t['\uFDBF'] = '\u062D\u062C\u064A'; + t['\uFDC0'] = '\u0645\u062C\u064A'; + t['\uFDC1'] = '\u0641\u0645\u064A'; + t['\uFDC2'] = '\u0628\u062D\u064A'; + t['\uFDC3'] = '\u0643\u0645\u0645'; + t['\uFDC4'] = '\u0639\u062C\u0645'; + t['\uFDC5'] = '\u0635\u0645\u0645'; + t['\uFDC6'] = '\u0633\u062E\u064A'; + t['\uFDC7'] = '\u0646\u062C\u064A'; + t['\uFE49'] = '\u203E'; + t['\uFE4A'] = '\u203E'; + t['\uFE4B'] = '\u203E'; + t['\uFE4C'] = '\u203E'; + t['\uFE4D'] = '\u005F'; + t['\uFE4E'] = '\u005F'; + t['\uFE4F'] = '\u005F'; + t['\uFE80'] = '\u0621'; + t['\uFE81'] = '\u0622'; + t['\uFE82'] = '\u0622'; + t['\uFE83'] = '\u0623'; + t['\uFE84'] = '\u0623'; + t['\uFE85'] = '\u0624'; + t['\uFE86'] = '\u0624'; + t['\uFE87'] = '\u0625'; + t['\uFE88'] = '\u0625'; + t['\uFE89'] = '\u0626'; + t['\uFE8A'] = '\u0626'; + t['\uFE8B'] = '\u0626'; + t['\uFE8C'] = '\u0626'; + t['\uFE8D'] = '\u0627'; + t['\uFE8E'] = '\u0627'; + t['\uFE8F'] = '\u0628'; + t['\uFE90'] = '\u0628'; + t['\uFE91'] = '\u0628'; + t['\uFE92'] = '\u0628'; + t['\uFE93'] = '\u0629'; + t['\uFE94'] = '\u0629'; + t['\uFE95'] = '\u062A'; + t['\uFE96'] = '\u062A'; + t['\uFE97'] = '\u062A'; + t['\uFE98'] = '\u062A'; + t['\uFE99'] = '\u062B'; + t['\uFE9A'] = '\u062B'; + t['\uFE9B'] = '\u062B'; + t['\uFE9C'] = '\u062B'; + t['\uFE9D'] = '\u062C'; + t['\uFE9E'] = '\u062C'; + t['\uFE9F'] = '\u062C'; + t['\uFEA0'] = '\u062C'; + t['\uFEA1'] = '\u062D'; + t['\uFEA2'] = '\u062D'; + t['\uFEA3'] = '\u062D'; + t['\uFEA4'] = '\u062D'; + t['\uFEA5'] = '\u062E'; + t['\uFEA6'] = '\u062E'; + t['\uFEA7'] = '\u062E'; + t['\uFEA8'] = '\u062E'; + t['\uFEA9'] = '\u062F'; + t['\uFEAA'] = '\u062F'; + t['\uFEAB'] = '\u0630'; + t['\uFEAC'] = '\u0630'; + t['\uFEAD'] = '\u0631'; + t['\uFEAE'] = '\u0631'; + t['\uFEAF'] = '\u0632'; + t['\uFEB0'] = '\u0632'; + t['\uFEB1'] = '\u0633'; + t['\uFEB2'] = '\u0633'; + t['\uFEB3'] = '\u0633'; + t['\uFEB4'] = '\u0633'; + t['\uFEB5'] = '\u0634'; + t['\uFEB6'] = '\u0634'; + t['\uFEB7'] = '\u0634'; + t['\uFEB8'] = '\u0634'; + t['\uFEB9'] = '\u0635'; + t['\uFEBA'] = '\u0635'; + t['\uFEBB'] = '\u0635'; + t['\uFEBC'] = '\u0635'; + t['\uFEBD'] = '\u0636'; + t['\uFEBE'] = '\u0636'; + t['\uFEBF'] = '\u0636'; + t['\uFEC0'] = '\u0636'; + t['\uFEC1'] = '\u0637'; + t['\uFEC2'] = '\u0637'; + t['\uFEC3'] = '\u0637'; + t['\uFEC4'] = '\u0637'; + t['\uFEC5'] = '\u0638'; + t['\uFEC6'] = '\u0638'; + t['\uFEC7'] = '\u0638'; + t['\uFEC8'] = '\u0638'; + t['\uFEC9'] = '\u0639'; + t['\uFECA'] = '\u0639'; + t['\uFECB'] = '\u0639'; + t['\uFECC'] = '\u0639'; + t['\uFECD'] = '\u063A'; + t['\uFECE'] = '\u063A'; + t['\uFECF'] = '\u063A'; + t['\uFED0'] = '\u063A'; + t['\uFED1'] = '\u0641'; + t['\uFED2'] = '\u0641'; + t['\uFED3'] = '\u0641'; + t['\uFED4'] = '\u0641'; + t['\uFED5'] = '\u0642'; + t['\uFED6'] = '\u0642'; + t['\uFED7'] = '\u0642'; + t['\uFED8'] = '\u0642'; + t['\uFED9'] = '\u0643'; + t['\uFEDA'] = '\u0643'; + t['\uFEDB'] = '\u0643'; + t['\uFEDC'] = '\u0643'; + t['\uFEDD'] = '\u0644'; + t['\uFEDE'] = '\u0644'; + t['\uFEDF'] = '\u0644'; + t['\uFEE0'] = '\u0644'; + t['\uFEE1'] = '\u0645'; + t['\uFEE2'] = '\u0645'; + t['\uFEE3'] = '\u0645'; + t['\uFEE4'] = '\u0645'; + t['\uFEE5'] = '\u0646'; + t['\uFEE6'] = '\u0646'; + t['\uFEE7'] = '\u0646'; + t['\uFEE8'] = '\u0646'; + t['\uFEE9'] = '\u0647'; + t['\uFEEA'] = '\u0647'; + t['\uFEEB'] = '\u0647'; + t['\uFEEC'] = '\u0647'; + t['\uFEED'] = '\u0648'; + t['\uFEEE'] = '\u0648'; + t['\uFEEF'] = '\u0649'; + t['\uFEF0'] = '\u0649'; + t['\uFEF1'] = '\u064A'; + t['\uFEF2'] = '\u064A'; + t['\uFEF3'] = '\u064A'; + t['\uFEF4'] = '\u064A'; + t['\uFEF5'] = '\u0644\u0622'; + t['\uFEF6'] = '\u0644\u0622'; + t['\uFEF7'] = '\u0644\u0623'; + t['\uFEF8'] = '\u0644\u0623'; + t['\uFEF9'] = '\u0644\u0625'; + t['\uFEFA'] = '\u0644\u0625'; + t['\uFEFB'] = '\u0644\u0627'; + t['\uFEFC'] = '\u0644\u0627'; +}); +function reverseIfRtl(chars) { + var charsLength = chars.length; + if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) { + return chars; + } + var s = ''; + for (var ii = charsLength - 1; ii >= 0; ii--) { + s += chars[ii]; + } + return s; +} +exports.mapSpecialUnicodeValues = mapSpecialUnicodeValues; +exports.reverseIfRtl = reverseIfRtl; +exports.getUnicodeRangeFor = getUnicodeRangeFor; +exports.getNormalizedUnicodes = getNormalizedUnicodes; +exports.getUnicodeForGlyph = getUnicodeForGlyph; + +/***/ }), +/* 19 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var coreWorker = __w_pdfjs_require__(8); +var globalScope = sharedUtil.globalScope; +var OK_RESPONSE = 200; +var PARTIAL_CONTENT_RESPONSE = 206; +function NetworkManager(url, args) { + this.url = url; + args = args || {}; + this.isHttp = /^https?:/i.test(url); + this.httpHeaders = this.isHttp && args.httpHeaders || {}; + this.withCredentials = args.withCredentials || false; + this.getXhr = args.getXhr || function NetworkManager_getXhr() { + return new XMLHttpRequest(); + }; + this.currXhrId = 0; + this.pendingRequests = Object.create(null); + this.loadedRequests = Object.create(null); +} +function getArrayBuffer(xhr) { + var data = xhr.response; + if (typeof data !== 'string') { + return data; + } + var length = data.length; + var array = new Uint8Array(length); + for (var i = 0; i < length; i++) { + array[i] = data.charCodeAt(i) & 0xFF; + } + return array.buffer; +} +var supportsMozChunked = function supportsMozChunkedClosure() { + try { + var x = new XMLHttpRequest(); + x.open('GET', globalScope.location.href); + x.responseType = 'moz-chunked-arraybuffer'; + return x.responseType === 'moz-chunked-arraybuffer'; + } catch (e) { + return false; + } +}(); +NetworkManager.prototype = { + requestRange: function NetworkManager_requestRange(begin, end, listeners) { + var args = { + begin: begin, + end: end + }; + for (var prop in listeners) { + args[prop] = listeners[prop]; + } + return this.request(args); + }, + requestFull: function NetworkManager_requestFull(listeners) { + return this.request(listeners); + }, + request: function NetworkManager_request(args) { + var xhr = this.getXhr(); + var xhrId = this.currXhrId++; + var pendingRequest = this.pendingRequests[xhrId] = { xhr: xhr }; + xhr.open('GET', this.url); + xhr.withCredentials = this.withCredentials; + for (var property in this.httpHeaders) { + var value = this.httpHeaders[property]; + if (typeof value === 'undefined') { + continue; + } + xhr.setRequestHeader(property, value); + } + if (this.isHttp && 'begin' in args && 'end' in args) { + var rangeStr = args.begin + '-' + (args.end - 1); + xhr.setRequestHeader('Range', 'bytes=' + rangeStr); + pendingRequest.expectedStatus = 206; + } else { + pendingRequest.expectedStatus = 200; + } + var useMozChunkedLoading = supportsMozChunked && !!args.onProgressiveData; + if (useMozChunkedLoading) { + xhr.responseType = 'moz-chunked-arraybuffer'; + pendingRequest.onProgressiveData = args.onProgressiveData; + pendingRequest.mozChunked = true; + } else { + xhr.responseType = 'arraybuffer'; + } + if (args.onError) { + xhr.onerror = function (evt) { + args.onError(xhr.status); + }; + } + xhr.onreadystatechange = this.onStateChange.bind(this, xhrId); + xhr.onprogress = this.onProgress.bind(this, xhrId); + pendingRequest.onHeadersReceived = args.onHeadersReceived; + pendingRequest.onDone = args.onDone; + pendingRequest.onError = args.onError; + pendingRequest.onProgress = args.onProgress; + xhr.send(null); + return xhrId; + }, + onProgress: function NetworkManager_onProgress(xhrId, evt) { + var pendingRequest = this.pendingRequests[xhrId]; + if (!pendingRequest) { + return; + } + if (pendingRequest.mozChunked) { + var chunk = getArrayBuffer(pendingRequest.xhr); + pendingRequest.onProgressiveData(chunk); + } + var onProgress = pendingRequest.onProgress; + if (onProgress) { + onProgress(evt); + } + }, + onStateChange: function NetworkManager_onStateChange(xhrId, evt) { + var pendingRequest = this.pendingRequests[xhrId]; + if (!pendingRequest) { + return; + } + var xhr = pendingRequest.xhr; + if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) { + pendingRequest.onHeadersReceived(); + delete pendingRequest.onHeadersReceived; + } + if (xhr.readyState !== 4) { + return; + } + if (!(xhrId in this.pendingRequests)) { + return; + } + delete this.pendingRequests[xhrId]; + if (xhr.status === 0 && this.isHttp) { + if (pendingRequest.onError) { + pendingRequest.onError(xhr.status); + } + return; + } + var xhrStatus = xhr.status || OK_RESPONSE; + var ok_response_on_range_request = xhrStatus === OK_RESPONSE && pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; + if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) { + if (pendingRequest.onError) { + pendingRequest.onError(xhr.status); + } + return; + } + this.loadedRequests[xhrId] = true; + var chunk = getArrayBuffer(xhr); + if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { + var rangeHeader = xhr.getResponseHeader('Content-Range'); + var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); + var begin = parseInt(matches[1], 10); + pendingRequest.onDone({ + begin: begin, + chunk: chunk + }); + } else if (pendingRequest.onProgressiveData) { + pendingRequest.onDone(null); + } else if (chunk) { + pendingRequest.onDone({ + begin: 0, + chunk: chunk + }); + } else if (pendingRequest.onError) { + pendingRequest.onError(xhr.status); + } + }, + hasPendingRequests: function NetworkManager_hasPendingRequests() { + for (var xhrId in this.pendingRequests) { + return true; + } + return false; + }, + getRequestXhr: function NetworkManager_getXhr(xhrId) { + return this.pendingRequests[xhrId].xhr; + }, + isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) { + return !!this.pendingRequests[xhrId].onProgressiveData; + }, + isPendingRequest: function NetworkManager_isPendingRequest(xhrId) { + return xhrId in this.pendingRequests; + }, + isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) { + return xhrId in this.loadedRequests; + }, + abortAllRequests: function NetworkManager_abortAllRequests() { + for (var xhrId in this.pendingRequests) { + this.abortRequest(xhrId | 0); + } + }, + abortRequest: function NetworkManager_abortRequest(xhrId) { + var xhr = this.pendingRequests[xhrId].xhr; + delete this.pendingRequests[xhrId]; + xhr.abort(); + } +}; +var assert = sharedUtil.assert; +var createPromiseCapability = sharedUtil.createPromiseCapability; +var isInt = sharedUtil.isInt; +var MissingPDFException = sharedUtil.MissingPDFException; +var UnexpectedResponseException = sharedUtil.UnexpectedResponseException; +function PDFNetworkStream(options) { + this._options = options; + var source = options.source; + this._manager = new NetworkManager(source.url, { + httpHeaders: source.httpHeaders, + withCredentials: source.withCredentials + }); + this._rangeChunkSize = source.rangeChunkSize; + this._fullRequestReader = null; + this._rangeRequestReaders = []; +} +PDFNetworkStream.prototype = { + _onRangeRequestReaderClosed: function PDFNetworkStream_onRangeRequestReaderClosed(reader) { + var i = this._rangeRequestReaders.indexOf(reader); + if (i >= 0) { + this._rangeRequestReaders.splice(i, 1); + } + }, + getFullReader: function PDFNetworkStream_getFullReader() { + assert(!this._fullRequestReader); + this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._options); + return this._fullRequestReader; + }, + getRangeReader: function PDFNetworkStream_getRangeReader(begin, end) { + var reader = new PDFNetworkStreamRangeRequestReader(this._manager, begin, end); + reader.onClosed = this._onRangeRequestReaderClosed.bind(this); + this._rangeRequestReaders.push(reader); + return reader; + }, + cancelAllRequests: function PDFNetworkStream_cancelAllRequests(reason) { + if (this._fullRequestReader) { + this._fullRequestReader.cancel(reason); + } + var readers = this._rangeRequestReaders.slice(0); + readers.forEach(function (reader) { + reader.cancel(reason); + }); + } +}; +function PDFNetworkStreamFullRequestReader(manager, options) { + this._manager = manager; + var source = options.source; + var args = { + onHeadersReceived: this._onHeadersReceived.bind(this), + onProgressiveData: source.disableStream ? null : this._onProgressiveData.bind(this), + onDone: this._onDone.bind(this), + onError: this._onError.bind(this), + onProgress: this._onProgress.bind(this) + }; + this._url = source.url; + this._fullRequestId = manager.requestFull(args); + this._headersReceivedCapability = createPromiseCapability(); + this._disableRange = options.disableRange || false; + this._contentLength = source.length; + this._rangeChunkSize = source.rangeChunkSize; + if (!this._rangeChunkSize && !this._disableRange) { + this._disableRange = true; + } + this._isStreamingSupported = false; + this._isRangeSupported = false; + this._cachedChunks = []; + this._requests = []; + this._done = false; + this._storedError = undefined; + this.onProgress = null; +} +PDFNetworkStreamFullRequestReader.prototype = { + _validateRangeRequestCapabilities: function PDFNetworkStreamFullRequestReader_validateRangeRequestCapabilities() { + if (this._disableRange) { + return false; + } + var networkManager = this._manager; + if (!networkManager.isHttp) { + return false; + } + var fullRequestXhrId = this._fullRequestId; + var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId); + if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') { + return false; + } + var contentEncoding = fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity'; + if (contentEncoding !== 'identity') { + return false; + } + var length = fullRequestXhr.getResponseHeader('Content-Length'); + length = parseInt(length, 10); + if (!isInt(length)) { + return false; + } + this._contentLength = length; + if (length <= 2 * this._rangeChunkSize) { + return false; + } + return true; + }, + _onHeadersReceived: function PDFNetworkStreamFullRequestReader_onHeadersReceived() { + if (this._validateRangeRequestCapabilities()) { + this._isRangeSupported = true; + } + var networkManager = this._manager; + var fullRequestXhrId = this._fullRequestId; + if (networkManager.isStreamingRequest(fullRequestXhrId)) { + this._isStreamingSupported = true; + } else if (this._isRangeSupported) { + networkManager.abortRequest(fullRequestXhrId); + } + this._headersReceivedCapability.resolve(); + }, + _onProgressiveData: function PDFNetworkStreamFullRequestReader_onProgressiveData(chunk) { + if (this._requests.length > 0) { + var requestCapability = this._requests.shift(); + requestCapability.resolve({ + value: chunk, + done: false + }); + } else { + this._cachedChunks.push(chunk); + } + }, + _onDone: function PDFNetworkStreamFullRequestReader_onDone(args) { + if (args) { + this._onProgressiveData(args.chunk); + } + this._done = true; + if (this._cachedChunks.length > 0) { + return; + } + this._requests.forEach(function (requestCapability) { + requestCapability.resolve({ + value: undefined, + done: true + }); + }); + this._requests = []; + }, + _onError: function PDFNetworkStreamFullRequestReader_onError(status) { + var url = this._url; + var exception; + if (status === 404 || status === 0 && /^file:/.test(url)) { + exception = new MissingPDFException('Missing PDF "' + url + '".'); + } else { + exception = new UnexpectedResponseException('Unexpected server response (' + status + ') while retrieving PDF "' + url + '".', status); + } + this._storedError = exception; + this._headersReceivedCapability.reject(exception); + this._requests.forEach(function (requestCapability) { + requestCapability.reject(exception); + }); + this._requests = []; + this._cachedChunks = []; + }, + _onProgress: function PDFNetworkStreamFullRequestReader_onProgress(data) { + if (this.onProgress) { + this.onProgress({ + loaded: data.loaded, + total: data.lengthComputable ? data.total : this._contentLength + }); + } + }, + get isRangeSupported() { + return this._isRangeSupported; + }, + get isStreamingSupported() { + return this._isStreamingSupported; + }, + get contentLength() { + return this._contentLength; + }, + get headersReady() { + return this._headersReceivedCapability.promise; + }, + read: function PDFNetworkStreamFullRequestReader_read() { + if (this._storedError) { + return Promise.reject(this._storedError); + } + if (this._cachedChunks.length > 0) { + var chunk = this._cachedChunks.shift(); + return Promise.resolve(chunk); + } + if (this._done) { + return Promise.resolve({ + value: undefined, + done: true + }); + } + var requestCapability = createPromiseCapability(); + this._requests.push(requestCapability); + return requestCapability.promise; + }, + cancel: function PDFNetworkStreamFullRequestReader_cancel(reason) { + this._done = true; + this._headersReceivedCapability.reject(reason); + this._requests.forEach(function (requestCapability) { + requestCapability.resolve({ + value: undefined, + done: true + }); + }); + this._requests = []; + if (this._manager.isPendingRequest(this._fullRequestId)) { + this._manager.abortRequest(this._fullRequestId); + } + this._fullRequestReader = null; + } +}; +function PDFNetworkStreamRangeRequestReader(manager, begin, end) { + this._manager = manager; + var args = { + onDone: this._onDone.bind(this), + onProgress: this._onProgress.bind(this) + }; + this._requestId = manager.requestRange(begin, end, args); + this._requests = []; + this._queuedChunk = null; + this._done = false; + this.onProgress = null; + this.onClosed = null; +} +PDFNetworkStreamRangeRequestReader.prototype = { + _close: function PDFNetworkStreamRangeRequestReader_close() { + if (this.onClosed) { + this.onClosed(this); + } + }, + _onDone: function PDFNetworkStreamRangeRequestReader_onDone(data) { + var chunk = data.chunk; + if (this._requests.length > 0) { + var requestCapability = this._requests.shift(); + requestCapability.resolve({ + value: chunk, + done: false + }); + } else { + this._queuedChunk = chunk; + } + this._done = true; + this._requests.forEach(function (requestCapability) { + requestCapability.resolve({ + value: undefined, + done: true + }); + }); + this._requests = []; + this._close(); + }, + _onProgress: function PDFNetworkStreamRangeRequestReader_onProgress(evt) { + if (!this.isStreamingSupported && this.onProgress) { + this.onProgress({ loaded: evt.loaded }); + } + }, + get isStreamingSupported() { + return false; + }, + read: function PDFNetworkStreamRangeRequestReader_read() { + if (this._queuedChunk !== null) { + var chunk = this._queuedChunk; + this._queuedChunk = null; + return Promise.resolve({ + value: chunk, + done: false + }); + } + if (this._done) { + return Promise.resolve({ + value: undefined, + done: true + }); + } + var requestCapability = createPromiseCapability(); + this._requests.push(requestCapability); + return requestCapability.promise; + }, + cancel: function PDFNetworkStreamRangeRequestReader_cancel(reason) { + this._done = true; + this._requests.forEach(function (requestCapability) { + requestCapability.resolve({ + value: undefined, + done: true + }); + }); + this._requests = []; + if (this._manager.isPendingRequest(this._requestId)) { + this._manager.abortRequest(this._requestId); + } + this._close(); + } +}; +coreWorker.setPDFNetworkStreamClass(PDFNetworkStream); +exports.PDFNetworkStream = PDFNetworkStream; +exports.NetworkManager = NetworkManager; + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreStream = __w_pdfjs_require__(2); +var coreColorSpace = __w_pdfjs_require__(3); +var coreObj = __w_pdfjs_require__(16); +var coreEvaluator = __w_pdfjs_require__(14); +var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType; +var AnnotationFieldFlag = sharedUtil.AnnotationFieldFlag; +var AnnotationFlag = sharedUtil.AnnotationFlag; +var AnnotationType = sharedUtil.AnnotationType; +var OPS = sharedUtil.OPS; +var Util = sharedUtil.Util; +var isArray = sharedUtil.isArray; +var isInt = sharedUtil.isInt; +var stringToBytes = sharedUtil.stringToBytes; +var stringToPDFString = sharedUtil.stringToPDFString; +var warn = sharedUtil.warn; +var Dict = corePrimitives.Dict; +var isDict = corePrimitives.isDict; +var isName = corePrimitives.isName; +var isRef = corePrimitives.isRef; +var isStream = corePrimitives.isStream; +var Stream = coreStream.Stream; +var ColorSpace = coreColorSpace.ColorSpace; +var Catalog = coreObj.Catalog; +var ObjectLoader = coreObj.ObjectLoader; +var FileSpec = coreObj.FileSpec; +var OperatorList = coreEvaluator.OperatorList; +function AnnotationFactory() { +} +AnnotationFactory.prototype = { + create: function AnnotationFactory_create(xref, ref, pdfManager, idFactory) { + var dict = xref.fetchIfRef(ref); + if (!isDict(dict)) { + return; + } + var id = isRef(ref) ? ref.toString() : 'annot_' + idFactory.createObjId(); + var subtype = dict.get('Subtype'); + subtype = isName(subtype) ? subtype.name : null; + var parameters = { + xref: xref, + dict: dict, + ref: isRef(ref) ? ref : null, + subtype: subtype, + id: id, + pdfManager: pdfManager + }; + switch (subtype) { + case 'Link': + return new LinkAnnotation(parameters); + case 'Text': + return new TextAnnotation(parameters); + case 'Widget': + var fieldType = Util.getInheritableProperty(dict, 'FT'); + fieldType = isName(fieldType) ? fieldType.name : null; + switch (fieldType) { + case 'Tx': + return new TextWidgetAnnotation(parameters); + case 'Btn': + return new ButtonWidgetAnnotation(parameters); + case 'Ch': + return new ChoiceWidgetAnnotation(parameters); + } + warn('Unimplemented widget field type "' + fieldType + '", ' + 'falling back to base field type.'); + return new WidgetAnnotation(parameters); + case 'Popup': + return new PopupAnnotation(parameters); + case 'Highlight': + return new HighlightAnnotation(parameters); + case 'Underline': + return new UnderlineAnnotation(parameters); + case 'Squiggly': + return new SquigglyAnnotation(parameters); + case 'StrikeOut': + return new StrikeOutAnnotation(parameters); + case 'FileAttachment': + return new FileAttachmentAnnotation(parameters); + default: + if (!subtype) { + warn('Annotation is missing the required /Subtype.'); + } else { + warn('Unimplemented annotation type "' + subtype + '", ' + 'falling back to base annotation.'); + } + return new Annotation(parameters); + } + } +}; +var Annotation = function AnnotationClosure() { + function getTransformMatrix(rect, bbox, matrix) { + var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix); + var minX = bounds[0]; + var minY = bounds[1]; + var maxX = bounds[2]; + var maxY = bounds[3]; + if (minX === maxX || minY === maxY) { + return [ + 1, + 0, + 0, + 1, + rect[0], + rect[1] + ]; + } + var xRatio = (rect[2] - rect[0]) / (maxX - minX); + var yRatio = (rect[3] - rect[1]) / (maxY - minY); + return [ + xRatio, + 0, + 0, + yRatio, + rect[0] - minX * xRatio, + rect[1] - minY * yRatio + ]; + } + function Annotation(params) { + var dict = params.dict; + this.setFlags(dict.get('F')); + this.setRectangle(dict.getArray('Rect')); + this.setColor(dict.getArray('C')); + this.setBorderStyle(dict); + this.setAppearance(dict); + this.data = {}; + this.data.id = params.id; + this.data.subtype = params.subtype; + this.data.annotationFlags = this.flags; + this.data.rect = this.rectangle; + this.data.color = this.color; + this.data.borderStyle = this.borderStyle; + this.data.hasAppearance = !!this.appearance; + } + Annotation.prototype = { + _hasFlag: function Annotation_hasFlag(flags, flag) { + return !!(flags & flag); + }, + _isViewable: function Annotation_isViewable(flags) { + return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, AnnotationFlag.HIDDEN) && !this._hasFlag(flags, AnnotationFlag.NOVIEW); + }, + _isPrintable: function AnnotationFlag_isPrintable(flags) { + return this._hasFlag(flags, AnnotationFlag.PRINT) && !this._hasFlag(flags, AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, AnnotationFlag.HIDDEN); + }, + get viewable() { + if (this.flags === 0) { + return true; + } + return this._isViewable(this.flags); + }, + get printable() { + if (this.flags === 0) { + return false; + } + return this._isPrintable(this.flags); + }, + setFlags: function Annotation_setFlags(flags) { + this.flags = isInt(flags) && flags > 0 ? flags : 0; + }, + hasFlag: function Annotation_hasFlag(flag) { + return this._hasFlag(this.flags, flag); + }, + setRectangle: function Annotation_setRectangle(rectangle) { + if (isArray(rectangle) && rectangle.length === 4) { + this.rectangle = Util.normalizeRect(rectangle); + } else { + this.rectangle = [ + 0, + 0, + 0, + 0 + ]; + } + }, + setColor: function Annotation_setColor(color) { + var rgbColor = new Uint8Array(3); + if (!isArray(color)) { + this.color = rgbColor; + return; + } + switch (color.length) { + case 0: + this.color = null; + break; + case 1: + ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0); + this.color = rgbColor; + break; + case 3: + ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0); + this.color = rgbColor; + break; + case 4: + ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0); + this.color = rgbColor; + break; + default: + this.color = rgbColor; + break; + } + }, + setBorderStyle: function Annotation_setBorderStyle(borderStyle) { + this.borderStyle = new AnnotationBorderStyle(); + if (!isDict(borderStyle)) { + return; + } + if (borderStyle.has('BS')) { + var dict = borderStyle.get('BS'); + var dictType = dict.get('Type'); + if (!dictType || isName(dictType, 'Border')) { + this.borderStyle.setWidth(dict.get('W')); + this.borderStyle.setStyle(dict.get('S')); + this.borderStyle.setDashArray(dict.getArray('D')); + } + } else if (borderStyle.has('Border')) { + var array = borderStyle.getArray('Border'); + if (isArray(array) && array.length >= 3) { + this.borderStyle.setHorizontalCornerRadius(array[0]); + this.borderStyle.setVerticalCornerRadius(array[1]); + this.borderStyle.setWidth(array[2]); + if (array.length === 4) { + this.borderStyle.setDashArray(array[3]); + } + } + } else { + this.borderStyle.setWidth(0); + } + }, + setAppearance: function Annotation_setAppearance(dict) { + this.appearance = null; + var appearanceStates = dict.get('AP'); + if (!isDict(appearanceStates)) { + return; + } + var normalAppearanceState = appearanceStates.get('N'); + if (isStream(normalAppearanceState)) { + this.appearance = normalAppearanceState; + return; + } + if (!isDict(normalAppearanceState)) { + return; + } + var as = dict.get('AS'); + if (!isName(as) || !normalAppearanceState.has(as.name)) { + return; + } + this.appearance = normalAppearanceState.get(as.name); + }, + _preparePopup: function Annotation_preparePopup(dict) { + if (!dict.has('C')) { + this.data.color = null; + } + this.data.hasPopup = dict.has('Popup'); + this.data.title = stringToPDFString(dict.get('T') || ''); + this.data.contents = stringToPDFString(dict.get('Contents') || ''); + }, + loadResources: function Annotation_loadResources(keys) { + return new Promise(function (resolve, reject) { + this.appearance.dict.getAsync('Resources').then(function (resources) { + if (!resources) { + resolve(); + return; + } + var objectLoader = new ObjectLoader(resources.map, keys, resources.xref); + objectLoader.load().then(function () { + resolve(resources); + }, reject); + }, reject); + }.bind(this)); + }, + getOperatorList: function Annotation_getOperatorList(evaluator, task, renderForms) { + if (!this.appearance) { + return Promise.resolve(new OperatorList()); + } + var data = this.data; + var appearanceDict = this.appearance.dict; + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'ColorSpace', + 'Pattern', + 'Shading', + 'XObject', + 'Font' + ]); + var bbox = appearanceDict.getArray('BBox') || [ + 0, + 0, + 1, + 1 + ]; + var matrix = appearanceDict.getArray('Matrix') || [ + 1, + 0, + 0, + 1, + 0, + 0 + ]; + var transform = getTransformMatrix(data.rect, bbox, matrix); + var self = this; + return resourcesPromise.then(function (resources) { + var opList = new OperatorList(); + opList.addOp(OPS.beginAnnotation, [ + data.rect, + transform, + matrix + ]); + return evaluator.getOperatorList(self.appearance, task, resources, opList).then(function () { + opList.addOp(OPS.endAnnotation, []); + self.appearance.reset(); + return opList; + }); + }); + } + }; + return Annotation; +}(); +var AnnotationBorderStyle = function AnnotationBorderStyleClosure() { + function AnnotationBorderStyle() { + this.width = 1; + this.style = AnnotationBorderStyleType.SOLID; + this.dashArray = [3]; + this.horizontalCornerRadius = 0; + this.verticalCornerRadius = 0; + } + AnnotationBorderStyle.prototype = { + setWidth: function AnnotationBorderStyle_setWidth(width) { + if (width === (width | 0)) { + this.width = width; + } + }, + setStyle: function AnnotationBorderStyle_setStyle(style) { + if (!style) { + return; + } + switch (style.name) { + case 'S': + this.style = AnnotationBorderStyleType.SOLID; + break; + case 'D': + this.style = AnnotationBorderStyleType.DASHED; + break; + case 'B': + this.style = AnnotationBorderStyleType.BEVELED; + break; + case 'I': + this.style = AnnotationBorderStyleType.INSET; + break; + case 'U': + this.style = AnnotationBorderStyleType.UNDERLINE; + break; + default: + break; + } + }, + setDashArray: function AnnotationBorderStyle_setDashArray(dashArray) { + if (isArray(dashArray) && dashArray.length > 0) { + var isValid = true; + var allZeros = true; + for (var i = 0, len = dashArray.length; i < len; i++) { + var element = dashArray[i]; + var validNumber = +element >= 0; + if (!validNumber) { + isValid = false; + break; + } else if (element > 0) { + allZeros = false; + } + } + if (isValid && !allZeros) { + this.dashArray = dashArray; + } else { + this.width = 0; + } + } else if (dashArray) { + this.width = 0; + } + }, + setHorizontalCornerRadius: function AnnotationBorderStyle_setHorizontalCornerRadius(radius) { + if (radius === (radius | 0)) { + this.horizontalCornerRadius = radius; + } + }, + setVerticalCornerRadius: function AnnotationBorderStyle_setVerticalCornerRadius(radius) { + if (radius === (radius | 0)) { + this.verticalCornerRadius = radius; + } + } + }; + return AnnotationBorderStyle; +}(); +var WidgetAnnotation = function WidgetAnnotationClosure() { + function WidgetAnnotation(params) { + Annotation.call(this, params); + var dict = params.dict; + var data = this.data; + data.annotationType = AnnotationType.WIDGET; + data.fieldName = this._constructFieldName(dict); + data.fieldValue = Util.getInheritableProperty(dict, 'V', true); + data.alternativeText = stringToPDFString(dict.get('TU') || ''); + data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || ''; + var fieldType = Util.getInheritableProperty(dict, 'FT'); + data.fieldType = isName(fieldType) ? fieldType.name : null; + this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty; + data.fieldFlags = Util.getInheritableProperty(dict, 'Ff'); + if (!isInt(data.fieldFlags) || data.fieldFlags < 0) { + data.fieldFlags = 0; + } + data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY); + if (data.fieldType === 'Sig') { + this.setFlags(AnnotationFlag.HIDDEN); + } + } + Util.inherit(WidgetAnnotation, Annotation, { + _constructFieldName: function WidgetAnnotation_constructFieldName(dict) { + if (!dict.has('T') && !dict.has('Parent')) { + warn('Unknown field name, falling back to empty field name.'); + return ''; + } + if (!dict.has('Parent')) { + return stringToPDFString(dict.get('T')); + } + var fieldName = []; + if (dict.has('T')) { + fieldName.unshift(stringToPDFString(dict.get('T'))); + } + var loopDict = dict; + while (loopDict.has('Parent')) { + loopDict = loopDict.get('Parent'); + if (loopDict.has('T')) { + fieldName.unshift(stringToPDFString(loopDict.get('T'))); + } + } + return fieldName.join('.'); + }, + hasFieldFlag: function WidgetAnnotation_hasFieldFlag(flag) { + return !!(this.data.fieldFlags & flag); + } + }); + return WidgetAnnotation; +}(); +var TextWidgetAnnotation = function TextWidgetAnnotationClosure() { + function TextWidgetAnnotation(params) { + WidgetAnnotation.call(this, params); + this.data.fieldValue = stringToPDFString(this.data.fieldValue || ''); + var alignment = Util.getInheritableProperty(params.dict, 'Q'); + if (!isInt(alignment) || alignment < 0 || alignment > 2) { + alignment = null; + } + this.data.textAlignment = alignment; + var maximumLength = Util.getInheritableProperty(params.dict, 'MaxLen'); + if (!isInt(maximumLength) || maximumLength < 0) { + maximumLength = null; + } + this.data.maxLen = maximumLength; + this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE); + this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) && !this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) && !this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) && !this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== null; + } + Util.inherit(TextWidgetAnnotation, WidgetAnnotation, { + getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator, task, renderForms) { + var operatorList = new OperatorList(); + if (renderForms) { + return Promise.resolve(operatorList); + } + if (this.appearance) { + return Annotation.prototype.getOperatorList.call(this, evaluator, task, renderForms); + } + if (!this.data.defaultAppearance) { + return Promise.resolve(operatorList); + } + var stream = new Stream(stringToBytes(this.data.defaultAppearance)); + return evaluator.getOperatorList(stream, task, this.fieldResources, operatorList).then(function () { + return operatorList; + }); + } + }); + return TextWidgetAnnotation; +}(); +var ButtonWidgetAnnotation = function ButtonWidgetAnnotationClosure() { + function ButtonWidgetAnnotation(params) { + WidgetAnnotation.call(this, params); + this.data.checkBox = !this.hasFieldFlag(AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON); + if (this.data.checkBox) { + if (!isName(this.data.fieldValue)) { + return; + } + this.data.fieldValue = this.data.fieldValue.name; + } + this.data.radioButton = this.hasFieldFlag(AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON); + if (this.data.radioButton) { + this.data.fieldValue = this.data.buttonValue = null; + var fieldParent = params.dict.get('Parent'); + if (isDict(fieldParent) && fieldParent.has('V')) { + var fieldParentValue = fieldParent.get('V'); + if (isName(fieldParentValue)) { + this.data.fieldValue = fieldParentValue.name; + } + } + var appearanceStates = params.dict.get('AP'); + if (!isDict(appearanceStates)) { + return; + } + var normalAppearanceState = appearanceStates.get('N'); + if (!isDict(normalAppearanceState)) { + return; + } + var keys = normalAppearanceState.getKeys(); + for (var i = 0, ii = keys.length; i < ii; i++) { + if (keys[i] !== 'Off') { + this.data.buttonValue = keys[i]; + break; + } + } + } + } + Util.inherit(ButtonWidgetAnnotation, WidgetAnnotation, { + getOperatorList: function ButtonWidgetAnnotation_getOperatorList(evaluator, task, renderForms) { + var operatorList = new OperatorList(); + if (renderForms) { + return Promise.resolve(operatorList); + } + if (this.appearance) { + return Annotation.prototype.getOperatorList.call(this, evaluator, task, renderForms); + } + return Promise.resolve(operatorList); + } + }); + return ButtonWidgetAnnotation; +}(); +var ChoiceWidgetAnnotation = function ChoiceWidgetAnnotationClosure() { + function ChoiceWidgetAnnotation(params) { + WidgetAnnotation.call(this, params); + this.data.options = []; + var options = Util.getInheritableProperty(params.dict, 'Opt'); + if (isArray(options)) { + var xref = params.xref; + for (var i = 0, ii = options.length; i < ii; i++) { + var option = xref.fetchIfRef(options[i]); + var isOptionArray = isArray(option); + this.data.options[i] = { + exportValue: isOptionArray ? xref.fetchIfRef(option[0]) : option, + displayValue: isOptionArray ? xref.fetchIfRef(option[1]) : option + }; + } + } + if (!isArray(this.data.fieldValue)) { + this.data.fieldValue = [this.data.fieldValue]; + } + this.data.combo = this.hasFieldFlag(AnnotationFieldFlag.COMBO); + this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT); + } + Util.inherit(ChoiceWidgetAnnotation, WidgetAnnotation, { + getOperatorList: function ChoiceWidgetAnnotation_getOperatorList(evaluator, task, renderForms) { + var operatorList = new OperatorList(); + if (renderForms) { + return Promise.resolve(operatorList); + } + return Annotation.prototype.getOperatorList.call(this, evaluator, task, renderForms); + } + }); + return ChoiceWidgetAnnotation; +}(); +var TextAnnotation = function TextAnnotationClosure() { + var DEFAULT_ICON_SIZE = 22; + function TextAnnotation(parameters) { + Annotation.call(this, parameters); + this.data.annotationType = AnnotationType.TEXT; + if (this.data.hasAppearance) { + this.data.name = 'NoIcon'; + } else { + this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE; + this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE; + this.data.name = parameters.dict.has('Name') ? parameters.dict.get('Name').name : 'Note'; + } + this._preparePopup(parameters.dict); + } + Util.inherit(TextAnnotation, Annotation, {}); + return TextAnnotation; +}(); +var LinkAnnotation = function LinkAnnotationClosure() { + function LinkAnnotation(params) { + Annotation.call(this, params); + var data = this.data; + data.annotationType = AnnotationType.LINK; + Catalog.parseDestDictionary({ + destDict: params.dict, + resultObj: data, + docBaseUrl: params.pdfManager.docBaseUrl + }); + } + Util.inherit(LinkAnnotation, Annotation, {}); + return LinkAnnotation; +}(); +var PopupAnnotation = function PopupAnnotationClosure() { + function PopupAnnotation(parameters) { + Annotation.call(this, parameters); + this.data.annotationType = AnnotationType.POPUP; + var dict = parameters.dict; + var parentItem = dict.get('Parent'); + if (!parentItem) { + warn('Popup annotation has a missing or invalid parent annotation.'); + return; + } + this.data.parentId = dict.getRaw('Parent').toString(); + this.data.title = stringToPDFString(parentItem.get('T') || ''); + this.data.contents = stringToPDFString(parentItem.get('Contents') || ''); + if (!parentItem.has('C')) { + this.data.color = null; + } else { + this.setColor(parentItem.getArray('C')); + this.data.color = this.color; + } + if (!this.viewable) { + var parentFlags = parentItem.get('F'); + if (this._isViewable(parentFlags)) { + this.setFlags(parentFlags); + } + } + } + Util.inherit(PopupAnnotation, Annotation, {}); + return PopupAnnotation; +}(); +var HighlightAnnotation = function HighlightAnnotationClosure() { + function HighlightAnnotation(parameters) { + Annotation.call(this, parameters); + this.data.annotationType = AnnotationType.HIGHLIGHT; + this._preparePopup(parameters.dict); + this.data.borderStyle.setWidth(0); + } + Util.inherit(HighlightAnnotation, Annotation, {}); + return HighlightAnnotation; +}(); +var UnderlineAnnotation = function UnderlineAnnotationClosure() { + function UnderlineAnnotation(parameters) { + Annotation.call(this, parameters); + this.data.annotationType = AnnotationType.UNDERLINE; + this._preparePopup(parameters.dict); + this.data.borderStyle.setWidth(0); + } + Util.inherit(UnderlineAnnotation, Annotation, {}); + return UnderlineAnnotation; +}(); +var SquigglyAnnotation = function SquigglyAnnotationClosure() { + function SquigglyAnnotation(parameters) { + Annotation.call(this, parameters); + this.data.annotationType = AnnotationType.SQUIGGLY; + this._preparePopup(parameters.dict); + this.data.borderStyle.setWidth(0); + } + Util.inherit(SquigglyAnnotation, Annotation, {}); + return SquigglyAnnotation; +}(); +var StrikeOutAnnotation = function StrikeOutAnnotationClosure() { + function StrikeOutAnnotation(parameters) { + Annotation.call(this, parameters); + this.data.annotationType = AnnotationType.STRIKEOUT; + this._preparePopup(parameters.dict); + this.data.borderStyle.setWidth(0); + } + Util.inherit(StrikeOutAnnotation, Annotation, {}); + return StrikeOutAnnotation; +}(); +var FileAttachmentAnnotation = function FileAttachmentAnnotationClosure() { + function FileAttachmentAnnotation(parameters) { + Annotation.call(this, parameters); + var file = new FileSpec(parameters.dict.get('FS'), parameters.xref); + this.data.annotationType = AnnotationType.FILEATTACHMENT; + this.data.file = file.serializable; + this._preparePopup(parameters.dict); + } + Util.inherit(FileAttachmentAnnotation, Annotation, {}); + return FileAttachmentAnnotation; +}(); +exports.Annotation = Annotation; +exports.AnnotationBorderStyle = AnnotationBorderStyle; +exports.AnnotationFactory = AnnotationFactory; + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var warn = sharedUtil.warn; +var baseTypes = [ + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'S', + 'B', + 'S', + 'WS', + 'B', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'B', + 'B', + 'B', + 'S', + 'WS', + 'ON', + 'ON', + 'ET', + 'ET', + 'ET', + 'ON', + 'ON', + 'ON', + 'ON', + 'ON', + 'ES', + 'CS', + 'ES', + 'CS', + 'CS', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'CS', + 'ON', + 'ON', + 'ON', + 'ON', + 'ON', + 'ON', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'ON', + 'ON', + 'ON', + 'ON', + 'ON', + 'ON', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'ON', + 'ON', + 'ON', + 'ON', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'B', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'BN', + 'CS', + 'ON', + 'ET', + 'ET', + 'ET', + 'ET', + 'ON', + 'ON', + 'ON', + 'ON', + 'L', + 'ON', + 'ON', + 'BN', + 'ON', + 'ON', + 'ET', + 'ET', + 'EN', + 'EN', + 'ON', + 'L', + 'ON', + 'ON', + 'ON', + 'EN', + 'L', + 'ON', + 'ON', + 'ON', + 'ON', + 'ON', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'ON', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'ON', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L', + 'L' +]; +var arabicTypes = [ + 'AN', + 'AN', + 'AN', + 'AN', + 'AN', + 'AN', + 'ON', + 'ON', + 'AL', + 'ET', + 'ET', + 'AL', + 'CS', + 'AL', + 'ON', + 'ON', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'AL', + 'AL', + '', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'AN', + 'AN', + 'AN', + 'AN', + 'AN', + 'AN', + 'AN', + 'AN', + 'AN', + 'AN', + 'ET', + 'AN', + 'AN', + 'AL', + 'AL', + 'AL', + 'NSM', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'AN', + 'ON', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'AL', + 'AL', + 'NSM', + 'NSM', + 'ON', + 'NSM', + 'NSM', + 'NSM', + 'NSM', + 'AL', + 'AL', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'EN', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL', + 'AL' +]; +function isOdd(i) { + return (i & 1) !== 0; +} +function isEven(i) { + return (i & 1) === 0; +} +function findUnequal(arr, start, value) { + for (var j = start, jj = arr.length; j < jj; ++j) { + if (arr[j] !== value) { + return j; + } + } + return j; +} +function setValues(arr, start, end, value) { + for (var j = start; j < end; ++j) { + arr[j] = value; + } +} +function reverseValues(arr, start, end) { + for (var i = start, j = end - 1; i < j; ++i, --j) { + var temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } +} +function createBidiText(str, isLTR, vertical) { + return { + str: str, + dir: vertical ? 'ttb' : isLTR ? 'ltr' : 'rtl' + }; +} +var chars = []; +var types = []; +function bidi(str, startLevel, vertical) { + var isLTR = true; + var strLength = str.length; + if (strLength === 0 || vertical) { + return createBidiText(str, isLTR, vertical); + } + chars.length = strLength; + types.length = strLength; + var numBidi = 0; + var i, ii; + for (i = 0; i < strLength; ++i) { + chars[i] = str.charAt(i); + var charCode = str.charCodeAt(i); + var charType = 'L'; + if (charCode <= 0x00ff) { + charType = baseTypes[charCode]; + } else if (0x0590 <= charCode && charCode <= 0x05f4) { + charType = 'R'; + } else if (0x0600 <= charCode && charCode <= 0x06ff) { + charType = arabicTypes[charCode & 0xff]; + if (!charType) { + warn('Bidi: invalid Unicode character ' + charCode.toString(16)); + } + } else if (0x0700 <= charCode && charCode <= 0x08AC) { + charType = 'AL'; + } + if (charType === 'R' || charType === 'AL' || charType === 'AN') { + numBidi++; + } + types[i] = charType; + } + if (numBidi === 0) { + isLTR = true; + return createBidiText(str, isLTR); + } + if (startLevel === -1) { + if (numBidi / strLength < 0.3) { + isLTR = true; + startLevel = 0; + } else { + isLTR = false; + startLevel = 1; + } + } + var levels = []; + for (i = 0; i < strLength; ++i) { + levels[i] = startLevel; + } + var e = isOdd(startLevel) ? 'R' : 'L'; + var sor = e; + var eor = sor; + var lastType = sor; + for (i = 0; i < strLength; ++i) { + if (types[i] === 'NSM') { + types[i] = lastType; + } else { + lastType = types[i]; + } + } + lastType = sor; + var t; + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'EN') { + types[i] = lastType === 'AL' ? 'AN' : 'EN'; + } else if (t === 'R' || t === 'L' || t === 'AL') { + lastType = t; + } + } + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'AL') { + types[i] = 'R'; + } + } + for (i = 1; i < strLength - 1; ++i) { + if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') { + types[i] = 'EN'; + } + if (types[i] === 'CS' && (types[i - 1] === 'EN' || types[i - 1] === 'AN') && types[i + 1] === types[i - 1]) { + types[i] = types[i - 1]; + } + } + for (i = 0; i < strLength; ++i) { + if (types[i] === 'EN') { + var j; + for (j = i - 1; j >= 0; --j) { + if (types[j] !== 'ET') { + break; + } + types[j] = 'EN'; + } + for (j = i + 1; j < strLength; ++j) { + if (types[j] !== 'ET') { + break; + } + types[j] = 'EN'; + } + } + } + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') { + types[i] = 'ON'; + } + } + lastType = sor; + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'EN') { + types[i] = lastType === 'L' ? 'L' : 'EN'; + } else if (t === 'R' || t === 'L') { + lastType = t; + } + } + for (i = 0; i < strLength; ++i) { + if (types[i] === 'ON') { + var end = findUnequal(types, i + 1, 'ON'); + var before = sor; + if (i > 0) { + before = types[i - 1]; + } + var after = eor; + if (end + 1 < strLength) { + after = types[end + 1]; + } + if (before !== 'L') { + before = 'R'; + } + if (after !== 'L') { + after = 'R'; + } + if (before === after) { + setValues(types, i, end, before); + } + i = end - 1; + } + } + for (i = 0; i < strLength; ++i) { + if (types[i] === 'ON') { + types[i] = e; + } + } + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (isEven(levels[i])) { + if (t === 'R') { + levels[i] += 1; + } else if (t === 'AN' || t === 'EN') { + levels[i] += 2; + } + } else { + if (t === 'L' || t === 'AN' || t === 'EN') { + levels[i] += 1; + } + } + } + var highestLevel = -1; + var lowestOddLevel = 99; + var level; + for (i = 0, ii = levels.length; i < ii; ++i) { + level = levels[i]; + if (highestLevel < level) { + highestLevel = level; + } + if (lowestOddLevel > level && isOdd(level)) { + lowestOddLevel = level; + } + } + for (level = highestLevel; level >= lowestOddLevel; --level) { + var start = -1; + for (i = 0, ii = levels.length; i < ii; ++i) { + if (levels[i] < level) { + if (start >= 0) { + reverseValues(chars, start, i); + start = -1; + } + } else if (start < 0) { + start = i; + } + } + if (start >= 0) { + reverseValues(chars, start, levels.length); + } + } + for (i = 0, ii = chars.length; i < ii; ++i) { + var ch = chars[i]; + if (ch === '<' || ch === '>') { + chars[i] = ''; + } + } + return createBidiText(chars.join(''), isLTR); +} +exports.bidi = bidi; + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var ISOAdobeCharset = [ + '.notdef', + 'space', + 'exclam', + 'quotedbl', + 'numbersign', + 'dollar', + 'percent', + 'ampersand', + 'quoteright', + 'parenleft', + 'parenright', + 'asterisk', + 'plus', + 'comma', + 'hyphen', + 'period', + 'slash', + 'zero', + 'one', + 'two', + 'three', + 'four', + 'five', + 'six', + 'seven', + 'eight', + 'nine', + 'colon', + 'semicolon', + 'less', + 'equal', + 'greater', + 'question', + 'at', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + 'bracketleft', + 'backslash', + 'bracketright', + 'asciicircum', + 'underscore', + 'quoteleft', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'braceleft', + 'bar', + 'braceright', + 'asciitilde', + 'exclamdown', + 'cent', + 'sterling', + 'fraction', + 'yen', + 'florin', + 'section', + 'currency', + 'quotesingle', + 'quotedblleft', + 'guillemotleft', + 'guilsinglleft', + 'guilsinglright', + 'fi', + 'fl', + 'endash', + 'dagger', + 'daggerdbl', + 'periodcentered', + 'paragraph', + 'bullet', + 'quotesinglbase', + 'quotedblbase', + 'quotedblright', + 'guillemotright', + 'ellipsis', + 'perthousand', + 'questiondown', + 'grave', + 'acute', + 'circumflex', + 'tilde', + 'macron', + 'breve', + 'dotaccent', + 'dieresis', + 'ring', + 'cedilla', + 'hungarumlaut', + 'ogonek', + 'caron', + 'emdash', + 'AE', + 'ordfeminine', + 'Lslash', + 'Oslash', + 'OE', + 'ordmasculine', + 'ae', + 'dotlessi', + 'lslash', + 'oslash', + 'oe', + 'germandbls', + 'onesuperior', + 'logicalnot', + 'mu', + 'trademark', + 'Eth', + 'onehalf', + 'plusminus', + 'Thorn', + 'onequarter', + 'divide', + 'brokenbar', + 'degree', + 'thorn', + 'threequarters', + 'twosuperior', + 'registered', + 'minus', + 'eth', + 'multiply', + 'threesuperior', + 'copyright', + 'Aacute', + 'Acircumflex', + 'Adieresis', + 'Agrave', + 'Aring', + 'Atilde', + 'Ccedilla', + 'Eacute', + 'Ecircumflex', + 'Edieresis', + 'Egrave', + 'Iacute', + 'Icircumflex', + 'Idieresis', + 'Igrave', + 'Ntilde', + 'Oacute', + 'Ocircumflex', + 'Odieresis', + 'Ograve', + 'Otilde', + 'Scaron', + 'Uacute', + 'Ucircumflex', + 'Udieresis', + 'Ugrave', + 'Yacute', + 'Ydieresis', + 'Zcaron', + 'aacute', + 'acircumflex', + 'adieresis', + 'agrave', + 'aring', + 'atilde', + 'ccedilla', + 'eacute', + 'ecircumflex', + 'edieresis', + 'egrave', + 'iacute', + 'icircumflex', + 'idieresis', + 'igrave', + 'ntilde', + 'oacute', + 'ocircumflex', + 'odieresis', + 'ograve', + 'otilde', + 'scaron', + 'uacute', + 'ucircumflex', + 'udieresis', + 'ugrave', + 'yacute', + 'ydieresis', + 'zcaron' +]; +var ExpertCharset = [ + '.notdef', + 'space', + 'exclamsmall', + 'Hungarumlautsmall', + 'dollaroldstyle', + 'dollarsuperior', + 'ampersandsmall', + 'Acutesmall', + 'parenleftsuperior', + 'parenrightsuperior', + 'twodotenleader', + 'onedotenleader', + 'comma', + 'hyphen', + 'period', + 'fraction', + 'zerooldstyle', + 'oneoldstyle', + 'twooldstyle', + 'threeoldstyle', + 'fouroldstyle', + 'fiveoldstyle', + 'sixoldstyle', + 'sevenoldstyle', + 'eightoldstyle', + 'nineoldstyle', + 'colon', + 'semicolon', + 'commasuperior', + 'threequartersemdash', + 'periodsuperior', + 'questionsmall', + 'asuperior', + 'bsuperior', + 'centsuperior', + 'dsuperior', + 'esuperior', + 'isuperior', + 'lsuperior', + 'msuperior', + 'nsuperior', + 'osuperior', + 'rsuperior', + 'ssuperior', + 'tsuperior', + 'ff', + 'fi', + 'fl', + 'ffi', + 'ffl', + 'parenleftinferior', + 'parenrightinferior', + 'Circumflexsmall', + 'hyphensuperior', + 'Gravesmall', + 'Asmall', + 'Bsmall', + 'Csmall', + 'Dsmall', + 'Esmall', + 'Fsmall', + 'Gsmall', + 'Hsmall', + 'Ismall', + 'Jsmall', + 'Ksmall', + 'Lsmall', + 'Msmall', + 'Nsmall', + 'Osmall', + 'Psmall', + 'Qsmall', + 'Rsmall', + 'Ssmall', + 'Tsmall', + 'Usmall', + 'Vsmall', + 'Wsmall', + 'Xsmall', + 'Ysmall', + 'Zsmall', + 'colonmonetary', + 'onefitted', + 'rupiah', + 'Tildesmall', + 'exclamdownsmall', + 'centoldstyle', + 'Lslashsmall', + 'Scaronsmall', + 'Zcaronsmall', + 'Dieresissmall', + 'Brevesmall', + 'Caronsmall', + 'Dotaccentsmall', + 'Macronsmall', + 'figuredash', + 'hypheninferior', + 'Ogoneksmall', + 'Ringsmall', + 'Cedillasmall', + 'onequarter', + 'onehalf', + 'threequarters', + 'questiondownsmall', + 'oneeighth', + 'threeeighths', + 'fiveeighths', + 'seveneighths', + 'onethird', + 'twothirds', + 'zerosuperior', + 'onesuperior', + 'twosuperior', + 'threesuperior', + 'foursuperior', + 'fivesuperior', + 'sixsuperior', + 'sevensuperior', + 'eightsuperior', + 'ninesuperior', + 'zeroinferior', + 'oneinferior', + 'twoinferior', + 'threeinferior', + 'fourinferior', + 'fiveinferior', + 'sixinferior', + 'seveninferior', + 'eightinferior', + 'nineinferior', + 'centinferior', + 'dollarinferior', + 'periodinferior', + 'commainferior', + 'Agravesmall', + 'Aacutesmall', + 'Acircumflexsmall', + 'Atildesmall', + 'Adieresissmall', + 'Aringsmall', + 'AEsmall', + 'Ccedillasmall', + 'Egravesmall', + 'Eacutesmall', + 'Ecircumflexsmall', + 'Edieresissmall', + 'Igravesmall', + 'Iacutesmall', + 'Icircumflexsmall', + 'Idieresissmall', + 'Ethsmall', + 'Ntildesmall', + 'Ogravesmall', + 'Oacutesmall', + 'Ocircumflexsmall', + 'Otildesmall', + 'Odieresissmall', + 'OEsmall', + 'Oslashsmall', + 'Ugravesmall', + 'Uacutesmall', + 'Ucircumflexsmall', + 'Udieresissmall', + 'Yacutesmall', + 'Thornsmall', + 'Ydieresissmall' +]; +var ExpertSubsetCharset = [ + '.notdef', + 'space', + 'dollaroldstyle', + 'dollarsuperior', + 'parenleftsuperior', + 'parenrightsuperior', + 'twodotenleader', + 'onedotenleader', + 'comma', + 'hyphen', + 'period', + 'fraction', + 'zerooldstyle', + 'oneoldstyle', + 'twooldstyle', + 'threeoldstyle', + 'fouroldstyle', + 'fiveoldstyle', + 'sixoldstyle', + 'sevenoldstyle', + 'eightoldstyle', + 'nineoldstyle', + 'colon', + 'semicolon', + 'commasuperior', + 'threequartersemdash', + 'periodsuperior', + 'asuperior', + 'bsuperior', + 'centsuperior', + 'dsuperior', + 'esuperior', + 'isuperior', + 'lsuperior', + 'msuperior', + 'nsuperior', + 'osuperior', + 'rsuperior', + 'ssuperior', + 'tsuperior', + 'ff', + 'fi', + 'fl', + 'ffi', + 'ffl', + 'parenleftinferior', + 'parenrightinferior', + 'hyphensuperior', + 'colonmonetary', + 'onefitted', + 'rupiah', + 'centoldstyle', + 'figuredash', + 'hypheninferior', + 'onequarter', + 'onehalf', + 'threequarters', + 'oneeighth', + 'threeeighths', + 'fiveeighths', + 'seveneighths', + 'onethird', + 'twothirds', + 'zerosuperior', + 'onesuperior', + 'twosuperior', + 'threesuperior', + 'foursuperior', + 'fivesuperior', + 'sixsuperior', + 'sevensuperior', + 'eightsuperior', + 'ninesuperior', + 'zeroinferior', + 'oneinferior', + 'twoinferior', + 'threeinferior', + 'fourinferior', + 'fiveinferior', + 'sixinferior', + 'seveninferior', + 'eightinferior', + 'nineinferior', + 'centinferior', + 'dollarinferior', + 'periodinferior', + 'commainferior' +]; +exports.ISOAdobeCharset = ISOAdobeCharset; +exports.ExpertCharset = ExpertCharset; +exports.ExpertSubsetCharset = ExpertSubsetCharset; + +/***/ }), +/* 23 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreStream = __w_pdfjs_require__(2); +var coreParser = __w_pdfjs_require__(5); +var Util = sharedUtil.Util; +var assert = sharedUtil.assert; +var warn = sharedUtil.warn; +var error = sharedUtil.error; +var isInt = sharedUtil.isInt; +var isString = sharedUtil.isString; +var MissingDataException = sharedUtil.MissingDataException; +var CMapCompressionType = sharedUtil.CMapCompressionType; +var isEOF = corePrimitives.isEOF; +var isName = corePrimitives.isName; +var isCmd = corePrimitives.isCmd; +var isStream = corePrimitives.isStream; +var Stream = coreStream.Stream; +var Lexer = coreParser.Lexer; +var BUILT_IN_CMAPS = [ + 'Adobe-GB1-UCS2', + 'Adobe-CNS1-UCS2', + 'Adobe-Japan1-UCS2', + 'Adobe-Korea1-UCS2', + '78-EUC-H', + '78-EUC-V', + '78-H', + '78-RKSJ-H', + '78-RKSJ-V', + '78-V', + '78ms-RKSJ-H', + '78ms-RKSJ-V', + '83pv-RKSJ-H', + '90ms-RKSJ-H', + '90ms-RKSJ-V', + '90msp-RKSJ-H', + '90msp-RKSJ-V', + '90pv-RKSJ-H', + '90pv-RKSJ-V', + 'Add-H', + 'Add-RKSJ-H', + 'Add-RKSJ-V', + 'Add-V', + 'Adobe-CNS1-0', + 'Adobe-CNS1-1', + 'Adobe-CNS1-2', + 'Adobe-CNS1-3', + 'Adobe-CNS1-4', + 'Adobe-CNS1-5', + 'Adobe-CNS1-6', + 'Adobe-GB1-0', + 'Adobe-GB1-1', + 'Adobe-GB1-2', + 'Adobe-GB1-3', + 'Adobe-GB1-4', + 'Adobe-GB1-5', + 'Adobe-Japan1-0', + 'Adobe-Japan1-1', + 'Adobe-Japan1-2', + 'Adobe-Japan1-3', + 'Adobe-Japan1-4', + 'Adobe-Japan1-5', + 'Adobe-Japan1-6', + 'Adobe-Korea1-0', + 'Adobe-Korea1-1', + 'Adobe-Korea1-2', + 'B5-H', + 'B5-V', + 'B5pc-H', + 'B5pc-V', + 'CNS-EUC-H', + 'CNS-EUC-V', + 'CNS1-H', + 'CNS1-V', + 'CNS2-H', + 'CNS2-V', + 'ETHK-B5-H', + 'ETHK-B5-V', + 'ETen-B5-H', + 'ETen-B5-V', + 'ETenms-B5-H', + 'ETenms-B5-V', + 'EUC-H', + 'EUC-V', + 'Ext-H', + 'Ext-RKSJ-H', + 'Ext-RKSJ-V', + 'Ext-V', + 'GB-EUC-H', + 'GB-EUC-V', + 'GB-H', + 'GB-V', + 'GBK-EUC-H', + 'GBK-EUC-V', + 'GBK2K-H', + 'GBK2K-V', + 'GBKp-EUC-H', + 'GBKp-EUC-V', + 'GBT-EUC-H', + 'GBT-EUC-V', + 'GBT-H', + 'GBT-V', + 'GBTpc-EUC-H', + 'GBTpc-EUC-V', + 'GBpc-EUC-H', + 'GBpc-EUC-V', + 'H', + 'HKdla-B5-H', + 'HKdla-B5-V', + 'HKdlb-B5-H', + 'HKdlb-B5-V', + 'HKgccs-B5-H', + 'HKgccs-B5-V', + 'HKm314-B5-H', + 'HKm314-B5-V', + 'HKm471-B5-H', + 'HKm471-B5-V', + 'HKscs-B5-H', + 'HKscs-B5-V', + 'Hankaku', + 'Hiragana', + 'KSC-EUC-H', + 'KSC-EUC-V', + 'KSC-H', + 'KSC-Johab-H', + 'KSC-Johab-V', + 'KSC-V', + 'KSCms-UHC-H', + 'KSCms-UHC-HW-H', + 'KSCms-UHC-HW-V', + 'KSCms-UHC-V', + 'KSCpc-EUC-H', + 'KSCpc-EUC-V', + 'Katakana', + 'NWP-H', + 'NWP-V', + 'RKSJ-H', + 'RKSJ-V', + 'Roman', + 'UniCNS-UCS2-H', + 'UniCNS-UCS2-V', + 'UniCNS-UTF16-H', + 'UniCNS-UTF16-V', + 'UniCNS-UTF32-H', + 'UniCNS-UTF32-V', + 'UniCNS-UTF8-H', + 'UniCNS-UTF8-V', + 'UniGB-UCS2-H', + 'UniGB-UCS2-V', + 'UniGB-UTF16-H', + 'UniGB-UTF16-V', + 'UniGB-UTF32-H', + 'UniGB-UTF32-V', + 'UniGB-UTF8-H', + 'UniGB-UTF8-V', + 'UniJIS-UCS2-H', + 'UniJIS-UCS2-HW-H', + 'UniJIS-UCS2-HW-V', + 'UniJIS-UCS2-V', + 'UniJIS-UTF16-H', + 'UniJIS-UTF16-V', + 'UniJIS-UTF32-H', + 'UniJIS-UTF32-V', + 'UniJIS-UTF8-H', + 'UniJIS-UTF8-V', + 'UniJIS2004-UTF16-H', + 'UniJIS2004-UTF16-V', + 'UniJIS2004-UTF32-H', + 'UniJIS2004-UTF32-V', + 'UniJIS2004-UTF8-H', + 'UniJIS2004-UTF8-V', + 'UniJISPro-UCS2-HW-V', + 'UniJISPro-UCS2-V', + 'UniJISPro-UTF8-V', + 'UniJISX0213-UTF32-H', + 'UniJISX0213-UTF32-V', + 'UniJISX02132004-UTF32-H', + 'UniJISX02132004-UTF32-V', + 'UniKS-UCS2-H', + 'UniKS-UCS2-V', + 'UniKS-UTF16-H', + 'UniKS-UTF16-V', + 'UniKS-UTF32-H', + 'UniKS-UTF32-V', + 'UniKS-UTF8-H', + 'UniKS-UTF8-V', + 'V', + 'WP-Symbol' +]; +var CMap = function CMapClosure() { + function CMap(builtInCMap) { + this.codespaceRanges = [ + [], + [], + [], + [] + ]; + this.numCodespaceRanges = 0; + this._map = []; + this.name = ''; + this.vertical = false; + this.useCMap = null; + this.builtInCMap = builtInCMap; + } + CMap.prototype = { + addCodespaceRange: function (n, low, high) { + this.codespaceRanges[n - 1].push(low, high); + this.numCodespaceRanges++; + }, + mapCidRange: function (low, high, dstLow) { + while (low <= high) { + this._map[low++] = dstLow++; + } + }, + mapBfRange: function (low, high, dstLow) { + var lastByte = dstLow.length - 1; + while (low <= high) { + this._map[low++] = dstLow; + dstLow = dstLow.substr(0, lastByte) + String.fromCharCode(dstLow.charCodeAt(lastByte) + 1); + } + }, + mapBfRangeToArray: function (low, high, array) { + var i = 0, ii = array.length; + while (low <= high && i < ii) { + this._map[low] = array[i++]; + ++low; + } + }, + mapOne: function (src, dst) { + this._map[src] = dst; + }, + lookup: function (code) { + return this._map[code]; + }, + contains: function (code) { + return this._map[code] !== undefined; + }, + forEach: function (callback) { + var map = this._map; + var length = map.length; + var i; + if (length <= 0x10000) { + for (i = 0; i < length; i++) { + if (map[i] !== undefined) { + callback(i, map[i]); + } + } + } else { + for (i in this._map) { + callback(i, map[i]); + } + } + }, + charCodeOf: function (value) { + return this._map.indexOf(value); + }, + getMap: function () { + return this._map; + }, + readCharCode: function (str, offset, out) { + var c = 0; + var codespaceRanges = this.codespaceRanges; + var codespaceRangesLen = this.codespaceRanges.length; + for (var n = 0; n < codespaceRangesLen; n++) { + c = (c << 8 | str.charCodeAt(offset + n)) >>> 0; + var codespaceRange = codespaceRanges[n]; + for (var k = 0, kk = codespaceRange.length; k < kk;) { + var low = codespaceRange[k++]; + var high = codespaceRange[k++]; + if (c >= low && c <= high) { + out.charcode = c; + out.length = n + 1; + return; + } + } + } + out.charcode = 0; + out.length = 1; + }, + get length() { + return this._map.length; + }, + get isIdentityCMap() { + if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) { + return false; + } + if (this._map.length !== 0x10000) { + return false; + } + for (var i = 0; i < 0x10000; i++) { + if (this._map[i] !== i) { + return false; + } + } + return true; + } + }; + return CMap; +}(); +var IdentityCMap = function IdentityCMapClosure() { + function IdentityCMap(vertical, n) { + CMap.call(this); + this.vertical = vertical; + this.addCodespaceRange(n, 0, 0xffff); + } + Util.inherit(IdentityCMap, CMap, {}); + IdentityCMap.prototype = { + addCodespaceRange: CMap.prototype.addCodespaceRange, + mapCidRange: function (low, high, dstLow) { + error('should not call mapCidRange'); + }, + mapBfRange: function (low, high, dstLow) { + error('should not call mapBfRange'); + }, + mapBfRangeToArray: function (low, high, array) { + error('should not call mapBfRangeToArray'); + }, + mapOne: function (src, dst) { + error('should not call mapCidOne'); + }, + lookup: function (code) { + return isInt(code) && code <= 0xffff ? code : undefined; + }, + contains: function (code) { + return isInt(code) && code <= 0xffff; + }, + forEach: function (callback) { + for (var i = 0; i <= 0xffff; i++) { + callback(i, i); + } + }, + charCodeOf: function (value) { + return isInt(value) && value <= 0xffff ? value : -1; + }, + getMap: function () { + var map = new Array(0x10000); + for (var i = 0; i <= 0xffff; i++) { + map[i] = i; + } + return map; + }, + readCharCode: CMap.prototype.readCharCode, + get length() { + return 0x10000; + }, + get isIdentityCMap() { + error('should not access .isIdentityCMap'); + } + }; + return IdentityCMap; +}(); +var BinaryCMapReader = function BinaryCMapReaderClosure() { + function hexToInt(a, size) { + var n = 0; + for (var i = 0; i <= size; i++) { + n = n << 8 | a[i]; + } + return n >>> 0; + } + function hexToStr(a, size) { + if (size === 1) { + return String.fromCharCode(a[0], a[1]); + } + if (size === 3) { + return String.fromCharCode(a[0], a[1], a[2], a[3]); + } + return String.fromCharCode.apply(null, a.subarray(0, size + 1)); + } + function addHex(a, b, size) { + var c = 0; + for (var i = size; i >= 0; i--) { + c += a[i] + b[i]; + a[i] = c & 255; + c >>= 8; + } + } + function incHex(a, size) { + var c = 1; + for (var i = size; i >= 0 && c > 0; i--) { + c += a[i]; + a[i] = c & 255; + c >>= 8; + } + } + var MAX_NUM_SIZE = 16; + var MAX_ENCODED_NUM_SIZE = 19; + function BinaryCMapStream(data) { + this.buffer = data; + this.pos = 0; + this.end = data.length; + this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE); + } + BinaryCMapStream.prototype = { + readByte: function () { + if (this.pos >= this.end) { + return -1; + } + return this.buffer[this.pos++]; + }, + readNumber: function () { + var n = 0; + var last; + do { + var b = this.readByte(); + if (b < 0) { + error('unexpected EOF in bcmap'); + } + last = !(b & 0x80); + n = n << 7 | b & 0x7F; + } while (!last); + return n; + }, + readSigned: function () { + var n = this.readNumber(); + return n & 1 ? ~(n >>> 1) : n >>> 1; + }, + readHex: function (num, size) { + num.set(this.buffer.subarray(this.pos, this.pos + size + 1)); + this.pos += size + 1; + }, + readHexNumber: function (num, size) { + var last; + var stack = this.tmpBuf, sp = 0; + do { + var b = this.readByte(); + if (b < 0) { + error('unexpected EOF in bcmap'); + } + last = !(b & 0x80); + stack[sp++] = b & 0x7F; + } while (!last); + var i = size, buffer = 0, bufferSize = 0; + while (i >= 0) { + while (bufferSize < 8 && stack.length > 0) { + buffer = stack[--sp] << bufferSize | buffer; + bufferSize += 7; + } + num[i] = buffer & 255; + i--; + buffer >>= 8; + bufferSize -= 8; + } + }, + readHexSigned: function (num, size) { + this.readHexNumber(num, size); + var sign = num[size] & 1 ? 255 : 0; + var c = 0; + for (var i = 0; i <= size; i++) { + c = (c & 1) << 8 | num[i]; + num[i] = c >> 1 ^ sign; + } + }, + readString: function () { + var len = this.readNumber(); + var s = ''; + for (var i = 0; i < len; i++) { + s += String.fromCharCode(this.readNumber()); + } + return s; + } + }; + function processBinaryCMap(data, cMap, extend) { + return new Promise(function (resolve, reject) { + var stream = new BinaryCMapStream(data); + var header = stream.readByte(); + cMap.vertical = !!(header & 1); + var useCMap = null; + var start = new Uint8Array(MAX_NUM_SIZE); + var end = new Uint8Array(MAX_NUM_SIZE); + var char = new Uint8Array(MAX_NUM_SIZE); + var charCode = new Uint8Array(MAX_NUM_SIZE); + var tmp = new Uint8Array(MAX_NUM_SIZE); + var code; + var b; + while ((b = stream.readByte()) >= 0) { + var type = b >> 5; + if (type === 7) { + switch (b & 0x1F) { + case 0: + stream.readString(); + break; + case 1: + useCMap = stream.readString(); + break; + } + continue; + } + var sequence = !!(b & 0x10); + var dataSize = b & 15; + assert(dataSize + 1 <= MAX_NUM_SIZE); + var ucs2DataSize = 1; + var subitemsCount = stream.readNumber(); + var i; + switch (type) { + case 0: + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize)); + for (i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize)); + } + break; + case 1: + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + for (i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + } + break; + case 2: + stream.readHex(char, dataSize); + code = stream.readNumber(); + cMap.mapOne(hexToInt(char, dataSize), code); + for (i = 1; i < subitemsCount; i++) { + incHex(char, dataSize); + if (!sequence) { + stream.readHexNumber(tmp, dataSize); + addHex(char, tmp, dataSize); + } + code = stream.readSigned() + (code + 1); + cMap.mapOne(hexToInt(char, dataSize), code); + } + break; + case 3: + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code); + for (i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + if (!sequence) { + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code); + } + break; + case 4: + stream.readHex(char, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize)); + for (i = 1; i < subitemsCount; i++) { + incHex(char, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(tmp, ucs2DataSize); + addHex(char, tmp, ucs2DataSize); + } + incHex(charCode, dataSize); + stream.readHexSigned(tmp, dataSize); + addHex(charCode, tmp, dataSize); + cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize)); + } + break; + case 5: + stream.readHex(start, ucs2DataSize); + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize)); + for (i = 1; i < subitemsCount; i++) { + incHex(end, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(start, ucs2DataSize); + addHex(start, end, ucs2DataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize)); + } + break; + default: + reject(new Error('processBinaryCMap: Unknown type: ' + type)); + return; + } + } + if (useCMap) { + resolve(extend(useCMap)); + return; + } + resolve(cMap); + }); + } + function BinaryCMapReader() { + } + BinaryCMapReader.prototype = { process: processBinaryCMap }; + return BinaryCMapReader; +}(); +var CMapFactory = function CMapFactoryClosure() { + function strToInt(str) { + var a = 0; + for (var i = 0; i < str.length; i++) { + a = a << 8 | str.charCodeAt(i); + } + return a >>> 0; + } + function expectString(obj) { + if (!isString(obj)) { + error('Malformed CMap: expected string.'); + } + } + function expectInt(obj) { + if (!isInt(obj)) { + error('Malformed CMap: expected int.'); + } + } + function parseBfChar(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endbfchar')) { + return; + } + expectString(obj); + var src = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + var dst = obj; + cMap.mapOne(src, dst); + } + } + function parseBfRange(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endbfrange')) { + return; + } + expectString(obj); + var low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + var high = strToInt(obj); + obj = lexer.getObj(); + if (isInt(obj) || isString(obj)) { + var dstLow = isInt(obj) ? String.fromCharCode(obj) : obj; + cMap.mapBfRange(low, high, dstLow); + } else if (isCmd(obj, '[')) { + obj = lexer.getObj(); + var array = []; + while (!isCmd(obj, ']') && !isEOF(obj)) { + array.push(obj); + obj = lexer.getObj(); + } + cMap.mapBfRangeToArray(low, high, array); + } else { + break; + } + } + error('Invalid bf range.'); + } + function parseCidChar(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endcidchar')) { + return; + } + expectString(obj); + var src = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + var dst = obj; + cMap.mapOne(src, dst); + } + } + function parseCidRange(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endcidrange')) { + return; + } + expectString(obj); + var low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + var high = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + var dstLow = obj; + cMap.mapCidRange(low, high, dstLow); + } + } + function parseCodespaceRange(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endcodespacerange')) { + return; + } + if (!isString(obj)) { + break; + } + var low = strToInt(obj); + obj = lexer.getObj(); + if (!isString(obj)) { + break; + } + var high = strToInt(obj); + cMap.addCodespaceRange(obj.length, low, high); + } + error('Invalid codespace range.'); + } + function parseWMode(cMap, lexer) { + var obj = lexer.getObj(); + if (isInt(obj)) { + cMap.vertical = !!obj; + } + } + function parseCMapName(cMap, lexer) { + var obj = lexer.getObj(); + if (isName(obj) && isString(obj.name)) { + cMap.name = obj.name; + } + } + function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) { + var previous; + var embededUseCMap; + objLoop: + while (true) { + try { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } else if (isName(obj)) { + if (obj.name === 'WMode') { + parseWMode(cMap, lexer); + } else if (obj.name === 'CMapName') { + parseCMapName(cMap, lexer); + } + previous = obj; + } else if (isCmd(obj)) { + switch (obj.cmd) { + case 'endcmap': + break objLoop; + case 'usecmap': + if (isName(previous)) { + embededUseCMap = previous.name; + } + break; + case 'begincodespacerange': + parseCodespaceRange(cMap, lexer); + break; + case 'beginbfchar': + parseBfChar(cMap, lexer); + break; + case 'begincidchar': + parseCidChar(cMap, lexer); + break; + case 'beginbfrange': + parseBfRange(cMap, lexer); + break; + case 'begincidrange': + parseCidRange(cMap, lexer); + break; + } + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Invalid cMap data: ' + ex); + continue; + } + } + if (!useCMap && embededUseCMap) { + useCMap = embededUseCMap; + } + if (useCMap) { + return extendCMap(cMap, fetchBuiltInCMap, useCMap); + } + return Promise.resolve(cMap); + } + function extendCMap(cMap, fetchBuiltInCMap, useCMap) { + return createBuiltInCMap(useCMap, fetchBuiltInCMap).then(function (newCMap) { + cMap.useCMap = newCMap; + if (cMap.numCodespaceRanges === 0) { + var useCodespaceRanges = cMap.useCMap.codespaceRanges; + for (var i = 0; i < useCodespaceRanges.length; i++) { + cMap.codespaceRanges[i] = useCodespaceRanges[i].slice(); + } + cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges; + } + cMap.useCMap.forEach(function (key, value) { + if (!cMap.contains(key)) { + cMap.mapOne(key, cMap.useCMap.lookup(key)); + } + }); + return cMap; + }); + } + function createBuiltInCMap(name, fetchBuiltInCMap) { + if (name === 'Identity-H') { + return Promise.resolve(new IdentityCMap(false, 2)); + } else if (name === 'Identity-V') { + return Promise.resolve(new IdentityCMap(true, 2)); + } + if (BUILT_IN_CMAPS.indexOf(name) === -1) { + return Promise.reject(new Error('Unknown cMap name: ' + name)); + } + assert(fetchBuiltInCMap, 'Built-in CMap parameters are not provided.'); + return fetchBuiltInCMap(name).then(function (data) { + var cMapData = data.cMapData, compressionType = data.compressionType; + var cMap = new CMap(true); + if (compressionType === CMapCompressionType.BINARY) { + return new BinaryCMapReader().process(cMapData, cMap, function (useCMap) { + return extendCMap(cMap, fetchBuiltInCMap, useCMap); + }); + } + assert(compressionType === CMapCompressionType.NONE, 'TODO: Only BINARY/NONE CMap compression is currently supported.'); + var lexer = new Lexer(new Stream(cMapData)); + return parseCMap(cMap, lexer, fetchBuiltInCMap, null); + }); + } + return { + create: function (params) { + var encoding = params.encoding; + var fetchBuiltInCMap = params.fetchBuiltInCMap; + var useCMap = params.useCMap; + if (isName(encoding)) { + return createBuiltInCMap(encoding.name, fetchBuiltInCMap); + } else if (isStream(encoding)) { + var cMap = new CMap(); + var lexer = new Lexer(encoding); + return parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap).then(function (parsedCMap) { + if (parsedCMap.isIdentityCMap) { + return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap); + } + return parsedCMap; + }); + } + return Promise.reject(new Error('Encoding required.')); + } + }; +}(); +exports.CMap = CMap; +exports.CMapFactory = CMapFactory; +exports.IdentityCMap = IdentityCMap; + +/***/ }), +/* 24 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreStream = __w_pdfjs_require__(2); +var coreObj = __w_pdfjs_require__(16); +var coreParser = __w_pdfjs_require__(5); +var coreCrypto = __w_pdfjs_require__(13); +var coreEvaluator = __w_pdfjs_require__(14); +var coreAnnotation = __w_pdfjs_require__(20); +var OPS = sharedUtil.OPS; +var MissingDataException = sharedUtil.MissingDataException; +var Util = sharedUtil.Util; +var assert = sharedUtil.assert; +var error = sharedUtil.error; +var info = sharedUtil.info; +var isArray = sharedUtil.isArray; +var isArrayBuffer = sharedUtil.isArrayBuffer; +var isNum = sharedUtil.isNum; +var isString = sharedUtil.isString; +var shadow = sharedUtil.shadow; +var stringToBytes = sharedUtil.stringToBytes; +var stringToPDFString = sharedUtil.stringToPDFString; +var warn = sharedUtil.warn; +var isSpace = sharedUtil.isSpace; +var Dict = corePrimitives.Dict; +var isDict = corePrimitives.isDict; +var isName = corePrimitives.isName; +var isStream = corePrimitives.isStream; +var NullStream = coreStream.NullStream; +var Stream = coreStream.Stream; +var StreamsSequenceStream = coreStream.StreamsSequenceStream; +var Catalog = coreObj.Catalog; +var ObjectLoader = coreObj.ObjectLoader; +var XRef = coreObj.XRef; +var Linearization = coreParser.Linearization; +var calculateMD5 = coreCrypto.calculateMD5; +var OperatorList = coreEvaluator.OperatorList; +var PartialEvaluator = coreEvaluator.PartialEvaluator; +var AnnotationFactory = coreAnnotation.AnnotationFactory; +var Page = function PageClosure() { + var DEFAULT_USER_UNIT = 1.0; + var LETTER_SIZE_MEDIABOX = [ + 0, + 0, + 612, + 792 + ]; + function isAnnotationRenderable(annotation, intent) { + return intent === 'display' && annotation.viewable || intent === 'print' && annotation.printable; + } + function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache, builtInCMapCache) { + this.pdfManager = pdfManager; + this.pageIndex = pageIndex; + this.pageDict = pageDict; + this.xref = xref; + this.ref = ref; + this.fontCache = fontCache; + this.builtInCMapCache = builtInCMapCache; + this.evaluatorOptions = pdfManager.evaluatorOptions; + this.resourcesPromise = null; + var uniquePrefix = 'p' + this.pageIndex + '_'; + var idCounters = { obj: 0 }; + this.idFactory = { + createObjId: function () { + return uniquePrefix + ++idCounters.obj; + } + }; + } + Page.prototype = { + getPageProp: function Page_getPageProp(key) { + return this.pageDict.get(key); + }, + getInheritedPageProp: function Page_getInheritedPageProp(key, getArray) { + var dict = this.pageDict, valueArray = null, loopCount = 0; + var MAX_LOOP_COUNT = 100; + getArray = getArray || false; + while (dict) { + var value = getArray ? dict.getArray(key) : dict.get(key); + if (value !== undefined) { + if (!valueArray) { + valueArray = []; + } + valueArray.push(value); + } + if (++loopCount > MAX_LOOP_COUNT) { + warn('getInheritedPageProp: maximum loop count exceeded for ' + key); + return valueArray ? valueArray[0] : undefined; + } + dict = dict.get('Parent'); + } + if (!valueArray) { + return undefined; + } + if (valueArray.length === 1 || !isDict(valueArray[0])) { + return valueArray[0]; + } + return Dict.merge(this.xref, valueArray); + }, + get content() { + return this.getPageProp('Contents'); + }, + get resources() { + return shadow(this, 'resources', this.getInheritedPageProp('Resources') || Dict.empty); + }, + get mediaBox() { + var mediaBox = this.getInheritedPageProp('MediaBox', true); + if (!isArray(mediaBox) || mediaBox.length !== 4) { + return shadow(this, 'mediaBox', LETTER_SIZE_MEDIABOX); + } + return shadow(this, 'mediaBox', mediaBox); + }, + get cropBox() { + var cropBox = this.getInheritedPageProp('CropBox', true); + if (!isArray(cropBox) || cropBox.length !== 4) { + return shadow(this, 'cropBox', this.mediaBox); + } + return shadow(this, 'cropBox', cropBox); + }, + get userUnit() { + var obj = this.getPageProp('UserUnit'); + if (!isNum(obj) || obj <= 0) { + obj = DEFAULT_USER_UNIT; + } + return shadow(this, 'userUnit', obj); + }, + get view() { + var mediaBox = this.mediaBox, cropBox = this.cropBox; + if (mediaBox === cropBox) { + return shadow(this, 'view', mediaBox); + } + var intersection = Util.intersect(cropBox, mediaBox); + return shadow(this, 'view', intersection || mediaBox); + }, + get rotate() { + var rotate = this.getInheritedPageProp('Rotate') || 0; + if (rotate % 90 !== 0) { + rotate = 0; + } else if (rotate >= 360) { + rotate = rotate % 360; + } else if (rotate < 0) { + rotate = (rotate % 360 + 360) % 360; + } + return shadow(this, 'rotate', rotate); + }, + getContentStream: function Page_getContentStream() { + var content = this.content; + var stream; + if (isArray(content)) { + var xref = this.xref; + var i, n = content.length; + var streams = []; + for (i = 0; i < n; ++i) { + streams.push(xref.fetchIfRef(content[i])); + } + stream = new StreamsSequenceStream(streams); + } else if (isStream(content)) { + stream = content; + } else { + stream = new NullStream(); + } + return stream; + }, + loadResources: function Page_loadResources(keys) { + if (!this.resourcesPromise) { + this.resourcesPromise = this.pdfManager.ensure(this, 'resources'); + } + return this.resourcesPromise.then(function resourceSuccess() { + var objectLoader = new ObjectLoader(this.resources.map, keys, this.xref); + return objectLoader.load(); + }.bind(this)); + }, + getOperatorList: function Page_getOperatorList(handler, task, intent, renderInteractiveForms) { + var self = this; + var pdfManager = this.pdfManager; + var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', []); + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'ColorSpace', + 'Pattern', + 'Shading', + 'XObject', + 'Font' + ]); + var partialEvaluator = new PartialEvaluator(pdfManager, this.xref, handler, this.pageIndex, this.idFactory, this.fontCache, this.builtInCMapCache, this.evaluatorOptions); + var dataPromises = Promise.all([ + contentStreamPromise, + resourcesPromise + ]); + var pageListPromise = dataPromises.then(function (data) { + var contentStream = data[0]; + var opList = new OperatorList(intent, handler, self.pageIndex); + handler.send('StartRenderPage', { + transparency: partialEvaluator.hasBlendModes(self.resources), + pageIndex: self.pageIndex, + intent: intent + }); + return partialEvaluator.getOperatorList(contentStream, task, self.resources, opList).then(function () { + return opList; + }); + }); + var annotationsPromise = pdfManager.ensure(this, 'annotations'); + return Promise.all([ + pageListPromise, + annotationsPromise + ]).then(function (datas) { + var pageOpList = datas[0]; + var annotations = datas[1]; + if (annotations.length === 0) { + pageOpList.flush(true); + return pageOpList; + } + var i, ii, opListPromises = []; + for (i = 0, ii = annotations.length; i < ii; i++) { + if (isAnnotationRenderable(annotations[i], intent)) { + opListPromises.push(annotations[i].getOperatorList(partialEvaluator, task, renderInteractiveForms)); + } + } + return Promise.all(opListPromises).then(function (opLists) { + pageOpList.addOp(OPS.beginAnnotations, []); + for (i = 0, ii = opLists.length; i < ii; i++) { + pageOpList.addOpList(opLists[i]); + } + pageOpList.addOp(OPS.endAnnotations, []); + pageOpList.flush(true); + return pageOpList; + }); + }); + }, + extractTextContent: function Page_extractTextContent(task, normalizeWhitespace, combineTextItems) { + var handler = { + on: function nullHandlerOn() { + }, + send: function nullHandlerSend() { + } + }; + var self = this; + var pdfManager = this.pdfManager; + var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', []); + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'XObject', + 'Font' + ]); + var dataPromises = Promise.all([ + contentStreamPromise, + resourcesPromise + ]); + return dataPromises.then(function (data) { + var contentStream = data[0]; + var partialEvaluator = new PartialEvaluator(pdfManager, self.xref, handler, self.pageIndex, self.idFactory, self.fontCache, self.builtInCMapCache, self.evaluatorOptions); + return partialEvaluator.getTextContent(contentStream, task, self.resources, null, normalizeWhitespace, combineTextItems); + }); + }, + getAnnotationsData: function Page_getAnnotationsData(intent) { + var annotations = this.annotations; + var annotationsData = []; + for (var i = 0, n = annotations.length; i < n; ++i) { + if (!intent || isAnnotationRenderable(annotations[i], intent)) { + annotationsData.push(annotations[i].data); + } + } + return annotationsData; + }, + get annotations() { + var annotations = []; + var annotationRefs = this.getInheritedPageProp('Annots') || []; + var annotationFactory = new AnnotationFactory(); + for (var i = 0, n = annotationRefs.length; i < n; ++i) { + var annotationRef = annotationRefs[i]; + var annotation = annotationFactory.create(this.xref, annotationRef, this.pdfManager, this.idFactory); + if (annotation) { + annotations.push(annotation); + } + } + return shadow(this, 'annotations', annotations); + } + }; + return Page; +}(); +var PDFDocument = function PDFDocumentClosure() { + var FINGERPRINT_FIRST_BYTES = 1024; + var EMPTY_FINGERPRINT = '\x00\x00\x00\x00\x00\x00\x00' + '\x00\x00\x00\x00\x00\x00\x00\x00\x00'; + function PDFDocument(pdfManager, arg) { + var stream; + if (isStream(arg)) { + stream = arg; + } else if (isArrayBuffer(arg)) { + stream = new Stream(arg); + } else { + error('PDFDocument: Unknown argument type'); + } + assert(stream.length > 0, 'stream must have data'); + this.pdfManager = pdfManager; + this.stream = stream; + this.xref = new XRef(stream, pdfManager); + } + function find(stream, needle, limit, backwards) { + var pos = stream.pos; + var end = stream.end; + var strBuf = []; + if (pos + limit > end) { + limit = end - pos; + } + for (var n = 0; n < limit; ++n) { + strBuf.push(String.fromCharCode(stream.getByte())); + } + var str = strBuf.join(''); + stream.pos = pos; + var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle); + if (index === -1) { + return false; + } + stream.pos += index; + return true; + } + var DocumentInfoValidators = { + get entries() { + return shadow(this, 'entries', { + Title: isString, + Author: isString, + Subject: isString, + Keywords: isString, + Creator: isString, + Producer: isString, + CreationDate: isString, + ModDate: isString, + Trapped: isName + }); + } + }; + PDFDocument.prototype = { + parse: function PDFDocument_parse(recoveryMode) { + this.setup(recoveryMode); + var version = this.catalog.catDict.get('Version'); + if (isName(version)) { + this.pdfFormatVersion = version.name; + } + try { + this.acroForm = this.catalog.catDict.get('AcroForm'); + if (this.acroForm) { + this.xfa = this.acroForm.get('XFA'); + var fields = this.acroForm.get('Fields'); + if ((!fields || !isArray(fields) || fields.length === 0) && !this.xfa) { + this.acroForm = null; + } + } + } catch (ex) { + info('Something wrong with AcroForm entry'); + this.acroForm = null; + } + }, + get linearization() { + var linearization = null; + if (this.stream.length) { + try { + linearization = Linearization.create(this.stream); + } catch (err) { + if (err instanceof MissingDataException) { + throw err; + } + info(err); + } + } + return shadow(this, 'linearization', linearization); + }, + get startXRef() { + var stream = this.stream; + var startXRef = 0; + var linearization = this.linearization; + if (linearization) { + stream.reset(); + if (find(stream, 'endobj', 1024)) { + startXRef = stream.pos + 6; + } + } else { + var step = 1024; + var found = false, pos = stream.end; + while (!found && pos > 0) { + pos -= step - 'startxref'.length; + if (pos < 0) { + pos = 0; + } + stream.pos = pos; + found = find(stream, 'startxref', step, true); + } + if (found) { + stream.skip(9); + var ch; + do { + ch = stream.getByte(); + } while (isSpace(ch)); + var str = ''; + while (ch >= 0x20 && ch <= 0x39) { + str += String.fromCharCode(ch); + ch = stream.getByte(); + } + startXRef = parseInt(str, 10); + if (isNaN(startXRef)) { + startXRef = 0; + } + } + } + return shadow(this, 'startXRef', startXRef); + }, + get mainXRefEntriesOffset() { + var mainXRefEntriesOffset = 0; + var linearization = this.linearization; + if (linearization) { + mainXRefEntriesOffset = linearization.mainXRefEntriesOffset; + } + return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset); + }, + checkHeader: function PDFDocument_checkHeader() { + var stream = this.stream; + stream.reset(); + if (find(stream, '%PDF-', 1024)) { + stream.moveStart(); + var MAX_VERSION_LENGTH = 12; + var version = '', ch; + while ((ch = stream.getByte()) > 0x20) { + if (version.length >= MAX_VERSION_LENGTH) { + break; + } + version += String.fromCharCode(ch); + } + if (!this.pdfFormatVersion) { + this.pdfFormatVersion = version.substring(5); + } + return; + } + }, + parseStartXRef: function PDFDocument_parseStartXRef() { + var startXRef = this.startXRef; + this.xref.setStartXRef(startXRef); + }, + setup: function PDFDocument_setup(recoveryMode) { + this.xref.parse(recoveryMode); + var self = this; + var pageFactory = { + createPage: function (pageIndex, dict, ref, fontCache, builtInCMapCache) { + return new Page(self.pdfManager, self.xref, pageIndex, dict, ref, fontCache, builtInCMapCache); + } + }; + this.catalog = new Catalog(this.pdfManager, this.xref, pageFactory); + }, + get numPages() { + var linearization = this.linearization; + var num = linearization ? linearization.numPages : this.catalog.numPages; + return shadow(this, 'numPages', num); + }, + get documentInfo() { + var docInfo = { + PDFFormatVersion: this.pdfFormatVersion, + IsAcroFormPresent: !!this.acroForm, + IsXFAPresent: !!this.xfa + }; + var infoDict; + try { + infoDict = this.xref.trailer.get('Info'); + } catch (err) { + info('The document information dictionary is invalid.'); + } + if (infoDict) { + var validEntries = DocumentInfoValidators.entries; + for (var key in validEntries) { + if (infoDict.has(key)) { + var value = infoDict.get(key); + if (validEntries[key](value)) { + docInfo[key] = typeof value !== 'string' ? value : stringToPDFString(value); + } else { + info('Bad value in document info for "' + key + '"'); + } + } + } + } + return shadow(this, 'documentInfo', docInfo); + }, + get fingerprint() { + var xref = this.xref, hash, fileID = ''; + var idArray = xref.trailer.get('ID'); + if (idArray && isArray(idArray) && idArray[0] && isString(idArray[0]) && idArray[0] !== EMPTY_FINGERPRINT) { + hash = stringToBytes(idArray[0]); + } else { + if (this.stream.ensureRange) { + this.stream.ensureRange(0, Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end)); + } + hash = calculateMD5(this.stream.bytes.subarray(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES); + } + for (var i = 0, n = hash.length; i < n; i++) { + var hex = hash[i].toString(16); + fileID += hex.length === 1 ? '0' + hex : hex; + } + return shadow(this, 'fingerprint', fileID); + }, + getPage: function PDFDocument_getPage(pageIndex) { + return this.catalog.getPage(pageIndex); + }, + cleanup: function PDFDocument_cleanup() { + return this.catalog.cleanup(); + } + }; + return PDFDocument; +}(); +exports.Page = Page; +exports.PDFDocument = PDFDocument; + +/***/ }), +/* 25 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var coreStream = __w_pdfjs_require__(2); +var coreGlyphList = __w_pdfjs_require__(7); +var coreEncodings = __w_pdfjs_require__(4); +var coreCFFParser = __w_pdfjs_require__(11); +var Util = sharedUtil.Util; +var bytesToString = sharedUtil.bytesToString; +var error = sharedUtil.error; +var Stream = coreStream.Stream; +var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode; +var StandardEncoding = coreEncodings.StandardEncoding; +var CFFParser = coreCFFParser.CFFParser; +var FontRendererFactory = function FontRendererFactoryClosure() { + function getLong(data, offset) { + return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]; + } + function getUshort(data, offset) { + return data[offset] << 8 | data[offset + 1]; + } + function parseCmap(data, start, end) { + var offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : getLong(data, start + 16); + var format = getUshort(data, start + offset); + var ranges, p, i; + if (format === 4) { + getUshort(data, start + offset + 2); + var segCount = getUshort(data, start + offset + 6) >> 1; + p = start + offset + 14; + ranges = []; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i] = { end: getUshort(data, p) }; + } + p += 2; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].start = getUshort(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].idDelta = getUshort(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + var idOffset = getUshort(data, p); + if (idOffset === 0) { + continue; + } + ranges[i].ids = []; + for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) { + ranges[i].ids[j] = getUshort(data, p + idOffset); + idOffset += 2; + } + } + return ranges; + } else if (format === 12) { + getLong(data, start + offset + 4); + var groups = getLong(data, start + offset + 12); + p = start + offset + 16; + ranges = []; + for (i = 0; i < groups; i++) { + ranges.push({ + start: getLong(data, p), + end: getLong(data, p + 4), + idDelta: getLong(data, p + 8) - getLong(data, p) + }); + p += 12; + } + return ranges; + } + error('not supported cmap: ' + format); + } + function parseCff(data, start, end, seacAnalysisEnabled) { + var properties = {}; + var parser = new CFFParser(new Stream(data, start, end - start), properties, seacAnalysisEnabled); + var cff = parser.parse(); + return { + glyphs: cff.charStrings.objects, + subrs: cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && cff.topDict.privateDict.subrsIndex.objects, + gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects + }; + } + function parseGlyfTable(glyf, loca, isGlyphLocationsLong) { + var itemSize, itemDecode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return data[offset] << 9 | data[offset + 1] << 1; + }; + } + var glyphs = []; + var startOffset = itemDecode(loca, 0); + for (var j = itemSize; j < loca.length; j += itemSize) { + var endOffset = itemDecode(loca, j); + glyphs.push(glyf.subarray(startOffset, endOffset)); + startOffset = endOffset; + } + return glyphs; + } + function lookupCmap(ranges, unicode) { + var code = unicode.charCodeAt(0), gid = 0; + var l = 0, r = ranges.length - 1; + while (l < r) { + var c = l + r + 1 >> 1; + if (code < ranges[c].start) { + r = c - 1; + } else { + l = c; + } + } + if (ranges[l].start <= code && code <= ranges[l].end) { + gid = ranges[l].idDelta + (ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code) & 0xFFFF; + } + return { + charCode: code, + glyphId: gid + }; + } + function compileGlyf(code, cmds, font) { + function moveTo(x, y) { + cmds.push({ + cmd: 'moveTo', + args: [ + x, + y + ] + }); + } + function lineTo(x, y) { + cmds.push({ + cmd: 'lineTo', + args: [ + x, + y + ] + }); + } + function quadraticCurveTo(xa, ya, x, y) { + cmds.push({ + cmd: 'quadraticCurveTo', + args: [ + xa, + ya, + x, + y + ] + }); + } + var i = 0; + var numberOfContours = (code[i] << 24 | code[i + 1] << 16) >> 16; + var flags; + var x = 0, y = 0; + i += 10; + if (numberOfContours < 0) { + do { + flags = code[i] << 8 | code[i + 1]; + var glyphIndex = code[i + 2] << 8 | code[i + 3]; + i += 4; + var arg1, arg2; + if (flags & 0x01) { + arg1 = (code[i] << 24 | code[i + 1] << 16) >> 16; + arg2 = (code[i + 2] << 24 | code[i + 3] << 16) >> 16; + i += 4; + } else { + arg1 = code[i++]; + arg2 = code[i++]; + } + if (flags & 0x02) { + x = arg1; + y = arg2; + } else { + x = 0; + y = 0; + } + var scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0; + if (flags & 0x08) { + scaleX = scaleY = (code[i] << 24 | code[i + 1] << 16) / 1073741824; + i += 2; + } else if (flags & 0x40) { + scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824; + scaleY = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824; + i += 4; + } else if (flags & 0x80) { + scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824; + scale01 = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824; + scale10 = (code[i + 4] << 24 | code[i + 5] << 16) / 1073741824; + scaleY = (code[i + 6] << 24 | code[i + 7] << 16) / 1073741824; + i += 8; + } + var subglyph = font.glyphs[glyphIndex]; + if (subglyph) { + cmds.push({ cmd: 'save' }); + cmds.push({ + cmd: 'transform', + args: [ + scaleX, + scale01, + scale10, + scaleY, + x, + y + ] + }); + compileGlyf(subglyph, cmds, font); + cmds.push({ cmd: 'restore' }); + } + } while (flags & 0x20); + } else { + var endPtsOfContours = []; + var j, jj; + for (j = 0; j < numberOfContours; j++) { + endPtsOfContours.push(code[i] << 8 | code[i + 1]); + i += 2; + } + var instructionLength = code[i] << 8 | code[i + 1]; + i += 2 + instructionLength; + var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1; + var points = []; + while (points.length < numberOfPoints) { + flags = code[i++]; + var repeat = 1; + if (flags & 0x08) { + repeat += code[i++]; + } + while (repeat-- > 0) { + points.push({ flags: flags }); + } + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x12) { + case 0x00: + x += (code[i] << 24 | code[i + 1] << 16) >> 16; + i += 2; + break; + case 0x02: + x -= code[i++]; + break; + case 0x12: + x += code[i++]; + break; + } + points[j].x = x; + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x24) { + case 0x00: + y += (code[i] << 24 | code[i + 1] << 16) >> 16; + i += 2; + break; + case 0x04: + y -= code[i++]; + break; + case 0x24: + y += code[i++]; + break; + } + points[j].y = y; + } + var startPoint = 0; + for (i = 0; i < numberOfContours; i++) { + var endPoint = endPtsOfContours[i]; + var contour = points.slice(startPoint, endPoint + 1); + if (contour[0].flags & 1) { + contour.push(contour[0]); + } else if (contour[contour.length - 1].flags & 1) { + contour.unshift(contour[contour.length - 1]); + } else { + var p = { + flags: 1, + x: (contour[0].x + contour[contour.length - 1].x) / 2, + y: (contour[0].y + contour[contour.length - 1].y) / 2 + }; + contour.unshift(p); + contour.push(p); + } + moveTo(contour[0].x, contour[0].y); + for (j = 1, jj = contour.length; j < jj; j++) { + if (contour[j].flags & 1) { + lineTo(contour[j].x, contour[j].y); + } else if (contour[j + 1].flags & 1) { + quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y); + j++; + } else { + quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2); + } + } + startPoint = endPoint + 1; + } + } + } + function compileCharString(code, cmds, font) { + var stack = []; + var x = 0, y = 0; + var stems = 0; + function moveTo(x, y) { + cmds.push({ + cmd: 'moveTo', + args: [ + x, + y + ] + }); + } + function lineTo(x, y) { + cmds.push({ + cmd: 'lineTo', + args: [ + x, + y + ] + }); + } + function bezierCurveTo(x1, y1, x2, y2, x, y) { + cmds.push({ + cmd: 'bezierCurveTo', + args: [ + x1, + y1, + x2, + y2, + x, + y + ] + }); + } + function parse(code) { + var i = 0; + while (i < code.length) { + var stackClean = false; + var v = code[i++]; + var xa, xb, ya, yb, y1, y2, y3, n, subrCode; + switch (v) { + case 1: + stems += stack.length >> 1; + stackClean = true; + break; + case 3: + stems += stack.length >> 1; + stackClean = true; + break; + case 4: + y += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 5: + while (stack.length > 0) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + break; + case 6: + while (stack.length > 0) { + x += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + y += stack.shift(); + lineTo(x, y); + } + break; + case 7: + while (stack.length > 0) { + y += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + x += stack.shift(); + lineTo(x, y); + } + break; + case 8: + while (stack.length > 0) { + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 10: + n = stack.pop() + font.subrsBias; + subrCode = font.subrs[n]; + if (subrCode) { + parse(subrCode); + } + break; + case 11: + return; + case 12: + v = code[i++]; + switch (v) { + case 34: + xa = x + stack.shift(); + xb = xa + stack.shift(); + y1 = y + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y, xb, y1, x, y1); + xa = x + stack.shift(); + xb = xa + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y, x, y); + break; + case 35: + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + stack.pop(); + break; + case 36: + xa = x + stack.shift(); + y1 = y + stack.shift(); + xb = xa + stack.shift(); + y2 = y1 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y2, x, y2); + xa = x + stack.shift(); + xb = xa + stack.shift(); + y3 = y2 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y2, xb, y3, x, y); + break; + case 37: + var x0 = x, y0 = y; + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb; + y = yb; + if (Math.abs(x - x0) > Math.abs(y - y0)) { + x += stack.shift(); + } else { + y += stack.shift(); + } + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + default: + error('unknown operator: 12 ' + v); + } + break; + case 14: + if (stack.length >= 4) { + var achar = stack.pop(); + var bchar = stack.pop(); + y = stack.pop(); + x = stack.pop(); + cmds.push({ cmd: 'save' }); + cmds.push({ + cmd: 'translate', + args: [ + x, + y + ] + }); + var cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]])); + compileCharString(font.glyphs[cmap.glyphId], cmds, font); + cmds.push({ cmd: 'restore' }); + cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[bchar]])); + compileCharString(font.glyphs[cmap.glyphId], cmds, font); + } + return; + case 18: + stems += stack.length >> 1; + stackClean = true; + break; + case 19: + stems += stack.length >> 1; + i += stems + 7 >> 3; + stackClean = true; + break; + case 20: + stems += stack.length >> 1; + i += stems + 7 >> 3; + stackClean = true; + break; + case 21: + y += stack.pop(); + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 22: + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 23: + stems += stack.length >> 1; + stackClean = true; + break; + case 24: + while (stack.length > 2) { + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + break; + case 25: + while (stack.length > 6) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + case 26: + if (stack.length % 2) { + x += stack.shift(); + } + while (stack.length > 0) { + xa = x; + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb; + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 27: + if (stack.length % 2) { + y += stack.shift(); + } + while (stack.length > 0) { + xa = x + stack.shift(); + ya = y; + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb; + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 28: + stack.push((code[i] << 24 | code[i + 1] << 16) >> 16); + i += 2; + break; + case 29: + n = stack.pop() + font.gsubrsBias; + subrCode = font.gsubrs[n]; + if (subrCode) { + parse(subrCode); + } + break; + case 30: + while (stack.length > 0) { + xa = x; + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + xa = x + stack.shift(); + ya = y; + xb = xa + stack.shift(); + yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 31: + while (stack.length > 0) { + xa = x + stack.shift(); + ya = y; + xb = xa + stack.shift(); + yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + xa = x; + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + default: + if (v < 32) { + error('unknown operator: ' + v); + } + if (v < 247) { + stack.push(v - 139); + } else if (v < 251) { + stack.push((v - 247) * 256 + code[i++] + 108); + } else if (v < 255) { + stack.push(-(v - 251) * 256 - code[i++] - 108); + } else { + stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3]) / 65536); + i += 4; + } + break; + } + if (stackClean) { + stack.length = 0; + } + } + } + parse(code); + } + var noop = ''; + function CompiledFont(fontMatrix) { + this.compiledGlyphs = Object.create(null); + this.compiledCharCodeToGlyphId = Object.create(null); + this.fontMatrix = fontMatrix; + } + CompiledFont.prototype = { + getPathJs: function (unicode) { + var cmap = lookupCmap(this.cmap, unicode); + var fn = this.compiledGlyphs[cmap.glyphId]; + if (!fn) { + fn = this.compileGlyph(this.glyphs[cmap.glyphId]); + this.compiledGlyphs[cmap.glyphId] = fn; + } + if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) { + this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId; + } + return fn; + }, + compileGlyph: function (code) { + if (!code || code.length === 0 || code[0] === 14) { + return noop; + } + var cmds = []; + cmds.push({ cmd: 'save' }); + cmds.push({ + cmd: 'transform', + args: this.fontMatrix.slice() + }); + cmds.push({ + cmd: 'scale', + args: [ + 'size', + '-size' + ] + }); + this.compileGlyphImpl(code, cmds); + cmds.push({ cmd: 'restore' }); + return cmds; + }, + compileGlyphImpl: function () { + error('Children classes should implement this.'); + }, + hasBuiltPath: function (unicode) { + var cmap = lookupCmap(this.cmap, unicode); + return this.compiledGlyphs[cmap.glyphId] !== undefined && this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined; + } + }; + function TrueTypeCompiled(glyphs, cmap, fontMatrix) { + fontMatrix = fontMatrix || [ + 0.000488, + 0, + 0, + 0.000488, + 0, + 0 + ]; + CompiledFont.call(this, fontMatrix); + this.glyphs = glyphs; + this.cmap = cmap; + } + Util.inherit(TrueTypeCompiled, CompiledFont, { + compileGlyphImpl: function (code, cmds) { + compileGlyf(code, cmds, this); + } + }); + function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) { + fontMatrix = fontMatrix || [ + 0.001, + 0, + 0, + 0.001, + 0, + 0 + ]; + CompiledFont.call(this, fontMatrix); + this.glyphs = cffInfo.glyphs; + this.gsubrs = cffInfo.gsubrs || []; + this.subrs = cffInfo.subrs || []; + this.cmap = cmap; + this.glyphNameMap = glyphNameMap || getGlyphsUnicode(); + this.gsubrsBias = this.gsubrs.length < 1240 ? 107 : this.gsubrs.length < 33900 ? 1131 : 32768; + this.subrsBias = this.subrs.length < 1240 ? 107 : this.subrs.length < 33900 ? 1131 : 32768; + } + Util.inherit(Type2Compiled, CompiledFont, { + compileGlyphImpl: function (code, cmds) { + compileCharString(code, cmds, this); + } + }); + return { + create: function FontRendererFactory_create(font, seacAnalysisEnabled) { + var data = new Uint8Array(font.data); + var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm; + var numTables = getUshort(data, 4); + for (var i = 0, p = 12; i < numTables; i++, p += 16) { + var tag = bytesToString(data.subarray(p, p + 4)); + var offset = getLong(data, p + 8); + var length = getLong(data, p + 12); + switch (tag) { + case 'cmap': + cmap = parseCmap(data, offset, offset + length); + break; + case 'glyf': + glyf = data.subarray(offset, offset + length); + break; + case 'loca': + loca = data.subarray(offset, offset + length); + break; + case 'head': + unitsPerEm = getUshort(data, offset + 18); + indexToLocFormat = getUshort(data, offset + 50); + break; + case 'CFF ': + cff = parseCff(data, offset, offset + length, seacAnalysisEnabled); + break; + } + } + if (glyf) { + var fontMatrix = !unitsPerEm ? font.fontMatrix : [ + 1 / unitsPerEm, + 0, + 0, + 1 / unitsPerEm, + 0, + 0 + ]; + return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix); + } + return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap); + } + }; +}(); +exports.FontRendererFactory = FontRendererFactory; + +/***/ }), +/* 26 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreStream = __w_pdfjs_require__(2); +var coreGlyphList = __w_pdfjs_require__(7); +var coreFontRenderer = __w_pdfjs_require__(25); +var coreEncodings = __w_pdfjs_require__(4); +var coreStandardFonts = __w_pdfjs_require__(17); +var coreUnicode = __w_pdfjs_require__(18); +var coreType1Parser = __w_pdfjs_require__(35); +var coreCFFParser = __w_pdfjs_require__(11); +var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX; +var FontType = sharedUtil.FontType; +var assert = sharedUtil.assert; +var bytesToString = sharedUtil.bytesToString; +var error = sharedUtil.error; +var info = sharedUtil.info; +var isArray = sharedUtil.isArray; +var isInt = sharedUtil.isInt; +var isNum = sharedUtil.isNum; +var readUint32 = sharedUtil.readUint32; +var shadow = sharedUtil.shadow; +var string32 = sharedUtil.string32; +var warn = sharedUtil.warn; +var MissingDataException = sharedUtil.MissingDataException; +var isSpace = sharedUtil.isSpace; +var Stream = coreStream.Stream; +var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode; +var getDingbatsGlyphsUnicode = coreGlyphList.getDingbatsGlyphsUnicode; +var FontRendererFactory = coreFontRenderer.FontRendererFactory; +var StandardEncoding = coreEncodings.StandardEncoding; +var MacRomanEncoding = coreEncodings.MacRomanEncoding; +var SymbolSetEncoding = coreEncodings.SymbolSetEncoding; +var ZapfDingbatsEncoding = coreEncodings.ZapfDingbatsEncoding; +var getEncoding = coreEncodings.getEncoding; +var getStdFontMap = coreStandardFonts.getStdFontMap; +var getNonStdFontMap = coreStandardFonts.getNonStdFontMap; +var getGlyphMapForStandardFonts = coreStandardFonts.getGlyphMapForStandardFonts; +var getSupplementalGlyphMapForArialBlack = coreStandardFonts.getSupplementalGlyphMapForArialBlack; +var getUnicodeRangeFor = coreUnicode.getUnicodeRangeFor; +var mapSpecialUnicodeValues = coreUnicode.mapSpecialUnicodeValues; +var getUnicodeForGlyph = coreUnicode.getUnicodeForGlyph; +var Type1Parser = coreType1Parser.Type1Parser; +var CFFStandardStrings = coreCFFParser.CFFStandardStrings; +var CFFParser = coreCFFParser.CFFParser; +var CFFCompiler = coreCFFParser.CFFCompiler; +var CFF = coreCFFParser.CFF; +var CFFHeader = coreCFFParser.CFFHeader; +var CFFTopDict = coreCFFParser.CFFTopDict; +var CFFPrivateDict = coreCFFParser.CFFPrivateDict; +var CFFStrings = coreCFFParser.CFFStrings; +var CFFIndex = coreCFFParser.CFFIndex; +var CFFCharset = coreCFFParser.CFFCharset; +var PRIVATE_USE_OFFSET_START = 0xE000; +var PRIVATE_USE_OFFSET_END = 0xF8FF; +var SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = false; +var PDF_GLYPH_SPACE_UNITS = 1000; +var SEAC_ANALYSIS_ENABLED = false; +var FontFlags = { + FixedPitch: 1, + Serif: 2, + Symbolic: 4, + Script: 8, + Nonsymbolic: 32, + Italic: 64, + AllCap: 65536, + SmallCap: 131072, + ForceBold: 262144 +}; +var MacStandardGlyphOrdering = [ + '.notdef', + '.null', + 'nonmarkingreturn', + 'space', + 'exclam', + 'quotedbl', + 'numbersign', + 'dollar', + 'percent', + 'ampersand', + 'quotesingle', + 'parenleft', + 'parenright', + 'asterisk', + 'plus', + 'comma', + 'hyphen', + 'period', + 'slash', + 'zero', + 'one', + 'two', + 'three', + 'four', + 'five', + 'six', + 'seven', + 'eight', + 'nine', + 'colon', + 'semicolon', + 'less', + 'equal', + 'greater', + 'question', + 'at', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + 'bracketleft', + 'backslash', + 'bracketright', + 'asciicircum', + 'underscore', + 'grave', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'braceleft', + 'bar', + 'braceright', + 'asciitilde', + 'Adieresis', + 'Aring', + 'Ccedilla', + 'Eacute', + 'Ntilde', + 'Odieresis', + 'Udieresis', + 'aacute', + 'agrave', + 'acircumflex', + 'adieresis', + 'atilde', + 'aring', + 'ccedilla', + 'eacute', + 'egrave', + 'ecircumflex', + 'edieresis', + 'iacute', + 'igrave', + 'icircumflex', + 'idieresis', + 'ntilde', + 'oacute', + 'ograve', + 'ocircumflex', + 'odieresis', + 'otilde', + 'uacute', + 'ugrave', + 'ucircumflex', + 'udieresis', + 'dagger', + 'degree', + 'cent', + 'sterling', + 'section', + 'bullet', + 'paragraph', + 'germandbls', + 'registered', + 'copyright', + 'trademark', + 'acute', + 'dieresis', + 'notequal', + 'AE', + 'Oslash', + 'infinity', + 'plusminus', + 'lessequal', + 'greaterequal', + 'yen', + 'mu', + 'partialdiff', + 'summation', + 'product', + 'pi', + 'integral', + 'ordfeminine', + 'ordmasculine', + 'Omega', + 'ae', + 'oslash', + 'questiondown', + 'exclamdown', + 'logicalnot', + 'radical', + 'florin', + 'approxequal', + 'Delta', + 'guillemotleft', + 'guillemotright', + 'ellipsis', + 'nonbreakingspace', + 'Agrave', + 'Atilde', + 'Otilde', + 'OE', + 'oe', + 'endash', + 'emdash', + 'quotedblleft', + 'quotedblright', + 'quoteleft', + 'quoteright', + 'divide', + 'lozenge', + 'ydieresis', + 'Ydieresis', + 'fraction', + 'currency', + 'guilsinglleft', + 'guilsinglright', + 'fi', + 'fl', + 'daggerdbl', + 'periodcentered', + 'quotesinglbase', + 'quotedblbase', + 'perthousand', + 'Acircumflex', + 'Ecircumflex', + 'Aacute', + 'Edieresis', + 'Egrave', + 'Iacute', + 'Icircumflex', + 'Idieresis', + 'Igrave', + 'Oacute', + 'Ocircumflex', + 'apple', + 'Ograve', + 'Uacute', + 'Ucircumflex', + 'Ugrave', + 'dotlessi', + 'circumflex', + 'tilde', + 'macron', + 'breve', + 'dotaccent', + 'ring', + 'cedilla', + 'hungarumlaut', + 'ogonek', + 'caron', + 'Lslash', + 'lslash', + 'Scaron', + 'scaron', + 'Zcaron', + 'zcaron', + 'brokenbar', + 'Eth', + 'eth', + 'Yacute', + 'yacute', + 'Thorn', + 'thorn', + 'minus', + 'multiply', + 'onesuperior', + 'twosuperior', + 'threesuperior', + 'onehalf', + 'onequarter', + 'threequarters', + 'franc', + 'Gbreve', + 'gbreve', + 'Idotaccent', + 'Scedilla', + 'scedilla', + 'Cacute', + 'cacute', + 'Ccaron', + 'ccaron', + 'dcroat' +]; +function adjustWidths(properties) { + if (!properties.fontMatrix) { + return; + } + if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) { + return; + } + var scale = 0.001 / properties.fontMatrix[0]; + var glyphsWidths = properties.widths; + for (var glyph in glyphsWidths) { + glyphsWidths[glyph] *= scale; + } + properties.defaultWidth *= scale; +} +function adjustToUnicode(properties, builtInEncoding) { + if (properties.hasIncludedToUnicodeMap) { + return; + } + if (properties.hasEncoding) { + return; + } + if (builtInEncoding === properties.defaultEncoding) { + return; + } + if (properties.toUnicode instanceof IdentityToUnicodeMap) { + return; + } + var toUnicode = [], glyphsUnicodeMap = getGlyphsUnicode(); + for (var charCode in builtInEncoding) { + var glyphName = builtInEncoding[charCode]; + var unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap); + if (unicode !== -1) { + toUnicode[charCode] = String.fromCharCode(unicode); + } + } + properties.toUnicode.amend(toUnicode); +} +function getFontType(type, subtype) { + switch (type) { + case 'Type1': + return subtype === 'Type1C' ? FontType.TYPE1C : FontType.TYPE1; + case 'CIDFontType0': + return subtype === 'CIDFontType0C' ? FontType.CIDFONTTYPE0C : FontType.CIDFONTTYPE0; + case 'OpenType': + return FontType.OPENTYPE; + case 'TrueType': + return FontType.TRUETYPE; + case 'CIDFontType2': + return FontType.CIDFONTTYPE2; + case 'MMType1': + return FontType.MMTYPE1; + case 'Type0': + return FontType.TYPE0; + default: + return FontType.UNKNOWN; + } +} +function recoverGlyphName(name, glyphsUnicodeMap) { + if (glyphsUnicodeMap[name] !== undefined) { + return name; + } + var unicode = getUnicodeForGlyph(name, glyphsUnicodeMap); + if (unicode !== -1) { + for (var key in glyphsUnicodeMap) { + if (glyphsUnicodeMap[key] === unicode) { + return key; + } + } + } + info('Unable to recover a standard glyph name for: ' + name); + return name; +} +var Glyph = function GlyphClosure() { + function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) { + this.fontChar = fontChar; + this.unicode = unicode; + this.accent = accent; + this.width = width; + this.vmetric = vmetric; + this.operatorListId = operatorListId; + this.isSpace = isSpace; + this.isInFont = isInFont; + } + Glyph.prototype.matchesForCache = function (fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) { + return this.fontChar === fontChar && this.unicode === unicode && this.accent === accent && this.width === width && this.vmetric === vmetric && this.operatorListId === operatorListId && this.isSpace === isSpace && this.isInFont === isInFont; + }; + return Glyph; +}(); +var ToUnicodeMap = function ToUnicodeMapClosure() { + function ToUnicodeMap(cmap) { + this._map = cmap; + } + ToUnicodeMap.prototype = { + get length() { + return this._map.length; + }, + forEach: function (callback) { + for (var charCode in this._map) { + callback(charCode, this._map[charCode].charCodeAt(0)); + } + }, + has: function (i) { + return this._map[i] !== undefined; + }, + get: function (i) { + return this._map[i]; + }, + charCodeOf: function (v) { + return this._map.indexOf(v); + }, + amend: function (map) { + for (var charCode in map) { + this._map[charCode] = map[charCode]; + } + } + }; + return ToUnicodeMap; +}(); +var IdentityToUnicodeMap = function IdentityToUnicodeMapClosure() { + function IdentityToUnicodeMap(firstChar, lastChar) { + this.firstChar = firstChar; + this.lastChar = lastChar; + } + IdentityToUnicodeMap.prototype = { + get length() { + return this.lastChar + 1 - this.firstChar; + }, + forEach: function (callback) { + for (var i = this.firstChar, ii = this.lastChar; i <= ii; i++) { + callback(i, i); + } + }, + has: function (i) { + return this.firstChar <= i && i <= this.lastChar; + }, + get: function (i) { + if (this.firstChar <= i && i <= this.lastChar) { + return String.fromCharCode(i); + } + return undefined; + }, + charCodeOf: function (v) { + return isInt(v) && v >= this.firstChar && v <= this.lastChar ? v : -1; + }, + amend: function (map) { + error('Should not call amend()'); + } + }; + return IdentityToUnicodeMap; +}(); +var OpenTypeFileBuilder = function OpenTypeFileBuilderClosure() { + function writeInt16(dest, offset, num) { + dest[offset] = num >> 8 & 0xFF; + dest[offset + 1] = num & 0xFF; + } + function writeInt32(dest, offset, num) { + dest[offset] = num >> 24 & 0xFF; + dest[offset + 1] = num >> 16 & 0xFF; + dest[offset + 2] = num >> 8 & 0xFF; + dest[offset + 3] = num & 0xFF; + } + function writeData(dest, offset, data) { + var i, ii; + if (data instanceof Uint8Array) { + dest.set(data, offset); + } else if (typeof data === 'string') { + for (i = 0, ii = data.length; i < ii; i++) { + dest[offset++] = data.charCodeAt(i) & 0xFF; + } + } else { + for (i = 0, ii = data.length; i < ii; i++) { + dest[offset++] = data[i] & 0xFF; + } + } + } + function OpenTypeFileBuilder(sfnt) { + this.sfnt = sfnt; + this.tables = Object.create(null); + } + OpenTypeFileBuilder.getSearchParams = function OpenTypeFileBuilder_getSearchParams(entriesCount, entrySize) { + var maxPower2 = 1, log2 = 0; + while ((maxPower2 ^ entriesCount) > maxPower2) { + maxPower2 <<= 1; + log2++; + } + var searchRange = maxPower2 * entrySize; + return { + range: searchRange, + entry: log2, + rangeShift: entrySize * entriesCount - searchRange + }; + }; + var OTF_HEADER_SIZE = 12; + var OTF_TABLE_ENTRY_SIZE = 16; + OpenTypeFileBuilder.prototype = { + toArray: function OpenTypeFileBuilder_toArray() { + var sfnt = this.sfnt; + var tables = this.tables; + var tablesNames = Object.keys(tables); + tablesNames.sort(); + var numTables = tablesNames.length; + var i, j, jj, table, tableName; + var offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE; + var tableOffsets = [offset]; + for (i = 0; i < numTables; i++) { + table = tables[tablesNames[i]]; + var paddedLength = (table.length + 3 & ~3) >>> 0; + offset += paddedLength; + tableOffsets.push(offset); + } + var file = new Uint8Array(offset); + for (i = 0; i < numTables; i++) { + table = tables[tablesNames[i]]; + writeData(file, tableOffsets[i], table); + } + if (sfnt === 'true') { + sfnt = string32(0x00010000); + } + file[0] = sfnt.charCodeAt(0) & 0xFF; + file[1] = sfnt.charCodeAt(1) & 0xFF; + file[2] = sfnt.charCodeAt(2) & 0xFF; + file[3] = sfnt.charCodeAt(3) & 0xFF; + writeInt16(file, 4, numTables); + var searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16); + writeInt16(file, 6, searchParams.range); + writeInt16(file, 8, searchParams.entry); + writeInt16(file, 10, searchParams.rangeShift); + offset = OTF_HEADER_SIZE; + for (i = 0; i < numTables; i++) { + tableName = tablesNames[i]; + file[offset] = tableName.charCodeAt(0) & 0xFF; + file[offset + 1] = tableName.charCodeAt(1) & 0xFF; + file[offset + 2] = tableName.charCodeAt(2) & 0xFF; + file[offset + 3] = tableName.charCodeAt(3) & 0xFF; + var checksum = 0; + for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) { + var quad = readUint32(file, j); + checksum = checksum + quad >>> 0; + } + writeInt32(file, offset + 4, checksum); + writeInt32(file, offset + 8, tableOffsets[i]); + writeInt32(file, offset + 12, tables[tableName].length); + offset += OTF_TABLE_ENTRY_SIZE; + } + return file; + }, + addTable: function OpenTypeFileBuilder_addTable(tag, data) { + if (tag in this.tables) { + throw new Error('Table ' + tag + ' already exists'); + } + this.tables[tag] = data; + } + }; + return OpenTypeFileBuilder; +}(); +var ProblematicCharRanges = new Int32Array([ + 0x0000, + 0x0020, + 0x007F, + 0x00A1, + 0x00AD, + 0x00AE, + 0x0600, + 0x0780, + 0x08A0, + 0x10A0, + 0x1780, + 0x1800, + 0x1C00, + 0x1C50, + 0x2000, + 0x2010, + 0x2011, + 0x2012, + 0x2028, + 0x2030, + 0x205F, + 0x2070, + 0x25CC, + 0x25CD, + 0x3000, + 0x3001, + 0xAA60, + 0xAA80, + 0xFFF0, + 0x10000 +]); +var Font = function FontClosure() { + function Font(name, file, properties) { + var charCode, glyphName, unicode; + this.name = name; + this.loadedName = properties.loadedName; + this.isType3Font = properties.isType3Font; + this.sizes = []; + this.missingFile = false; + this.glyphCache = Object.create(null); + this.isSerifFont = !!(properties.flags & FontFlags.Serif); + this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + this.isMonospace = !!(properties.flags & FontFlags.FixedPitch); + var type = properties.type; + var subtype = properties.subtype; + this.type = type; + this.fallbackName = this.isMonospace ? 'monospace' : this.isSerifFont ? 'serif' : 'sans-serif'; + this.differences = properties.differences; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.composite = properties.composite; + this.wideChars = properties.wideChars; + this.cMap = properties.cMap; + this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS; + this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS; + this.fontMatrix = properties.fontMatrix; + this.bbox = properties.bbox; + this.toUnicode = properties.toUnicode; + this.toFontChar = []; + if (properties.type === 'Type3') { + for (charCode = 0; charCode < 256; charCode++) { + this.toFontChar[charCode] = this.differences[charCode] || properties.defaultEncoding[charCode]; + } + this.fontType = FontType.TYPE3; + return; + } + this.cidEncoding = properties.cidEncoding; + this.vertical = properties.vertical; + if (this.vertical) { + this.vmetrics = properties.vmetrics; + this.defaultVMetrics = properties.defaultVMetrics; + } + var glyphsUnicodeMap; + if (!file || file.isEmpty) { + if (file) { + warn('Font file is empty in "' + name + '" (' + this.loadedName + ')'); + } + this.missingFile = true; + var fontName = name.replace(/[,_]/g, '-'); + var stdFontMap = getStdFontMap(), nonStdFontMap = getNonStdFontMap(); + var isStandardFont = !!stdFontMap[fontName] || !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]); + fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; + this.bold = fontName.search(/bold/gi) !== -1; + this.italic = fontName.search(/oblique/gi) !== -1 || fontName.search(/italic/gi) !== -1; + this.black = name.search(/Black/g) !== -1; + this.remeasure = Object.keys(this.widths).length > 0; + if (isStandardFont && type === 'CIDFontType2' && properties.cidEncoding.indexOf('Identity-') === 0) { + var GlyphMapForStandardFonts = getGlyphMapForStandardFonts(); + var map = []; + for (charCode in GlyphMapForStandardFonts) { + map[+charCode] = GlyphMapForStandardFonts[charCode]; + } + if (/Arial-?Black/i.test(name)) { + var SupplementalGlyphMapForArialBlack = getSupplementalGlyphMapForArialBlack(); + for (charCode in SupplementalGlyphMapForArialBlack) { + map[+charCode] = SupplementalGlyphMapForArialBlack[charCode]; + } + } + var isIdentityUnicode = this.toUnicode instanceof IdentityToUnicodeMap; + if (!isIdentityUnicode) { + this.toUnicode.forEach(function (charCode, unicodeCharCode) { + map[+charCode] = unicodeCharCode; + }); + } + this.toFontChar = map; + this.toUnicode = new ToUnicodeMap(map); + } else if (/Symbol/i.test(fontName)) { + this.toFontChar = buildToFontChar(SymbolSetEncoding, getGlyphsUnicode(), properties.differences); + } else if (/Dingbats/i.test(fontName)) { + if (/Wingdings/i.test(name)) { + warn('Non-embedded Wingdings font, falling back to ZapfDingbats.'); + } + this.toFontChar = buildToFontChar(ZapfDingbatsEncoding, getDingbatsGlyphsUnicode(), properties.differences); + } else if (isStandardFont) { + this.toFontChar = buildToFontChar(properties.defaultEncoding, getGlyphsUnicode(), properties.differences); + } else { + glyphsUnicodeMap = getGlyphsUnicode(); + this.toUnicode.forEach(function (charCode, unicodeCharCode) { + if (!this.composite) { + glyphName = properties.differences[charCode] || properties.defaultEncoding[charCode]; + unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap); + if (unicode !== -1) { + unicodeCharCode = unicode; + } + } + this.toFontChar[charCode] = unicodeCharCode; + }.bind(this)); + } + this.loadedName = fontName.split('-')[0]; + this.loading = false; + this.fontType = getFontType(type, subtype); + return; + } + if (subtype === 'Type1C') { + if (type !== 'Type1' && type !== 'MMType1') { + if (isTrueTypeFile(file)) { + subtype = 'TrueType'; + } else { + type = 'Type1'; + } + } else if (isOpenTypeFile(file)) { + type = subtype = 'OpenType'; + } + } + if (subtype === 'CIDFontType0C' && type !== 'CIDFontType0') { + type = 'CIDFontType0'; + } + if (subtype === 'OpenType') { + type = 'OpenType'; + } + if (type === 'CIDFontType0') { + if (isType1File(file)) { + subtype = 'CIDFontType0'; + } else if (isOpenTypeFile(file)) { + type = subtype = 'OpenType'; + } else { + subtype = 'CIDFontType0C'; + } + } + var data; + switch (type) { + case 'MMType1': + info('MMType1 font (' + name + '), falling back to Type1.'); + case 'Type1': + case 'CIDFontType0': + this.mimetype = 'font/opentype'; + var cff = subtype === 'Type1C' || subtype === 'CIDFontType0C' ? new CFFFont(file, properties) : new Type1Font(name, file, properties); + adjustWidths(properties); + data = this.convert(name, cff, properties); + break; + case 'OpenType': + case 'TrueType': + case 'CIDFontType2': + this.mimetype = 'font/opentype'; + data = this.checkAndRepair(name, file, properties); + if (this.isOpenType) { + adjustWidths(properties); + type = 'OpenType'; + } + break; + default: + error('Font ' + type + ' is not supported'); + break; + } + this.data = data; + this.fontType = getFontType(type, subtype); + this.fontMatrix = properties.fontMatrix; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.toUnicode = properties.toUnicode; + this.encoding = properties.baseEncoding; + this.seacMap = properties.seacMap; + this.loading = true; + } + Font.getFontID = function () { + var ID = 1; + return function Font_getFontID() { + return String(ID++); + }; + }(); + function int16(b0, b1) { + return (b0 << 8) + b1; + } + function signedInt16(b0, b1) { + var value = (b0 << 8) + b1; + return value & 1 << 15 ? value - 0x10000 : value; + } + function int32(b0, b1, b2, b3) { + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + } + function string16(value) { + return String.fromCharCode(value >> 8 & 0xff, value & 0xff); + } + function safeString16(value) { + value = value > 0x7FFF ? 0x7FFF : value < -0x8000 ? -0x8000 : value; + return String.fromCharCode(value >> 8 & 0xff, value & 0xff); + } + function isTrueTypeFile(file) { + var header = file.peekBytes(4); + return readUint32(header, 0) === 0x00010000; + } + function isOpenTypeFile(file) { + var header = file.peekBytes(4); + return bytesToString(header) === 'OTTO'; + } + function isType1File(file) { + var header = file.peekBytes(2); + if (header[0] === 0x25 && header[1] === 0x21) { + return true; + } + if (header[0] === 0x80 && header[1] === 0x01) { + return true; + } + return false; + } + function buildToFontChar(encoding, glyphsUnicodeMap, differences) { + var toFontChar = [], unicode; + for (var i = 0, ii = encoding.length; i < ii; i++) { + unicode = getUnicodeForGlyph(encoding[i], glyphsUnicodeMap); + if (unicode !== -1) { + toFontChar[i] = unicode; + } + } + for (var charCode in differences) { + unicode = getUnicodeForGlyph(differences[charCode], glyphsUnicodeMap); + if (unicode !== -1) { + toFontChar[+charCode] = unicode; + } + } + return toFontChar; + } + function isProblematicUnicodeLocation(code) { + var i = 0, j = ProblematicCharRanges.length - 1; + while (i < j) { + var c = i + j + 1 >> 1; + if (code < ProblematicCharRanges[c]) { + j = c - 1; + } else { + i = c; + } + } + return !(i & 1); + } + function adjustMapping(charCodeToGlyphId, properties) { + var toUnicode = properties.toUnicode; + var isSymbolic = !!(properties.flags & FontFlags.Symbolic); + var isIdentityUnicode = properties.toUnicode instanceof IdentityToUnicodeMap; + var newMap = Object.create(null); + var toFontChar = []; + var usedFontCharCodes = []; + var nextAvailableFontCharCode = PRIVATE_USE_OFFSET_START; + for (var originalCharCode in charCodeToGlyphId) { + originalCharCode |= 0; + var glyphId = charCodeToGlyphId[originalCharCode]; + var fontCharCode = originalCharCode; + var hasUnicodeValue = false; + if (!isIdentityUnicode && toUnicode.has(originalCharCode)) { + hasUnicodeValue = true; + var unicode = toUnicode.get(fontCharCode); + if (unicode.length === 1) { + fontCharCode = unicode.charCodeAt(0); + } + } + if ((usedFontCharCodes[fontCharCode] !== undefined || isProblematicUnicodeLocation(fontCharCode) || isSymbolic && !hasUnicodeValue) && nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END) { + do { + fontCharCode = nextAvailableFontCharCode++; + if (SKIP_PRIVATE_USE_RANGE_F000_TO_F01F && fontCharCode === 0xF000) { + fontCharCode = 0xF020; + nextAvailableFontCharCode = fontCharCode + 1; + } + } while (usedFontCharCodes[fontCharCode] !== undefined && nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END); + } + newMap[fontCharCode] = glyphId; + toFontChar[originalCharCode] = fontCharCode; + usedFontCharCodes[fontCharCode] = true; + } + return { + toFontChar: toFontChar, + charCodeToGlyphId: newMap, + nextAvailableFontCharCode: nextAvailableFontCharCode + }; + } + function getRanges(glyphs, numGlyphs) { + var codes = []; + for (var charCode in glyphs) { + if (glyphs[charCode] >= numGlyphs) { + continue; + } + codes.push({ + fontCharCode: charCode | 0, + glyphId: glyphs[charCode] + }); + } + codes.sort(function fontGetRangesSort(a, b) { + return a.fontCharCode - b.fontCharCode; + }); + var ranges = []; + var length = codes.length; + for (var n = 0; n < length;) { + var start = codes[n].fontCharCode; + var codeIndices = [codes[n].glyphId]; + ++n; + var end = start; + while (n < length && end + 1 === codes[n].fontCharCode) { + codeIndices.push(codes[n].glyphId); + ++end; + ++n; + if (end === 0xFFFF) { + break; + } + } + ranges.push([ + start, + end, + codeIndices + ]); + } + return ranges; + } + function createCmapTable(glyphs, numGlyphs) { + var ranges = getRanges(glyphs, numGlyphs); + var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1; + var cmap = '\x00\x00' + string16(numTables) + '\x00\x03' + '\x00\x01' + string32(4 + numTables * 8); + var i, ii, j, jj; + for (i = ranges.length - 1; i >= 0; --i) { + if (ranges[i][0] <= 0xFFFF) { + break; + } + } + var bmpLength = i + 1; + if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) { + ranges[i][1] = 0xFFFE; + } + var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0; + var segCount = bmpLength + trailingRangesCount; + var searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2); + var startCount = ''; + var endCount = ''; + var idDeltas = ''; + var idRangeOffsets = ''; + var glyphsIds = ''; + var bias = 0; + var range, start, end, codes; + for (i = 0, ii = bmpLength; i < ii; i++) { + range = ranges[i]; + start = range[0]; + end = range[1]; + startCount += string16(start); + endCount += string16(end); + codes = range[2]; + var contiguous = true; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + contiguous = false; + break; + } + } + if (!contiguous) { + var offset = (segCount - i) * 2 + bias * 2; + bias += end - start + 1; + idDeltas += string16(0); + idRangeOffsets += string16(offset); + for (j = 0, jj = codes.length; j < jj; ++j) { + glyphsIds += string16(codes[j]); + } + } else { + var startCode = codes[0]; + idDeltas += string16(startCode - start & 0xFFFF); + idRangeOffsets += string16(0); + } + } + if (trailingRangesCount > 0) { + endCount += '\xFF\xFF'; + startCount += '\xFF\xFF'; + idDeltas += '\x00\x01'; + idRangeOffsets += '\x00\x00'; + } + var format314 = '\x00\x00' + string16(2 * segCount) + string16(searchParams.range) + string16(searchParams.entry) + string16(searchParams.rangeShift) + endCount + '\x00\x00' + startCount + idDeltas + idRangeOffsets + glyphsIds; + var format31012 = ''; + var header31012 = ''; + if (numTables > 1) { + cmap += '\x00\x03' + '\x00\x0A' + string32(4 + numTables * 8 + 4 + format314.length); + format31012 = ''; + for (i = 0, ii = ranges.length; i < ii; i++) { + range = ranges[i]; + start = range[0]; + codes = range[2]; + var code = codes[0]; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + end = range[0] + j - 1; + format31012 += string32(start) + string32(end) + string32(code); + start = end + 1; + code = codes[j]; + } + } + format31012 += string32(start) + string32(range[1]) + string32(code); + } + header31012 = '\x00\x0C' + '\x00\x00' + string32(format31012.length + 16) + '\x00\x00\x00\x00' + string32(format31012.length / 12); + } + return cmap + '\x00\x04' + string16(format314.length + 4) + format314 + header31012 + format31012; + } + function validateOS2Table(os2) { + var stream = new Stream(os2.data); + var version = stream.getUint16(); + stream.getBytes(60); + var selection = stream.getUint16(); + if (version < 4 && selection & 0x0300) { + return false; + } + var firstChar = stream.getUint16(); + var lastChar = stream.getUint16(); + if (firstChar > lastChar) { + return false; + } + stream.getBytes(6); + var usWinAscent = stream.getUint16(); + if (usWinAscent === 0) { + return false; + } + os2.data[8] = os2.data[9] = 0; + return true; + } + function createOS2Table(properties, charstrings, override) { + override = override || { + unitsPerEm: 0, + yMax: 0, + yMin: 0, + ascent: 0, + descent: 0 + }; + var ulUnicodeRange1 = 0; + var ulUnicodeRange2 = 0; + var ulUnicodeRange3 = 0; + var ulUnicodeRange4 = 0; + var firstCharIndex = null; + var lastCharIndex = 0; + if (charstrings) { + for (var code in charstrings) { + code |= 0; + if (firstCharIndex > code || !firstCharIndex) { + firstCharIndex = code; + } + if (lastCharIndex < code) { + lastCharIndex = code; + } + var position = getUnicodeRangeFor(code); + if (position < 32) { + ulUnicodeRange1 |= 1 << position; + } else if (position < 64) { + ulUnicodeRange2 |= 1 << position - 32; + } else if (position < 96) { + ulUnicodeRange3 |= 1 << position - 64; + } else if (position < 123) { + ulUnicodeRange4 |= 1 << position - 96; + } else { + error('Unicode ranges Bits > 123 are reserved for internal usage'); + } + } + } else { + firstCharIndex = 0; + lastCharIndex = 255; + } + var bbox = properties.bbox || [ + 0, + 0, + 0, + 0 + ]; + var unitsPerEm = override.unitsPerEm || 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]; + var scale = properties.ascentScaled ? 1.0 : unitsPerEm / PDF_GLYPH_SPACE_UNITS; + var typoAscent = override.ascent || Math.round(scale * (properties.ascent || bbox[3])); + var typoDescent = override.descent || Math.round(scale * (properties.descent || bbox[1])); + if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) { + typoDescent = -typoDescent; + } + var winAscent = override.yMax || typoAscent; + var winDescent = -override.yMin || -typoDescent; + return '\x00\x03' + '\x02\x24' + '\x01\xF4' + '\x00\x05' + '\x00\x00' + '\x02\x8A' + '\x02\xBB' + '\x00\x00' + '\x00\x8C' + '\x02\x8A' + '\x02\xBB' + '\x00\x00' + '\x01\xDF' + '\x00\x31' + '\x01\x02' + '\x00\x00' + '\x00\x00\x06' + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + '\x00\x00\x00\x00\x00\x00' + string32(ulUnicodeRange1) + string32(ulUnicodeRange2) + string32(ulUnicodeRange3) + string32(ulUnicodeRange4) + '\x2A\x32\x31\x2A' + string16(properties.italicAngle ? 1 : 0) + string16(firstCharIndex || properties.firstChar) + string16(lastCharIndex || properties.lastChar) + string16(typoAscent) + string16(typoDescent) + '\x00\x64' + string16(winAscent) + string16(winDescent) + '\x00\x00\x00\x00' + '\x00\x00\x00\x00' + string16(properties.xHeight) + string16(properties.capHeight) + string16(0) + string16(firstCharIndex || properties.firstChar) + '\x00\x03'; + } + function createPostTable(properties) { + var angle = Math.floor(properties.italicAngle * Math.pow(2, 16)); + return '\x00\x03\x00\x00' + string32(angle) + '\x00\x00' + '\x00\x00' + string32(properties.fixedPitch) + '\x00\x00\x00\x00' + '\x00\x00\x00\x00' + '\x00\x00\x00\x00' + '\x00\x00\x00\x00'; + } + function createNameTable(name, proto) { + if (!proto) { + proto = [ + [], + [] + ]; + } + var strings = [ + proto[0][0] || 'Original licence', + proto[0][1] || name, + proto[0][2] || 'Unknown', + proto[0][3] || 'uniqueID', + proto[0][4] || name, + proto[0][5] || 'Version 0.11', + proto[0][6] || '', + proto[0][7] || 'Unknown', + proto[0][8] || 'Unknown', + proto[0][9] || 'Unknown' + ]; + var stringsUnicode = []; + var i, ii, j, jj, str; + for (i = 0, ii = strings.length; i < ii; i++) { + str = proto[1][i] || strings[i]; + var strBufUnicode = []; + for (j = 0, jj = str.length; j < jj; j++) { + strBufUnicode.push(string16(str.charCodeAt(j))); + } + stringsUnicode.push(strBufUnicode.join('')); + } + var names = [ + strings, + stringsUnicode + ]; + var platforms = [ + '\x00\x01', + '\x00\x03' + ]; + var encodings = [ + '\x00\x00', + '\x00\x01' + ]; + var languages = [ + '\x00\x00', + '\x04\x09' + ]; + var namesRecordCount = strings.length * platforms.length; + var nameTable = '\x00\x00' + string16(namesRecordCount) + string16(namesRecordCount * 12 + 6); + var strOffset = 0; + for (i = 0, ii = platforms.length; i < ii; i++) { + var strs = names[i]; + for (j = 0, jj = strs.length; j < jj; j++) { + str = strs[j]; + var nameRecord = platforms[i] + encodings[i] + languages[i] + string16(j) + string16(str.length) + string16(strOffset); + nameTable += nameRecord; + strOffset += str.length; + } + } + nameTable += strings.join('') + stringsUnicode.join(''); + return nameTable; + } + Font.prototype = { + name: null, + font: null, + mimetype: null, + encoding: null, + get renderer() { + var renderer = FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED); + return shadow(this, 'renderer', renderer); + }, + exportData: function Font_exportData() { + var data = {}; + for (var i in this) { + if (this.hasOwnProperty(i)) { + data[i] = this[i]; + } + } + return data; + }, + checkAndRepair: function Font_checkAndRepair(name, font, properties) { + function readTableEntry(file) { + var tag = bytesToString(file.getBytes(4)); + var checksum = file.getInt32() >>> 0; + var offset = file.getInt32() >>> 0; + var length = file.getInt32() >>> 0; + var previousPosition = file.pos; + file.pos = file.start ? file.start : 0; + file.skip(offset); + var data = file.getBytes(length); + file.pos = previousPosition; + if (tag === 'head') { + data[8] = data[9] = data[10] = data[11] = 0; + data[17] |= 0x20; + } + return { + tag: tag, + checksum: checksum, + length: length, + offset: offset, + data: data + }; + } + function readOpenTypeHeader(ttf) { + return { + version: bytesToString(ttf.getBytes(4)), + numTables: ttf.getUint16(), + searchRange: ttf.getUint16(), + entrySelector: ttf.getUint16(), + rangeShift: ttf.getUint16() + }; + } + function readCmapTable(cmap, font, isSymbolicFont, hasEncoding) { + if (!cmap) { + warn('No cmap table available.'); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + var segment; + var start = (font.start ? font.start : 0) + cmap.offset; + font.pos = start; + font.getUint16(); + var numTables = font.getUint16(); + var potentialTable; + var canBreak = false; + for (var i = 0; i < numTables; i++) { + var platformId = font.getUint16(); + var encodingId = font.getUint16(); + var offset = font.getInt32() >>> 0; + var useTable = false; + if (platformId === 0 && encodingId === 0) { + useTable = true; + } else if (platformId === 1 && encodingId === 0) { + useTable = true; + } else if (platformId === 3 && encodingId === 1 && (hasEncoding || !potentialTable)) { + useTable = true; + if (!isSymbolicFont) { + canBreak = true; + } + } else if (isSymbolicFont && platformId === 3 && encodingId === 0) { + useTable = true; + canBreak = true; + } + if (useTable) { + potentialTable = { + platformId: platformId, + encodingId: encodingId, + offset: offset + }; + } + if (canBreak) { + break; + } + } + if (potentialTable) { + font.pos = start + potentialTable.offset; + } + if (!potentialTable || font.peekByte() === -1) { + warn('Could not find a preferred cmap table.'); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + var format = font.getUint16(); + font.getUint16(); + font.getUint16(); + var hasShortCmap = false; + var mappings = []; + var j, glyphId; + if (format === 0) { + for (j = 0; j < 256; j++) { + var index = font.getByte(); + if (!index) { + continue; + } + mappings.push({ + charCode: j, + glyphId: index + }); + } + hasShortCmap = true; + } else if (format === 4) { + var segCount = font.getUint16() >> 1; + font.getBytes(6); + var segIndex, segments = []; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments.push({ end: font.getUint16() }); + } + font.getUint16(); + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].start = font.getUint16(); + } + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].delta = font.getUint16(); + } + var offsetsCount = 0; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + var rangeOffset = font.getUint16(); + if (!rangeOffset) { + segment.offsetIndex = -1; + continue; + } + var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex); + segment.offsetIndex = offsetIndex; + offsetsCount = Math.max(offsetsCount, offsetIndex + segment.end - segment.start + 1); + } + var offsets = []; + for (j = 0; j < offsetsCount; j++) { + offsets.push(font.getUint16()); + } + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + start = segment.start; + var end = segment.end; + var delta = segment.delta; + offsetIndex = segment.offsetIndex; + for (j = start; j <= end; j++) { + if (j === 0xFFFF) { + continue; + } + glyphId = offsetIndex < 0 ? j : offsets[offsetIndex + j - start]; + glyphId = glyphId + delta & 0xFFFF; + if (glyphId === 0) { + continue; + } + mappings.push({ + charCode: j, + glyphId: glyphId + }); + } + } + } else if (format === 6) { + var firstCode = font.getUint16(); + var entryCount = font.getUint16(); + for (j = 0; j < entryCount; j++) { + glyphId = font.getUint16(); + var charCode = firstCode + j; + mappings.push({ + charCode: charCode, + glyphId: glyphId + }); + } + } else { + warn('cmap table has unsupported format: ' + format); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + mappings.sort(function (a, b) { + return a.charCode - b.charCode; + }); + for (i = 1; i < mappings.length; i++) { + if (mappings[i - 1].charCode === mappings[i].charCode) { + mappings.splice(i, 1); + i--; + } + } + return { + platformId: potentialTable.platformId, + encodingId: potentialTable.encodingId, + mappings: mappings, + hasShortCmap: hasShortCmap + }; + } + function sanitizeMetrics(font, header, metrics, numGlyphs) { + if (!header) { + if (metrics) { + metrics.data = null; + } + return; + } + font.pos = (font.start ? font.start : 0) + header.offset; + font.pos += header.length - 2; + var numOfMetrics = font.getUint16(); + if (numOfMetrics > numGlyphs) { + info('The numOfMetrics (' + numOfMetrics + ') should not be ' + 'greater than the numGlyphs (' + numGlyphs + ')'); + numOfMetrics = numGlyphs; + header.data[34] = (numOfMetrics & 0xff00) >> 8; + header.data[35] = numOfMetrics & 0x00ff; + } + var numOfSidebearings = numGlyphs - numOfMetrics; + var numMissing = numOfSidebearings - (metrics.length - numOfMetrics * 4 >> 1); + if (numMissing > 0) { + var entries = new Uint8Array(metrics.length + numMissing * 2); + entries.set(metrics.data); + metrics.data = entries; + } + } + function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid) { + if (sourceEnd - sourceStart <= 12) { + return 0; + } + var glyf = source.subarray(sourceStart, sourceEnd); + var contoursCount = glyf[0] << 8 | glyf[1]; + if (contoursCount & 0x8000) { + dest.set(glyf, destStart); + return glyf.length; + } + var i, j = 10, flagsCount = 0; + for (i = 0; i < contoursCount; i++) { + var endPoint = glyf[j] << 8 | glyf[j + 1]; + flagsCount = endPoint + 1; + j += 2; + } + var instructionsStart = j; + var instructionsLength = glyf[j] << 8 | glyf[j + 1]; + j += 2 + instructionsLength; + var instructionsEnd = j; + var coordinatesLength = 0; + for (i = 0; i < flagsCount; i++) { + var flag = glyf[j++]; + if (flag & 0xC0) { + glyf[j - 1] = flag & 0x3F; + } + var xyLength = (flag & 2 ? 1 : flag & 16 ? 0 : 2) + (flag & 4 ? 1 : flag & 32 ? 0 : 2); + coordinatesLength += xyLength; + if (flag & 8) { + var repeat = glyf[j++]; + i += repeat; + coordinatesLength += repeat * xyLength; + } + } + if (coordinatesLength === 0) { + return 0; + } + var glyphDataLength = j + coordinatesLength; + if (glyphDataLength > glyf.length) { + return 0; + } + if (!hintsValid && instructionsLength > 0) { + dest.set(glyf.subarray(0, instructionsStart), destStart); + dest.set([ + 0, + 0 + ], destStart + instructionsStart); + dest.set(glyf.subarray(instructionsEnd, glyphDataLength), destStart + instructionsStart + 2); + glyphDataLength -= instructionsLength; + if (glyf.length - glyphDataLength > 3) { + glyphDataLength = glyphDataLength + 3 & ~3; + } + return glyphDataLength; + } + if (glyf.length - glyphDataLength > 3) { + glyphDataLength = glyphDataLength + 3 & ~3; + dest.set(glyf.subarray(0, glyphDataLength), destStart); + return glyphDataLength; + } + dest.set(glyf, destStart); + return glyf.length; + } + function sanitizeHead(head, numGlyphs, locaLength) { + var data = head.data; + var version = int32(data[0], data[1], data[2], data[3]); + if (version >> 16 !== 1) { + info('Attempting to fix invalid version in head table: ' + version); + data[0] = 0; + data[1] = 1; + data[2] = 0; + data[3] = 0; + } + var indexToLocFormat = int16(data[50], data[51]); + if (indexToLocFormat < 0 || indexToLocFormat > 1) { + info('Attempting to fix invalid indexToLocFormat in head table: ' + indexToLocFormat); + var numGlyphsPlusOne = numGlyphs + 1; + if (locaLength === numGlyphsPlusOne << 1) { + data[50] = 0; + data[51] = 0; + } else if (locaLength === numGlyphsPlusOne << 2) { + data[50] = 0; + data[51] = 1; + } else { + warn('Could not fix indexToLocFormat: ' + indexToLocFormat); + } + } + } + function sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry) { + var itemSize, itemDecode, itemEncode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]; + }; + itemEncode = function fontItemEncodeLong(data, offset, value) { + data[offset] = value >>> 24 & 0xFF; + data[offset + 1] = value >> 16 & 0xFF; + data[offset + 2] = value >> 8 & 0xFF; + data[offset + 3] = value & 0xFF; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return data[offset] << 9 | data[offset + 1] << 1; + }; + itemEncode = function fontItemEncode(data, offset, value) { + data[offset] = value >> 9 & 0xFF; + data[offset + 1] = value >> 1 & 0xFF; + }; + } + var locaData = loca.data; + var locaDataSize = itemSize * (1 + numGlyphs); + if (locaData.length !== locaDataSize) { + locaData = new Uint8Array(locaDataSize); + locaData.set(loca.data.subarray(0, locaDataSize)); + loca.data = locaData; + } + var oldGlyfData = glyf.data; + var oldGlyfDataLength = oldGlyfData.length; + var newGlyfData = new Uint8Array(oldGlyfDataLength); + var startOffset = itemDecode(locaData, 0); + var writeOffset = 0; + var missingGlyphData = Object.create(null); + itemEncode(locaData, 0, writeOffset); + var i, j; + for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { + var endOffset = itemDecode(locaData, j); + if (endOffset > oldGlyfDataLength && (oldGlyfDataLength + 3 & ~3) === endOffset) { + endOffset = oldGlyfDataLength; + } + if (endOffset > oldGlyfDataLength) { + itemEncode(locaData, j, writeOffset); + startOffset = endOffset; + continue; + } + if (startOffset === endOffset) { + missingGlyphData[i] = true; + } + var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset, newGlyfData, writeOffset, hintsValid); + writeOffset += newLength; + itemEncode(locaData, j, writeOffset); + startOffset = endOffset; + } + if (writeOffset === 0) { + var simpleGlyph = new Uint8Array([ + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 49, + 0 + ]); + for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { + itemEncode(locaData, j, simpleGlyph.length); + } + glyf.data = simpleGlyph; + return missingGlyphData; + } + if (dupFirstEntry) { + var firstEntryLength = itemDecode(locaData, itemSize); + if (newGlyfData.length > firstEntryLength + writeOffset) { + glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); + } else { + glyf.data = new Uint8Array(firstEntryLength + writeOffset); + glyf.data.set(newGlyfData.subarray(0, writeOffset)); + } + glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset); + itemEncode(loca.data, locaData.length - itemSize, writeOffset + firstEntryLength); + } else { + glyf.data = newGlyfData.subarray(0, writeOffset); + } + return missingGlyphData; + } + function readPostScriptTable(post, properties, maxpNumGlyphs) { + var start = (font.start ? font.start : 0) + post.offset; + font.pos = start; + var length = post.length, end = start + length; + var version = font.getInt32(); + font.getBytes(28); + var glyphNames; + var valid = true; + var i; + switch (version) { + case 0x00010000: + glyphNames = MacStandardGlyphOrdering; + break; + case 0x00020000: + var numGlyphs = font.getUint16(); + if (numGlyphs !== maxpNumGlyphs) { + valid = false; + break; + } + var glyphNameIndexes = []; + for (i = 0; i < numGlyphs; ++i) { + var index = font.getUint16(); + if (index >= 32768) { + valid = false; + break; + } + glyphNameIndexes.push(index); + } + if (!valid) { + break; + } + var customNames = []; + var strBuf = []; + while (font.pos < end) { + var stringLength = font.getByte(); + strBuf.length = stringLength; + for (i = 0; i < stringLength; ++i) { + strBuf[i] = String.fromCharCode(font.getByte()); + } + customNames.push(strBuf.join('')); + } + glyphNames = []; + for (i = 0; i < numGlyphs; ++i) { + var j = glyphNameIndexes[i]; + if (j < 258) { + glyphNames.push(MacStandardGlyphOrdering[j]); + continue; + } + glyphNames.push(customNames[j - 258]); + } + break; + case 0x00030000: + break; + default: + warn('Unknown/unsupported post table version ' + version); + valid = false; + if (properties.defaultEncoding) { + glyphNames = properties.defaultEncoding; + } + break; + } + properties.glyphNames = glyphNames; + return valid; + } + function readNameTable(nameTable) { + var start = (font.start ? font.start : 0) + nameTable.offset; + font.pos = start; + var names = [ + [], + [] + ]; + var length = nameTable.length, end = start + length; + var format = font.getUint16(); + var FORMAT_0_HEADER_LENGTH = 6; + if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) { + return names; + } + var numRecords = font.getUint16(); + var stringsStart = font.getUint16(); + var records = []; + var NAME_RECORD_LENGTH = 12; + var i, ii; + for (i = 0; i < numRecords && font.pos + NAME_RECORD_LENGTH <= end; i++) { + var r = { + platform: font.getUint16(), + encoding: font.getUint16(), + language: font.getUint16(), + name: font.getUint16(), + length: font.getUint16(), + offset: font.getUint16() + }; + if (r.platform === 1 && r.encoding === 0 && r.language === 0 || r.platform === 3 && r.encoding === 1 && r.language === 0x409) { + records.push(r); + } + } + for (i = 0, ii = records.length; i < ii; i++) { + var record = records[i]; + if (record.length <= 0) { + continue; + } + var pos = start + stringsStart + record.offset; + if (pos + record.length > end) { + continue; + } + font.pos = pos; + var nameIndex = record.name; + if (record.encoding) { + var str = ''; + for (var j = 0, jj = record.length; j < jj; j += 2) { + str += String.fromCharCode(font.getUint16()); + } + names[1][nameIndex] = str; + } else { + names[0][nameIndex] = bytesToString(font.getBytes(record.length)); + } + } + return names; + } + var TTOpsStackDeltas = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -2, + -2, + -2, + -2, + 0, + 0, + -2, + -5, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + 0, + 0, + -1, + 0, + -1, + -1, + -1, + -1, + 1, + -1, + -999, + 0, + 1, + 0, + -1, + -2, + 0, + -1, + -2, + -1, + -1, + 0, + -1, + -1, + 0, + 0, + -999, + -999, + -1, + -1, + -1, + -1, + -2, + -999, + -2, + -2, + -999, + 0, + -2, + -2, + 0, + 0, + -2, + 0, + -2, + 0, + 0, + 0, + -2, + -1, + -1, + 1, + 1, + 0, + 0, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + 0, + 0, + -1, + 0, + -1, + -1, + 0, + -999, + -1, + -1, + -1, + -1, + -1, + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -2, + -999, + -999, + -999, + -999, + -999, + -1, + -1, + -2, + -2, + 0, + 0, + 0, + 0, + -1, + -1, + -999, + -2, + -2, + 0, + 0, + -1, + -2, + -2, + 0, + 0, + 0, + -1, + -1, + -1, + -2 + ]; + function sanitizeTTProgram(table, ttContext) { + var data = table.data; + var i = 0, j, n, b, funcId, pc, lastEndf = 0, lastDeff = 0; + var stack = []; + var callstack = []; + var functionsCalled = []; + var tooComplexToFollowFunctions = ttContext.tooComplexToFollowFunctions; + var inFDEF = false, ifLevel = 0, inELSE = 0; + for (var ii = data.length; i < ii;) { + var op = data[i++]; + if (op === 0x40) { + n = data[i++]; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if (op === 0x41) { + n = data[i++]; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b = data[i++]; + stack.push(b << 8 | data[i++]); + } + } + } else if ((op & 0xF8) === 0xB0) { + n = op - 0xB0 + 1; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if ((op & 0xF8) === 0xB8) { + n = op - 0xB8 + 1; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b = data[i++]; + stack.push(b << 8 | data[i++]); + } + } + } else if (op === 0x2B && !tooComplexToFollowFunctions) { + if (!inFDEF && !inELSE) { + funcId = stack[stack.length - 1]; + ttContext.functionsUsed[funcId] = true; + if (funcId in ttContext.functionsStackDeltas) { + stack.length += ttContext.functionsStackDeltas[funcId]; + } else if (funcId in ttContext.functionsDefined && functionsCalled.indexOf(funcId) < 0) { + callstack.push({ + data: data, + i: i, + stackTop: stack.length - 1 + }); + functionsCalled.push(funcId); + pc = ttContext.functionsDefined[funcId]; + if (!pc) { + warn('TT: CALL non-existent function'); + ttContext.hintsValid = false; + return; + } + data = pc.data; + i = pc.i; + } + } + } else if (op === 0x2C && !tooComplexToFollowFunctions) { + if (inFDEF || inELSE) { + warn('TT: nested FDEFs not allowed'); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + lastDeff = i; + funcId = stack.pop(); + ttContext.functionsDefined[funcId] = { + data: data, + i: i + }; + } else if (op === 0x2D) { + if (inFDEF) { + inFDEF = false; + lastEndf = i; + } else { + pc = callstack.pop(); + if (!pc) { + warn('TT: ENDF bad stack'); + ttContext.hintsValid = false; + return; + } + funcId = functionsCalled.pop(); + data = pc.data; + i = pc.i; + ttContext.functionsStackDeltas[funcId] = stack.length - pc.stackTop; + } + } else if (op === 0x89) { + if (inFDEF || inELSE) { + warn('TT: nested IDEFs not allowed'); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + lastDeff = i; + } else if (op === 0x58) { + ++ifLevel; + } else if (op === 0x1B) { + inELSE = ifLevel; + } else if (op === 0x59) { + if (inELSE === ifLevel) { + inELSE = 0; + } + --ifLevel; + } else if (op === 0x1C) { + if (!inFDEF && !inELSE) { + var offset = stack[stack.length - 1]; + if (offset > 0) { + i += offset - 1; + } + } + } + if (!inFDEF && !inELSE) { + var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0; + if (op >= 0x71 && op <= 0x75) { + n = stack.pop(); + if (!isNaN(n)) { + stackDelta = -n * 2; + } + } + while (stackDelta < 0 && stack.length > 0) { + stack.pop(); + stackDelta++; + } + while (stackDelta > 0) { + stack.push(NaN); + stackDelta--; + } + } + } + ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions; + var content = [data]; + if (i > data.length) { + content.push(new Uint8Array(i - data.length)); + } + if (lastDeff > lastEndf) { + warn('TT: complementing a missing function tail'); + content.push(new Uint8Array([ + 0x22, + 0x2D + ])); + } + foldTTTable(table, content); + } + function checkInvalidFunctions(ttContext, maxFunctionDefs) { + if (ttContext.tooComplexToFollowFunctions) { + return; + } + if (ttContext.functionsDefined.length > maxFunctionDefs) { + warn('TT: more functions defined than expected'); + ttContext.hintsValid = false; + return; + } + for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) { + if (j > maxFunctionDefs) { + warn('TT: invalid function id: ' + j); + ttContext.hintsValid = false; + return; + } + if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) { + warn('TT: undefined function: ' + j); + ttContext.hintsValid = false; + return; + } + } + } + function foldTTTable(table, content) { + if (content.length > 1) { + var newLength = 0; + var j, jj; + for (j = 0, jj = content.length; j < jj; j++) { + newLength += content[j].length; + } + newLength = newLength + 3 & ~3; + var result = new Uint8Array(newLength); + var pos = 0; + for (j = 0, jj = content.length; j < jj; j++) { + result.set(content[j], pos); + pos += content[j].length; + } + table.data = result; + table.length = newLength; + } + } + function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs) { + var ttContext = { + functionsDefined: [], + functionsUsed: [], + functionsStackDeltas: [], + tooComplexToFollowFunctions: false, + hintsValid: true + }; + if (fpgm) { + sanitizeTTProgram(fpgm, ttContext); + } + if (prep) { + sanitizeTTProgram(prep, ttContext); + } + if (fpgm) { + checkInvalidFunctions(ttContext, maxFunctionDefs); + } + if (cvt && cvt.length & 1) { + var cvtData = new Uint8Array(cvt.length + 1); + cvtData.set(cvt.data); + cvt.data = cvtData; + } + return ttContext.hintsValid; + } + font = new Stream(new Uint8Array(font.getBytes())); + var VALID_TABLES = [ + 'OS/2', + 'cmap', + 'head', + 'hhea', + 'hmtx', + 'maxp', + 'name', + 'post', + 'loca', + 'glyf', + 'fpgm', + 'prep', + 'cvt ', + 'CFF ' + ]; + var header = readOpenTypeHeader(font); + var numTables = header.numTables; + var cff, cffFile; + var tables = Object.create(null); + tables['OS/2'] = null; + tables['cmap'] = null; + tables['head'] = null; + tables['hhea'] = null; + tables['hmtx'] = null; + tables['maxp'] = null; + tables['name'] = null; + tables['post'] = null; + var table; + for (var i = 0; i < numTables; i++) { + table = readTableEntry(font); + if (VALID_TABLES.indexOf(table.tag) < 0) { + continue; + } + if (table.length === 0) { + continue; + } + tables[table.tag] = table; + } + var isTrueType = !tables['CFF ']; + if (!isTrueType) { + if (header.version === 'OTTO' && !properties.composite || !tables['head'] || !tables['hhea'] || !tables['maxp'] || !tables['post']) { + cffFile = new Stream(tables['CFF '].data); + cff = new CFFFont(cffFile, properties); + adjustWidths(properties); + return this.convert(name, cff, properties); + } + delete tables['glyf']; + delete tables['loca']; + delete tables['fpgm']; + delete tables['prep']; + delete tables['cvt ']; + this.isOpenType = true; + } else { + if (!tables['loca']) { + error('Required "loca" table is not found'); + } + if (!tables['glyf']) { + warn('Required "glyf" table is not found -- trying to recover.'); + tables['glyf'] = { + tag: 'glyf', + data: new Uint8Array(0) + }; + } + this.isOpenType = false; + } + if (!tables['maxp']) { + error('Required "maxp" table is not found'); + } + font.pos = (font.start || 0) + tables['maxp'].offset; + var version = font.getInt32(); + var numGlyphs = font.getUint16(); + var maxFunctionDefs = 0; + if (version >= 0x00010000 && tables['maxp'].length >= 22) { + font.pos += 8; + var maxZones = font.getUint16(); + if (maxZones > 2) { + tables['maxp'].data[14] = 0; + tables['maxp'].data[15] = 2; + } + font.pos += 4; + maxFunctionDefs = font.getUint16(); + } + var dupFirstEntry = false; + if (properties.type === 'CIDFontType2' && properties.toUnicode && properties.toUnicode.get(0) > '\u0000') { + dupFirstEntry = true; + numGlyphs++; + tables['maxp'].data[4] = numGlyphs >> 8; + tables['maxp'].data[5] = numGlyphs & 255; + } + var hintsValid = sanitizeTTPrograms(tables['fpgm'], tables['prep'], tables['cvt '], maxFunctionDefs); + if (!hintsValid) { + delete tables['fpgm']; + delete tables['prep']; + delete tables['cvt ']; + } + sanitizeMetrics(font, tables['hhea'], tables['hmtx'], numGlyphs); + if (!tables['head']) { + error('Required "head" table is not found'); + } + sanitizeHead(tables['head'], numGlyphs, isTrueType ? tables['loca'].length : 0); + var missingGlyphs = Object.create(null); + if (isTrueType) { + var isGlyphLocationsLong = int16(tables['head'].data[50], tables['head'].data[51]); + missingGlyphs = sanitizeGlyphLocations(tables['loca'], tables['glyf'], numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry); + } + if (!tables['hhea']) { + error('Required "hhea" table is not found'); + } + if (tables['hhea'].data[10] === 0 && tables['hhea'].data[11] === 0) { + tables['hhea'].data[10] = 0xFF; + tables['hhea'].data[11] = 0xFF; + } + var metricsOverride = { + unitsPerEm: int16(tables['head'].data[18], tables['head'].data[19]), + yMax: int16(tables['head'].data[42], tables['head'].data[43]), + yMin: signedInt16(tables['head'].data[38], tables['head'].data[39]), + ascent: int16(tables['hhea'].data[4], tables['hhea'].data[5]), + descent: signedInt16(tables['hhea'].data[6], tables['hhea'].data[7]) + }; + this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm; + this.descent = metricsOverride.descent / metricsOverride.unitsPerEm; + if (tables['post']) { + var valid = readPostScriptTable(tables['post'], properties, numGlyphs); + if (!valid) { + tables['post'] = null; + } + } + var charCodeToGlyphId = [], charCode; + var toUnicode = properties.toUnicode, widths = properties.widths; + var skipToUnicode = toUnicode instanceof IdentityToUnicodeMap || toUnicode.length === 0x10000; + function hasGlyph(glyphId, charCode, widthCode) { + if (!missingGlyphs[glyphId]) { + return true; + } + if (!skipToUnicode && charCode >= 0 && toUnicode.has(charCode)) { + return true; + } + if (widths && widthCode >= 0 && isNum(widths[widthCode])) { + return true; + } + return false; + } + if (properties.composite) { + var cidToGidMap = properties.cidToGidMap || []; + var isCidToGidMapEmpty = cidToGidMap.length === 0; + properties.cMap.forEach(function (charCode, cid) { + assert(cid <= 0xffff, 'Max size of CID is 65,535'); + var glyphId = -1; + if (isCidToGidMapEmpty) { + glyphId = cid; + } else if (cidToGidMap[cid] !== undefined) { + glyphId = cidToGidMap[cid]; + } + if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId, charCode, cid)) { + charCodeToGlyphId[charCode] = glyphId; + } + }); + if (dupFirstEntry && (isCidToGidMapEmpty || !charCodeToGlyphId[0])) { + charCodeToGlyphId[0] = numGlyphs - 1; + } + } else { + var cmapTable = readCmapTable(tables['cmap'], font, this.isSymbolicFont, properties.hasEncoding); + var cmapPlatformId = cmapTable.platformId; + var cmapEncodingId = cmapTable.encodingId; + var cmapMappings = cmapTable.mappings; + var cmapMappingsLength = cmapMappings.length; + if (properties.hasEncoding && (cmapPlatformId === 3 && cmapEncodingId === 1 || cmapPlatformId === 1 && cmapEncodingId === 0) || cmapPlatformId === -1 && cmapEncodingId === -1 && !!getEncoding(properties.baseEncodingName)) { + var baseEncoding = []; + if (properties.baseEncodingName === 'MacRomanEncoding' || properties.baseEncodingName === 'WinAnsiEncoding') { + baseEncoding = getEncoding(properties.baseEncodingName); + } + var glyphsUnicodeMap = getGlyphsUnicode(); + for (charCode = 0; charCode < 256; charCode++) { + var glyphName, standardGlyphName; + if (this.differences && charCode in this.differences) { + glyphName = this.differences[charCode]; + } else if (charCode in baseEncoding && baseEncoding[charCode] !== '') { + glyphName = baseEncoding[charCode]; + } else { + glyphName = StandardEncoding[charCode]; + } + if (!glyphName) { + continue; + } + standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap); + var unicodeOrCharCode, isUnicode = false; + if (cmapPlatformId === 3 && cmapEncodingId === 1) { + unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName]; + isUnicode = true; + } else if (cmapPlatformId === 1 && cmapEncodingId === 0) { + unicodeOrCharCode = MacRomanEncoding.indexOf(standardGlyphName); + } + var found = false; + for (i = 0; i < cmapMappingsLength; ++i) { + if (cmapMappings[i].charCode !== unicodeOrCharCode) { + continue; + } + var code = isUnicode ? charCode : unicodeOrCharCode; + if (hasGlyph(cmapMappings[i].glyphId, code, -1)) { + charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; + found = true; + break; + } + } + if (!found && properties.glyphNames) { + var glyphId = properties.glyphNames.indexOf(glyphName); + if (glyphId === -1 && standardGlyphName !== glyphName) { + glyphId = properties.glyphNames.indexOf(standardGlyphName); + } + if (glyphId > 0 && hasGlyph(glyphId, -1, -1)) { + charCodeToGlyphId[charCode] = glyphId; + found = true; + } + } + if (!found) { + charCodeToGlyphId[charCode] = 0; + } + } + } else if (cmapPlatformId === 0 && cmapEncodingId === 0) { + for (i = 0; i < cmapMappingsLength; ++i) { + charCodeToGlyphId[cmapMappings[i].charCode] = cmapMappings[i].glyphId; + } + } else { + for (i = 0; i < cmapMappingsLength; ++i) { + charCode = cmapMappings[i].charCode & 0xFF; + charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; + } + } + } + if (charCodeToGlyphId.length === 0) { + charCodeToGlyphId[0] = 0; + } + var newMapping = adjustMapping(charCodeToGlyphId, properties); + this.toFontChar = newMapping.toFontChar; + tables['cmap'] = { + tag: 'cmap', + data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphs) + }; + if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) { + tables['OS/2'] = { + tag: 'OS/2', + data: createOS2Table(properties, newMapping.charCodeToGlyphId, metricsOverride) + }; + } + if (!tables['post']) { + tables['post'] = { + tag: 'post', + data: createPostTable(properties) + }; + } + if (!isTrueType) { + try { + cffFile = new Stream(tables['CFF '].data); + var parser = new CFFParser(cffFile, properties, SEAC_ANALYSIS_ENABLED); + cff = parser.parse(); + var compiler = new CFFCompiler(cff); + tables['CFF '].data = compiler.compile(); + } catch (e) { + warn('Failed to compile font ' + properties.loadedName); + } + } + if (!tables['name']) { + tables['name'] = { + tag: 'name', + data: createNameTable(this.name) + }; + } else { + var namePrototype = readNameTable(tables['name']); + tables['name'].data = createNameTable(name, namePrototype); + } + var builder = new OpenTypeFileBuilder(header.version); + for (var tableTag in tables) { + builder.addTable(tableTag, tables[tableTag].data); + } + return builder.toArray(); + }, + convert: function Font_convert(fontName, font, properties) { + properties.fixedPitch = false; + if (properties.builtInEncoding) { + adjustToUnicode(properties, properties.builtInEncoding); + } + var mapping = font.getGlyphMapping(properties); + var newMapping = adjustMapping(mapping, properties); + this.toFontChar = newMapping.toFontChar; + var numGlyphs = font.numGlyphs; + function getCharCodes(charCodeToGlyphId, glyphId) { + var charCodes = null; + for (var charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + if (!charCodes) { + charCodes = []; + } + charCodes.push(charCode | 0); + } + } + return charCodes; + } + function createCharCode(charCodeToGlyphId, glyphId) { + for (var charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + return charCode | 0; + } + } + newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = glyphId; + return newMapping.nextAvailableFontCharCode++; + } + var seacs = font.seacs; + if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) { + var matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX; + var charset = font.getCharset(); + var seacMap = Object.create(null); + for (var glyphId in seacs) { + glyphId |= 0; + var seac = seacs[glyphId]; + var baseGlyphName = StandardEncoding[seac[2]]; + var accentGlyphName = StandardEncoding[seac[3]]; + var baseGlyphId = charset.indexOf(baseGlyphName); + var accentGlyphId = charset.indexOf(accentGlyphName); + if (baseGlyphId < 0 || accentGlyphId < 0) { + continue; + } + var accentOffset = { + x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4], + y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5] + }; + var charCodes = getCharCodes(mapping, glyphId); + if (!charCodes) { + continue; + } + for (var i = 0, ii = charCodes.length; i < ii; i++) { + var charCode = charCodes[i]; + var charCodeToGlyphId = newMapping.charCodeToGlyphId; + var baseFontCharCode = createCharCode(charCodeToGlyphId, baseGlyphId); + var accentFontCharCode = createCharCode(charCodeToGlyphId, accentGlyphId); + seacMap[charCode] = { + baseFontCharCode: baseFontCharCode, + accentFontCharCode: accentFontCharCode, + accentOffset: accentOffset + }; + } + } + properties.seacMap = seacMap; + } + var unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]; + var builder = new OpenTypeFileBuilder('\x4F\x54\x54\x4F'); + builder.addTable('CFF ', font.data); + builder.addTable('OS/2', createOS2Table(properties, newMapping.charCodeToGlyphId)); + builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId, numGlyphs)); + builder.addTable('head', '\x00\x01\x00\x00' + '\x00\x00\x10\x00' + '\x00\x00\x00\x00' + '\x5F\x0F\x3C\xF5' + '\x00\x00' + safeString16(unitsPerEm) + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + '\x00\x00' + safeString16(properties.descent) + '\x0F\xFF' + safeString16(properties.ascent) + string16(properties.italicAngle ? 2 : 0) + '\x00\x11' + '\x00\x00' + '\x00\x00' + '\x00\x00'); + builder.addTable('hhea', '\x00\x01\x00\x00' + safeString16(properties.ascent) + safeString16(properties.descent) + '\x00\x00' + '\xFF\xFF' + '\x00\x00' + '\x00\x00' + '\x00\x00' + safeString16(properties.capHeight) + safeString16(Math.tan(properties.italicAngle) * properties.xHeight) + '\x00\x00' + '\x00\x00' + '\x00\x00' + '\x00\x00' + '\x00\x00' + '\x00\x00' + string16(numGlyphs)); + builder.addTable('hmtx', function fontFieldsHmtx() { + var charstrings = font.charstrings; + var cffWidths = font.cff ? font.cff.widths : null; + var hmtx = '\x00\x00\x00\x00'; + for (var i = 1, ii = numGlyphs; i < ii; i++) { + var width = 0; + if (charstrings) { + var charstring = charstrings[i - 1]; + width = 'width' in charstring ? charstring.width : 0; + } else if (cffWidths) { + width = Math.ceil(cffWidths[i] || 0); + } + hmtx += string16(width) + string16(0); + } + return hmtx; + }()); + builder.addTable('maxp', '\x00\x00\x50\x00' + string16(numGlyphs)); + builder.addTable('name', createNameTable(fontName)); + builder.addTable('post', createPostTable(properties)); + return builder.toArray(); + }, + get spaceWidth() { + if ('_shadowWidth' in this) { + return this._shadowWidth; + } + var possibleSpaceReplacements = [ + 'space', + 'minus', + 'one', + 'i', + 'I' + ]; + var width; + for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) { + var glyphName = possibleSpaceReplacements[i]; + if (glyphName in this.widths) { + width = this.widths[glyphName]; + break; + } + var glyphsUnicodeMap = getGlyphsUnicode(); + var glyphUnicode = glyphsUnicodeMap[glyphName]; + var charcode = 0; + if (this.composite) { + if (this.cMap.contains(glyphUnicode)) { + charcode = this.cMap.lookup(glyphUnicode); + } + } + if (!charcode && this.toUnicode) { + charcode = this.toUnicode.charCodeOf(glyphUnicode); + } + if (charcode <= 0) { + charcode = glyphUnicode; + } + width = this.widths[charcode]; + if (width) { + break; + } + } + width = width || this.defaultWidth; + this._shadowWidth = width; + return width; + }, + charToGlyph: function Font_charToGlyph(charcode, isSpace) { + var fontCharCode, width, operatorListId; + var widthCode = charcode; + if (this.cMap && this.cMap.contains(charcode)) { + widthCode = this.cMap.lookup(charcode); + } + width = this.widths[widthCode]; + width = isNum(width) ? width : this.defaultWidth; + var vmetric = this.vmetrics && this.vmetrics[widthCode]; + var unicode = this.toUnicode.get(charcode) || charcode; + if (typeof unicode === 'number') { + unicode = String.fromCharCode(unicode); + } + var isInFont = charcode in this.toFontChar; + fontCharCode = this.toFontChar[charcode] || charcode; + if (this.missingFile) { + fontCharCode = mapSpecialUnicodeValues(fontCharCode); + } + if (this.isType3Font) { + operatorListId = fontCharCode; + } + var accent = null; + if (this.seacMap && this.seacMap[charcode]) { + isInFont = true; + var seac = this.seacMap[charcode]; + fontCharCode = seac.baseFontCharCode; + accent = { + fontChar: String.fromCharCode(seac.accentFontCharCode), + offset: seac.accentOffset + }; + } + var fontChar = String.fromCharCode(fontCharCode); + var glyph = this.glyphCache[charcode]; + if (!glyph || !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont)) { + glyph = new Glyph(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont); + this.glyphCache[charcode] = glyph; + } + return glyph; + }, + charsToGlyphs: function Font_charsToGlyphs(chars) { + var charsCache = this.charsCache; + var glyphs, glyph, charcode; + if (charsCache) { + glyphs = charsCache[chars]; + if (glyphs) { + return glyphs; + } + } + if (!charsCache) { + charsCache = this.charsCache = Object.create(null); + } + glyphs = []; + var charsCacheKey = chars; + var i = 0, ii; + if (this.cMap) { + var c = Object.create(null); + while (i < chars.length) { + this.cMap.readCharCode(chars, i, c); + charcode = c.charcode; + var length = c.length; + i += length; + var isSpace = length === 1 && chars.charCodeAt(i - 1) === 0x20; + glyph = this.charToGlyph(charcode, isSpace); + glyphs.push(glyph); + } + } else { + for (i = 0, ii = chars.length; i < ii; ++i) { + charcode = chars.charCodeAt(i); + glyph = this.charToGlyph(charcode, charcode === 0x20); + glyphs.push(glyph); + } + } + return charsCache[charsCacheKey] = glyphs; + } + }; + return Font; +}(); +var ErrorFont = function ErrorFontClosure() { + function ErrorFont(error) { + this.error = error; + this.loadedName = 'g_font_error'; + this.loading = false; + } + ErrorFont.prototype = { + charsToGlyphs: function ErrorFont_charsToGlyphs() { + return []; + }, + exportData: function ErrorFont_exportData() { + return { error: this.error }; + } + }; + return ErrorFont; +}(); +function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) { + var charCodeToGlyphId = Object.create(null); + var glyphId, charCode, baseEncoding; + var isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + if (properties.baseEncodingName) { + baseEncoding = getEncoding(properties.baseEncodingName); + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + if (glyphId >= 0) { + charCodeToGlyphId[charCode] = glyphId; + } else { + charCodeToGlyphId[charCode] = 0; + } + } + } else if (isSymbolicFont) { + for (charCode in builtInEncoding) { + charCodeToGlyphId[charCode] = builtInEncoding[charCode]; + } + } else { + baseEncoding = StandardEncoding; + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + if (glyphId >= 0) { + charCodeToGlyphId[charCode] = glyphId; + } else { + charCodeToGlyphId[charCode] = 0; + } + } + } + var differences = properties.differences, glyphsUnicodeMap; + if (differences) { + for (charCode in differences) { + var glyphName = differences[charCode]; + glyphId = glyphNames.indexOf(glyphName); + if (glyphId === -1) { + if (!glyphsUnicodeMap) { + glyphsUnicodeMap = getGlyphsUnicode(); + } + var standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap); + if (standardGlyphName !== glyphName) { + glyphId = glyphNames.indexOf(standardGlyphName); + } + } + if (glyphId >= 0) { + charCodeToGlyphId[charCode] = glyphId; + } else { + charCodeToGlyphId[charCode] = 0; + } + } + } + return charCodeToGlyphId; +} +var Type1Font = function Type1FontClosure() { + function findBlock(streamBytes, signature, startIndex) { + var streamBytesLength = streamBytes.length; + var signatureLength = signature.length; + var scanLength = streamBytesLength - signatureLength; + var i = startIndex, j, found = false; + while (i < scanLength) { + j = 0; + while (j < signatureLength && streamBytes[i + j] === signature[j]) { + j++; + } + if (j >= signatureLength) { + i += j; + while (i < streamBytesLength && isSpace(streamBytes[i])) { + i++; + } + found = true; + break; + } + i++; + } + return { + found: found, + length: i + }; + } + function getHeaderBlock(stream, suggestedLength) { + var EEXEC_SIGNATURE = [ + 0x65, + 0x65, + 0x78, + 0x65, + 0x63 + ]; + var streamStartPos = stream.pos; + var headerBytes, headerBytesLength, block; + try { + headerBytes = stream.getBytes(suggestedLength); + headerBytesLength = headerBytes.length; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + } + if (headerBytesLength === suggestedLength) { + block = findBlock(headerBytes, EEXEC_SIGNATURE, suggestedLength - 2 * EEXEC_SIGNATURE.length); + if (block.found && block.length === suggestedLength) { + return { + stream: new Stream(headerBytes), + length: suggestedLength + }; + } + } + warn('Invalid "Length1" property in Type1 font -- trying to recover.'); + stream.pos = streamStartPos; + var SCAN_BLOCK_LENGTH = 2048; + var actualLength; + while (true) { + var scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH); + block = findBlock(scanBytes, EEXEC_SIGNATURE, 0); + if (block.length === 0) { + break; + } + stream.pos += block.length; + if (block.found) { + actualLength = stream.pos - streamStartPos; + break; + } + } + stream.pos = streamStartPos; + if (actualLength) { + return { + stream: new Stream(stream.getBytes(actualLength)), + length: actualLength + }; + } + warn('Unable to recover "Length1" property in Type1 font -- using as is.'); + return { + stream: new Stream(stream.getBytes(suggestedLength)), + length: suggestedLength + }; + } + function getEexecBlock(stream, suggestedLength) { + var eexecBytes = stream.getBytes(); + return { + stream: new Stream(eexecBytes), + length: eexecBytes.length + }; + } + function Type1Font(name, file, properties) { + var PFB_HEADER_SIZE = 6; + var headerBlockLength = properties.length1; + var eexecBlockLength = properties.length2; + var pfbHeader = file.peekBytes(PFB_HEADER_SIZE); + var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01; + if (pfbHeaderPresent) { + file.skip(PFB_HEADER_SIZE); + headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2]; + } + var headerBlock = getHeaderBlock(file, headerBlockLength); + headerBlockLength = headerBlock.length; + var headerBlockParser = new Type1Parser(headerBlock.stream, false, SEAC_ANALYSIS_ENABLED); + headerBlockParser.extractFontHeader(properties); + if (pfbHeaderPresent) { + pfbHeader = file.getBytes(PFB_HEADER_SIZE); + eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2]; + } + var eexecBlock = getEexecBlock(file, eexecBlockLength); + eexecBlockLength = eexecBlock.length; + var eexecBlockParser = new Type1Parser(eexecBlock.stream, true, SEAC_ANALYSIS_ENABLED); + var data = eexecBlockParser.extractFontProgram(); + for (var info in data.properties) { + properties[info] = data.properties[info]; + } + var charstrings = data.charstrings; + var type2Charstrings = this.getType2Charstrings(charstrings); + var subrs = this.getType2Subrs(data.subrs); + this.charstrings = charstrings; + this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties); + this.seacs = this.getSeacs(data.charstrings); + } + Type1Font.prototype = { + get numGlyphs() { + return this.charstrings.length + 1; + }, + getCharset: function Type1Font_getCharset() { + var charset = ['.notdef']; + var charstrings = this.charstrings; + for (var glyphId = 0; glyphId < charstrings.length; glyphId++) { + charset.push(charstrings[glyphId].glyphName); + } + return charset; + }, + getGlyphMapping: function Type1Font_getGlyphMapping(properties) { + var charstrings = this.charstrings; + var glyphNames = ['.notdef'], glyphId; + for (glyphId = 0; glyphId < charstrings.length; glyphId++) { + glyphNames.push(charstrings[glyphId].glyphName); + } + var encoding = properties.builtInEncoding; + if (encoding) { + var builtInEncoding = Object.create(null); + for (var charCode in encoding) { + glyphId = glyphNames.indexOf(encoding[charCode]); + if (glyphId >= 0) { + builtInEncoding[charCode] = glyphId; + } + } + } + return type1FontGlyphMapping(properties, builtInEncoding, glyphNames); + }, + getSeacs: function Type1Font_getSeacs(charstrings) { + var i, ii; + var seacMap = []; + for (i = 0, ii = charstrings.length; i < ii; i++) { + var charstring = charstrings[i]; + if (charstring.seac) { + seacMap[i + 1] = charstring.seac; + } + } + return seacMap; + }, + getType2Charstrings: function Type1Font_getType2Charstrings(type1Charstrings) { + var type2Charstrings = []; + for (var i = 0, ii = type1Charstrings.length; i < ii; i++) { + type2Charstrings.push(type1Charstrings[i].charstring); + } + return type2Charstrings; + }, + getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) { + var bias = 0; + var count = type1Subrs.length; + if (count < 1133) { + bias = 107; + } else if (count < 33769) { + bias = 1131; + } else { + bias = 32768; + } + var type2Subrs = []; + var i; + for (i = 0; i < bias; i++) { + type2Subrs.push([0x0B]); + } + for (i = 0; i < count; i++) { + type2Subrs.push(type1Subrs[i]); + } + return type2Subrs; + }, + wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) { + var cff = new CFF(); + cff.header = new CFFHeader(1, 0, 4, 4); + cff.names = [name]; + var topDict = new CFFTopDict(); + topDict.setByName('version', 391); + topDict.setByName('Notice', 392); + topDict.setByName('FullName', 393); + topDict.setByName('FamilyName', 394); + topDict.setByName('Weight', 395); + topDict.setByName('Encoding', null); + topDict.setByName('FontMatrix', properties.fontMatrix); + topDict.setByName('FontBBox', properties.bbox); + topDict.setByName('charset', null); + topDict.setByName('CharStrings', null); + topDict.setByName('Private', null); + cff.topDict = topDict; + var strings = new CFFStrings(); + strings.add('Version 0.11'); + strings.add('See original notice'); + strings.add(name); + strings.add(name); + strings.add('Medium'); + cff.strings = strings; + cff.globalSubrIndex = new CFFIndex(); + var count = glyphs.length; + var charsetArray = [0]; + var i, ii; + for (i = 0; i < count; i++) { + var index = CFFStandardStrings.indexOf(charstrings[i].glyphName); + if (index === -1) { + index = 0; + } + charsetArray.push(index >> 8 & 0xff, index & 0xff); + } + cff.charset = new CFFCharset(false, 0, [], charsetArray); + var charStringsIndex = new CFFIndex(); + charStringsIndex.add([ + 0x8B, + 0x0E + ]); + for (i = 0; i < count; i++) { + var glyph = glyphs[i]; + if (glyph.length === 0) { + charStringsIndex.add([ + 0x8B, + 0x0E + ]); + continue; + } + charStringsIndex.add(glyph); + } + cff.charStrings = charStringsIndex; + var privateDict = new CFFPrivateDict(); + privateDict.setByName('Subrs', null); + var fields = [ + 'BlueValues', + 'OtherBlues', + 'FamilyBlues', + 'FamilyOtherBlues', + 'StemSnapH', + 'StemSnapV', + 'BlueShift', + 'BlueFuzz', + 'BlueScale', + 'LanguageGroup', + 'ExpansionFactor', + 'ForceBold', + 'StdHW', + 'StdVW' + ]; + for (i = 0, ii = fields.length; i < ii; i++) { + var field = fields[i]; + if (!(field in properties.privateData)) { + continue; + } + var value = properties.privateData[field]; + if (isArray(value)) { + for (var j = value.length - 1; j > 0; j--) { + value[j] -= value[j - 1]; + } + } + privateDict.setByName(field, value); + } + cff.topDict.privateDict = privateDict; + var subrIndex = new CFFIndex(); + for (i = 0, ii = subrs.length; i < ii; i++) { + subrIndex.add(subrs[i]); + } + privateDict.subrsIndex = subrIndex; + var compiler = new CFFCompiler(cff); + return compiler.compile(); + } + }; + return Type1Font; +}(); +var CFFFont = function CFFFontClosure() { + function CFFFont(file, properties) { + this.properties = properties; + var parser = new CFFParser(file, properties, SEAC_ANALYSIS_ENABLED); + this.cff = parser.parse(); + var compiler = new CFFCompiler(this.cff); + this.seacs = this.cff.seacs; + try { + this.data = compiler.compile(); + } catch (e) { + warn('Failed to compile font ' + properties.loadedName); + this.data = file; + } + } + CFFFont.prototype = { + get numGlyphs() { + return this.cff.charStrings.count; + }, + getCharset: function CFFFont_getCharset() { + return this.cff.charset.charset; + }, + getGlyphMapping: function CFFFont_getGlyphMapping() { + var cff = this.cff; + var properties = this.properties; + var charsets = cff.charset.charset; + var charCodeToGlyphId; + var glyphId; + if (properties.composite) { + charCodeToGlyphId = Object.create(null); + if (cff.isCIDFont) { + for (glyphId = 0; glyphId < charsets.length; glyphId++) { + var cid = charsets[glyphId]; + var charCode = properties.cMap.charCodeOf(cid); + charCodeToGlyphId[charCode] = glyphId; + } + } else { + for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) { + charCodeToGlyphId[glyphId] = glyphId; + } + } + return charCodeToGlyphId; + } + var encoding = cff.encoding ? cff.encoding.encoding : null; + charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets); + return charCodeToGlyphId; + } + }; + return CFFFont; +}(); +(function checkSeacSupport() { + if (typeof navigator !== 'undefined' && /Windows/.test(navigator.userAgent)) { + SEAC_ANALYSIS_ENABLED = true; + } +}()); +(function checkChromeWindows() { + if (typeof navigator !== 'undefined' && /Windows.*Chrome/.test(navigator.userAgent)) { + SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = true; + } +}()); +exports.SEAC_ANALYSIS_ENABLED = SEAC_ANALYSIS_ENABLED; +exports.PRIVATE_USE_OFFSET_START = PRIVATE_USE_OFFSET_START; +exports.PRIVATE_USE_OFFSET_END = PRIVATE_USE_OFFSET_END; +exports.ErrorFont = ErrorFont; +exports.Font = Font; +exports.FontFlags = FontFlags; +exports.IdentityToUnicodeMap = IdentityToUnicodeMap; +exports.ProblematicCharRanges = ProblematicCharRanges; +exports.ToUnicodeMap = ToUnicodeMap; +exports.getFontType = getFontType; + +/***/ }), +/* 27 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreColorSpace = __w_pdfjs_require__(3); +var coreStream = __w_pdfjs_require__(2); +var coreJpx = __w_pdfjs_require__(15); +var ImageKind = sharedUtil.ImageKind; +var assert = sharedUtil.assert; +var error = sharedUtil.error; +var info = sharedUtil.info; +var isArray = sharedUtil.isArray; +var warn = sharedUtil.warn; +var Name = corePrimitives.Name; +var isStream = corePrimitives.isStream; +var ColorSpace = coreColorSpace.ColorSpace; +var DecodeStream = coreStream.DecodeStream; +var JpegStream = coreStream.JpegStream; +var JpxImage = coreJpx.JpxImage; +var PDFImage = function PDFImageClosure() { + function handleImageData(image, nativeDecoder) { + if (nativeDecoder && nativeDecoder.canDecode(image)) { + return nativeDecoder.decode(image); + } + return Promise.resolve(image); + } + function decodeAndClamp(value, addend, coefficient, max) { + value = addend + value * coefficient; + return value < 0 ? 0 : value > max ? max : value; + } + function resizeImageMask(src, bpc, w1, h1, w2, h2) { + var length = w2 * h2; + var dest = bpc <= 8 ? new Uint8Array(length) : bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length); + var xRatio = w1 / w2; + var yRatio = h1 / h2; + var i, j, py, newIndex = 0, oldIndex; + var xScaled = new Uint16Array(w2); + var w1Scanline = w1; + for (i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio); + } + for (i = 0; i < h2; i++) { + py = Math.floor(i * yRatio) * w1Scanline; + for (j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + dest[newIndex++] = src[oldIndex]; + } + } + return dest; + } + function PDFImage(xref, res, image, inline, smask, mask, isMask) { + this.image = image; + var dict = image.dict; + if (dict.has('Filter')) { + var filter = dict.get('Filter').name; + if (filter === 'JPXDecode') { + var jpxImage = new JpxImage(); + jpxImage.parseImageProperties(image.stream); + image.stream.reset(); + image.bitsPerComponent = jpxImage.bitsPerComponent; + image.numComps = jpxImage.componentsCount; + } else if (filter === 'JBIG2Decode') { + image.bitsPerComponent = 1; + image.numComps = 1; + } + } + this.width = dict.get('Width', 'W'); + this.height = dict.get('Height', 'H'); + if (this.width < 1 || this.height < 1) { + error('Invalid image width: ' + this.width + ' or height: ' + this.height); + } + this.interpolate = dict.get('Interpolate', 'I') || false; + this.imageMask = dict.get('ImageMask', 'IM') || false; + this.matte = dict.get('Matte') || false; + var bitsPerComponent = image.bitsPerComponent; + if (!bitsPerComponent) { + bitsPerComponent = dict.get('BitsPerComponent', 'BPC'); + if (!bitsPerComponent) { + if (this.imageMask) { + bitsPerComponent = 1; + } else { + error('Bits per component missing in image: ' + this.imageMask); + } + } + } + this.bpc = bitsPerComponent; + if (!this.imageMask) { + var colorSpace = dict.get('ColorSpace', 'CS'); + if (!colorSpace) { + info('JPX images (which do not require color spaces)'); + switch (image.numComps) { + case 1: + colorSpace = Name.get('DeviceGray'); + break; + case 3: + colorSpace = Name.get('DeviceRGB'); + break; + case 4: + colorSpace = Name.get('DeviceCMYK'); + break; + default: + error('JPX images with ' + this.numComps + ' color components not supported.'); + } + } + this.colorSpace = ColorSpace.parse(colorSpace, xref, res); + this.numComps = this.colorSpace.numComps; + } + this.decode = dict.getArray('Decode', 'D'); + this.needsDecode = false; + if (this.decode && (this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode) || isMask && !ColorSpace.isDefaultDecode(this.decode, 1))) { + this.needsDecode = true; + var max = (1 << bitsPerComponent) - 1; + this.decodeCoefficients = []; + this.decodeAddends = []; + for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) { + var dmin = this.decode[i]; + var dmax = this.decode[i + 1]; + this.decodeCoefficients[j] = dmax - dmin; + this.decodeAddends[j] = max * dmin; + } + } + if (smask) { + this.smask = new PDFImage(xref, res, smask, false); + } else if (mask) { + if (isStream(mask)) { + var maskDict = mask.dict, imageMask = maskDict.get('ImageMask', 'IM'); + if (!imageMask) { + warn('Ignoring /Mask in image without /ImageMask.'); + } else { + this.mask = new PDFImage(xref, res, mask, false, null, null, true); + } + } else { + this.mask = mask; + } + } + } + PDFImage.buildImage = function PDFImage_buildImage(handler, xref, res, image, inline, nativeDecoder) { + var imagePromise = handleImageData(image, nativeDecoder); + var smaskPromise; + var maskPromise; + var smask = image.dict.get('SMask'); + var mask = image.dict.get('Mask'); + if (smask) { + smaskPromise = handleImageData(smask, nativeDecoder); + maskPromise = Promise.resolve(null); + } else { + smaskPromise = Promise.resolve(null); + if (mask) { + if (isStream(mask)) { + maskPromise = handleImageData(mask, nativeDecoder); + } else if (isArray(mask)) { + maskPromise = Promise.resolve(mask); + } else { + warn('Unsupported mask format.'); + maskPromise = Promise.resolve(null); + } + } else { + maskPromise = Promise.resolve(null); + } + } + return Promise.all([ + imagePromise, + smaskPromise, + maskPromise + ]).then(function (results) { + var imageData = results[0]; + var smaskData = results[1]; + var maskData = results[2]; + return new PDFImage(xref, res, imageData, inline, smaskData, maskData); + }); + }; + PDFImage.createMask = function PDFImage_createMask(imgArray, width, height, imageIsFromDecodeStream, inverseDecode) { + var computedLength = (width + 7 >> 3) * height; + var actualLength = imgArray.byteLength; + var haveFullData = computedLength === actualLength; + var data, i; + if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) { + data = imgArray; + } else if (!inverseDecode) { + data = new Uint8Array(actualLength); + data.set(imgArray); + } else { + data = new Uint8Array(computedLength); + data.set(imgArray); + for (i = actualLength; i < computedLength; i++) { + data[i] = 0xff; + } + } + if (inverseDecode) { + for (i = 0; i < actualLength; i++) { + data[i] = ~data[i]; + } + } + return { + data: data, + width: width, + height: height + }; + }; + PDFImage.prototype = { + get drawWidth() { + return Math.max(this.width, this.smask && this.smask.width || 0, this.mask && this.mask.width || 0); + }, + get drawHeight() { + return Math.max(this.height, this.smask && this.smask.height || 0, this.mask && this.mask.height || 0); + }, + decodeBuffer: function PDFImage_decodeBuffer(buffer) { + var bpc = this.bpc; + var numComps = this.numComps; + var decodeAddends = this.decodeAddends; + var decodeCoefficients = this.decodeCoefficients; + var max = (1 << bpc) - 1; + var i, ii; + if (bpc === 1) { + for (i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] = +!buffer[i]; + } + return; + } + var index = 0; + for (i = 0, ii = this.width * this.height; i < ii; i++) { + for (var j = 0; j < numComps; j++) { + buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], decodeCoefficients[j], max); + index++; + } + } + }, + getComponents: function PDFImage_getComponents(buffer) { + var bpc = this.bpc; + if (bpc === 8) { + return buffer; + } + var width = this.width; + var height = this.height; + var numComps = this.numComps; + var length = width * height * numComps; + var bufferPos = 0; + var output = bpc <= 8 ? new Uint8Array(length) : bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length); + var rowComps = width * numComps; + var max = (1 << bpc) - 1; + var i = 0, ii, buf; + if (bpc === 1) { + var mask, loop1End, loop2End; + for (var j = 0; j < height; j++) { + loop1End = i + (rowComps & ~7); + loop2End = i + rowComps; + while (i < loop1End) { + buf = buffer[bufferPos++]; + output[i] = buf >> 7 & 1; + output[i + 1] = buf >> 6 & 1; + output[i + 2] = buf >> 5 & 1; + output[i + 3] = buf >> 4 & 1; + output[i + 4] = buf >> 3 & 1; + output[i + 5] = buf >> 2 & 1; + output[i + 6] = buf >> 1 & 1; + output[i + 7] = buf & 1; + i += 8; + } + if (i < loop2End) { + buf = buffer[bufferPos++]; + mask = 128; + while (i < loop2End) { + output[i++] = +!!(buf & mask); + mask >>= 1; + } + } + } + } else { + var bits = 0; + buf = 0; + for (i = 0, ii = length; i < ii; ++i) { + if (i % rowComps === 0) { + buf = 0; + bits = 0; + } + while (bits < bpc) { + buf = buf << 8 | buffer[bufferPos++]; + bits += 8; + } + var remainingBits = bits - bpc; + var value = buf >> remainingBits; + output[i] = value < 0 ? 0 : value > max ? max : value; + buf = buf & (1 << remainingBits) - 1; + bits = remainingBits; + } + } + return output; + }, + fillOpacity: function PDFImage_fillOpacity(rgbaBuf, width, height, actualHeight, image) { + var smask = this.smask; + var mask = this.mask; + var alphaBuf, sw, sh, i, ii, j; + if (smask) { + sw = smask.width; + sh = smask.height; + alphaBuf = new Uint8Array(sw * sh); + smask.fillGrayBuffer(alphaBuf); + if (sw !== width || sh !== height) { + alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh, width, height); + } + } else if (mask) { + if (mask instanceof PDFImage) { + sw = mask.width; + sh = mask.height; + alphaBuf = new Uint8Array(sw * sh); + mask.numComps = 1; + mask.fillGrayBuffer(alphaBuf); + for (i = 0, ii = sw * sh; i < ii; ++i) { + alphaBuf[i] = 255 - alphaBuf[i]; + } + if (sw !== width || sh !== height) { + alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh, width, height); + } + } else if (isArray(mask)) { + alphaBuf = new Uint8Array(width * height); + var numComps = this.numComps; + for (i = 0, ii = width * height; i < ii; ++i) { + var opacity = 0; + var imageOffset = i * numComps; + for (j = 0; j < numComps; ++j) { + var color = image[imageOffset + j]; + var maskOffset = j * 2; + if (color < mask[maskOffset] || color > mask[maskOffset + 1]) { + opacity = 255; + break; + } + } + alphaBuf[i] = opacity; + } + } else { + error('Unknown mask format.'); + } + } + if (alphaBuf) { + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = alphaBuf[i]; + } + } else { + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = 255; + } + } + }, + undoPreblend: function PDFImage_undoPreblend(buffer, width, height) { + var matte = this.smask && this.smask.matte; + if (!matte) { + return; + } + var matteRgb = this.colorSpace.getRgb(matte, 0); + var matteR = matteRgb[0]; + var matteG = matteRgb[1]; + var matteB = matteRgb[2]; + var length = width * height * 4; + var r, g, b; + for (var i = 0; i < length; i += 4) { + var alpha = buffer[i + 3]; + if (alpha === 0) { + buffer[i] = 255; + buffer[i + 1] = 255; + buffer[i + 2] = 255; + continue; + } + var k = 255 / alpha; + r = (buffer[i] - matteR) * k + matteR; + g = (buffer[i + 1] - matteG) * k + matteG; + b = (buffer[i + 2] - matteB) * k + matteB; + buffer[i] = r <= 0 ? 0 : r >= 255 ? 255 : r | 0; + buffer[i + 1] = g <= 0 ? 0 : g >= 255 ? 255 : g | 0; + buffer[i + 2] = b <= 0 ? 0 : b >= 255 ? 255 : b | 0; + } + }, + createImageData: function PDFImage_createImageData(forceRGBA) { + var drawWidth = this.drawWidth; + var drawHeight = this.drawHeight; + var imgData = { + width: drawWidth, + height: drawHeight + }; + var numComps = this.numComps; + var originalWidth = this.width; + var originalHeight = this.height; + var bpc = this.bpc; + var rowBytes = originalWidth * numComps * bpc + 7 >> 3; + var imgArray; + if (!forceRGBA) { + var kind; + if (this.colorSpace.name === 'DeviceGray' && bpc === 1) { + kind = ImageKind.GRAYSCALE_1BPP; + } else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 && !this.needsDecode) { + kind = ImageKind.RGB_24BPP; + } + if (kind && !this.smask && !this.mask && drawWidth === originalWidth && drawHeight === originalHeight) { + imgData.kind = kind; + imgArray = this.getImageBytes(originalHeight * rowBytes); + if (this.image instanceof DecodeStream) { + imgData.data = imgArray; + } else { + var newArray = new Uint8Array(imgArray.length); + newArray.set(imgArray); + imgData.data = newArray; + } + if (this.needsDecode) { + assert(kind === ImageKind.GRAYSCALE_1BPP); + var buffer = imgData.data; + for (var i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] ^= 0xff; + } + } + return imgData; + } + if (this.image instanceof JpegStream && !this.smask && !this.mask && (this.colorSpace.name === 'DeviceGray' || this.colorSpace.name === 'DeviceRGB' || this.colorSpace.name === 'DeviceCMYK')) { + imgData.kind = ImageKind.RGB_24BPP; + imgData.data = this.getImageBytes(originalHeight * rowBytes, drawWidth, drawHeight, true); + return imgData; + } + } + imgArray = this.getImageBytes(originalHeight * rowBytes); + var actualHeight = 0 | imgArray.length / rowBytes * drawHeight / originalHeight; + var comps = this.getComponents(imgArray); + var alpha01, maybeUndoPreblend; + if (!forceRGBA && !this.smask && !this.mask) { + imgData.kind = ImageKind.RGB_24BPP; + imgData.data = new Uint8Array(drawWidth * drawHeight * 3); + alpha01 = 0; + maybeUndoPreblend = false; + } else { + imgData.kind = ImageKind.RGBA_32BPP; + imgData.data = new Uint8Array(drawWidth * drawHeight * 4); + alpha01 = 1; + maybeUndoPreblend = true; + this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight, comps); + } + if (this.needsDecode) { + this.decodeBuffer(comps); + } + this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight, drawWidth, drawHeight, actualHeight, bpc, comps, alpha01); + if (maybeUndoPreblend) { + this.undoPreblend(imgData.data, drawWidth, actualHeight); + } + return imgData; + }, + fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) { + var numComps = this.numComps; + if (numComps !== 1) { + error('Reading gray scale from a color image: ' + numComps); + } + var width = this.width; + var height = this.height; + var bpc = this.bpc; + var rowBytes = width * numComps * bpc + 7 >> 3; + var imgArray = this.getImageBytes(height * rowBytes); + var comps = this.getComponents(imgArray); + var i, length; + if (bpc === 1) { + length = width * height; + if (this.needsDecode) { + for (i = 0; i < length; ++i) { + buffer[i] = comps[i] - 1 & 255; + } + } else { + for (i = 0; i < length; ++i) { + buffer[i] = -comps[i] & 255; + } + } + return; + } + if (this.needsDecode) { + this.decodeBuffer(comps); + } + length = width * height; + var scale = 255 / ((1 << bpc) - 1); + for (i = 0; i < length; ++i) { + buffer[i] = scale * comps[i] | 0; + } + }, + getImageBytes: function PDFImage_getImageBytes(length, drawWidth, drawHeight, forceRGB) { + this.image.reset(); + this.image.drawWidth = drawWidth || this.width; + this.image.drawHeight = drawHeight || this.height; + this.image.forceRGB = !!forceRGB; + return this.image.getBytes(length); + } + }; + return PDFImage; +}(); +exports.PDFImage = PDFImage; + +/***/ }), +/* 28 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var coreArithmeticDecoder = __w_pdfjs_require__(10); +var error = sharedUtil.error; +var log2 = sharedUtil.log2; +var readInt8 = sharedUtil.readInt8; +var readUint16 = sharedUtil.readUint16; +var readUint32 = sharedUtil.readUint32; +var shadow = sharedUtil.shadow; +var ArithmeticDecoder = coreArithmeticDecoder.ArithmeticDecoder; +var Jbig2Image = function Jbig2ImageClosure() { + function ContextCache() { + } + ContextCache.prototype = { + getContexts: function (id) { + if (id in this) { + return this[id]; + } + return this[id] = new Int8Array(1 << 16); + } + }; + function DecodingContext(data, start, end) { + this.data = data; + this.start = start; + this.end = end; + } + DecodingContext.prototype = { + get decoder() { + var decoder = new ArithmeticDecoder(this.data, this.start, this.end); + return shadow(this, 'decoder', decoder); + }, + get contextCache() { + var cache = new ContextCache(); + return shadow(this, 'contextCache', cache); + } + }; + function decodeInteger(contextCache, procedure, decoder) { + var contexts = contextCache.getContexts(procedure); + var prev = 1; + function readBits(length) { + var v = 0; + for (var i = 0; i < length; i++) { + var bit = decoder.readBit(contexts, prev); + prev = prev < 256 ? prev << 1 | bit : (prev << 1 | bit) & 511 | 256; + v = v << 1 | bit; + } + return v >>> 0; + } + var sign = readBits(1); + var value = readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(32) + 4436 : readBits(12) + 340 : readBits(8) + 84 : readBits(6) + 20 : readBits(4) + 4 : readBits(2); + return sign === 0 ? value : value > 0 ? -value : null; + } + function decodeIAID(contextCache, decoder, codeLength) { + var contexts = contextCache.getContexts('IAID'); + var prev = 1; + for (var i = 0; i < codeLength; i++) { + var bit = decoder.readBit(contexts, prev); + prev = prev << 1 | bit; + } + if (codeLength < 31) { + return prev & (1 << codeLength) - 1; + } + return prev & 0x7FFFFFFF; + } + var SegmentTypes = [ + 'SymbolDictionary', + null, + null, + null, + 'IntermediateTextRegion', + null, + 'ImmediateTextRegion', + 'ImmediateLosslessTextRegion', + null, + null, + null, + null, + null, + null, + null, + null, + 'patternDictionary', + null, + null, + null, + 'IntermediateHalftoneRegion', + null, + 'ImmediateHalftoneRegion', + 'ImmediateLosslessHalftoneRegion', + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 'IntermediateGenericRegion', + null, + 'ImmediateGenericRegion', + 'ImmediateLosslessGenericRegion', + 'IntermediateGenericRefinementRegion', + null, + 'ImmediateGenericRefinementRegion', + 'ImmediateLosslessGenericRefinementRegion', + null, + null, + null, + null, + 'PageInformation', + 'EndOfPage', + 'EndOfStripe', + 'EndOfFile', + 'Profiles', + 'Tables', + null, + null, + null, + null, + null, + null, + null, + null, + 'Extension' + ]; + var CodingTemplates = [ + [ + { + x: -1, + y: -2 + }, + { + x: 0, + y: -2 + }, + { + x: 1, + y: -2 + }, + { + x: -2, + y: -1 + }, + { + x: -1, + y: -1 + }, + { + x: 0, + y: -1 + }, + { + x: 1, + y: -1 + }, + { + x: 2, + y: -1 + }, + { + x: -4, + y: 0 + }, + { + x: -3, + y: 0 + }, + { + x: -2, + y: 0 + }, + { + x: -1, + y: 0 + } + ], + [ + { + x: -1, + y: -2 + }, + { + x: 0, + y: -2 + }, + { + x: 1, + y: -2 + }, + { + x: 2, + y: -2 + }, + { + x: -2, + y: -1 + }, + { + x: -1, + y: -1 + }, + { + x: 0, + y: -1 + }, + { + x: 1, + y: -1 + }, + { + x: 2, + y: -1 + }, + { + x: -3, + y: 0 + }, + { + x: -2, + y: 0 + }, + { + x: -1, + y: 0 + } + ], + [ + { + x: -1, + y: -2 + }, + { + x: 0, + y: -2 + }, + { + x: 1, + y: -2 + }, + { + x: -2, + y: -1 + }, + { + x: -1, + y: -1 + }, + { + x: 0, + y: -1 + }, + { + x: 1, + y: -1 + }, + { + x: -2, + y: 0 + }, + { + x: -1, + y: 0 + } + ], + [ + { + x: -3, + y: -1 + }, + { + x: -2, + y: -1 + }, + { + x: -1, + y: -1 + }, + { + x: 0, + y: -1 + }, + { + x: 1, + y: -1 + }, + { + x: -4, + y: 0 + }, + { + x: -3, + y: 0 + }, + { + x: -2, + y: 0 + }, + { + x: -1, + y: 0 + } + ] + ]; + var RefinementTemplates = [ + { + coding: [ + { + x: 0, + y: -1 + }, + { + x: 1, + y: -1 + }, + { + x: -1, + y: 0 + } + ], + reference: [ + { + x: 0, + y: -1 + }, + { + x: 1, + y: -1 + }, + { + x: -1, + y: 0 + }, + { + x: 0, + y: 0 + }, + { + x: 1, + y: 0 + }, + { + x: -1, + y: 1 + }, + { + x: 0, + y: 1 + }, + { + x: 1, + y: 1 + } + ] + }, + { + coding: [ + { + x: -1, + y: -1 + }, + { + x: 0, + y: -1 + }, + { + x: 1, + y: -1 + }, + { + x: -1, + y: 0 + } + ], + reference: [ + { + x: 0, + y: -1 + }, + { + x: -1, + y: 0 + }, + { + x: 0, + y: 0 + }, + { + x: 1, + y: 0 + }, + { + x: 0, + y: 1 + }, + { + x: 1, + y: 1 + } + ] + } + ]; + var ReusedContexts = [ + 0x9B25, + 0x0795, + 0x00E5, + 0x0195 + ]; + var RefinementReusedContexts = [ + 0x0020, + 0x0008 + ]; + function decodeBitmapTemplate0(width, height, decodingContext) { + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GB'); + var contextLabel, i, j, pixel, row, row1, row2, bitmap = []; + var OLD_PIXEL_MASK = 0x7BF7; + for (i = 0; i < height; i++) { + row = bitmap[i] = new Uint8Array(width); + row1 = i < 1 ? row : bitmap[i - 1]; + row2 = i < 2 ? row : bitmap[i - 2]; + contextLabel = row2[0] << 13 | row2[1] << 12 | row2[2] << 11 | row1[0] << 7 | row1[1] << 6 | row1[2] << 5 | row1[3] << 4; + for (j = 0; j < width; j++) { + row[j] = pixel = decoder.readBit(contexts, contextLabel); + contextLabel = (contextLabel & OLD_PIXEL_MASK) << 1 | (j + 3 < width ? row2[j + 3] << 11 : 0) | (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel; + } + } + return bitmap; + } + function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) { + if (mmr) { + error('JBIG2 error: MMR encoding is not supported'); + } + if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) { + return decodeBitmapTemplate0(width, height, decodingContext); + } + var useskip = !!skip; + var template = CodingTemplates[templateIndex].concat(at); + template.sort(function (a, b) { + return a.y - b.y || a.x - b.x; + }); + var templateLength = template.length; + var templateX = new Int8Array(templateLength); + var templateY = new Int8Array(templateLength); + var changingTemplateEntries = []; + var reuseMask = 0, minX = 0, maxX = 0, minY = 0; + var c, k; + for (k = 0; k < templateLength; k++) { + templateX[k] = template[k].x; + templateY[k] = template[k].y; + minX = Math.min(minX, template[k].x); + maxX = Math.max(maxX, template[k].x); + minY = Math.min(minY, template[k].y); + if (k < templateLength - 1 && template[k].y === template[k + 1].y && template[k].x === template[k + 1].x - 1) { + reuseMask |= 1 << templateLength - 1 - k; + } else { + changingTemplateEntries.push(k); + } + } + var changingEntriesLength = changingTemplateEntries.length; + var changingTemplateX = new Int8Array(changingEntriesLength); + var changingTemplateY = new Int8Array(changingEntriesLength); + var changingTemplateBit = new Uint16Array(changingEntriesLength); + for (c = 0; c < changingEntriesLength; c++) { + k = changingTemplateEntries[c]; + changingTemplateX[c] = template[k].x; + changingTemplateY[c] = template[k].y; + changingTemplateBit[c] = 1 << templateLength - 1 - k; + } + var sbb_left = -minX; + var sbb_top = -minY; + var sbb_right = width - maxX; + var pseudoPixelContext = ReusedContexts[templateIndex]; + var row = new Uint8Array(width); + var bitmap = []; + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GB'); + var ltp = 0, j, i0, j0, contextLabel = 0, bit, shift; + for (var i = 0; i < height; i++) { + if (prediction) { + var sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + bitmap.push(row); + continue; + } + } + row = new Uint8Array(row); + bitmap.push(row); + for (j = 0; j < width; j++) { + if (useskip && skip[i][j]) { + row[j] = 0; + continue; + } + if (j >= sbb_left && j < sbb_right && i >= sbb_top) { + contextLabel = contextLabel << 1 & reuseMask; + for (k = 0; k < changingEntriesLength; k++) { + i0 = i + changingTemplateY[k]; + j0 = j + changingTemplateX[k]; + bit = bitmap[i0][j0]; + if (bit) { + bit = changingTemplateBit[k]; + contextLabel |= bit; + } + } + } else { + contextLabel = 0; + shift = templateLength - 1; + for (k = 0; k < templateLength; k++, shift--) { + j0 = j + templateX[k]; + if (j0 >= 0 && j0 < width) { + i0 = i + templateY[k]; + if (i0 >= 0) { + bit = bitmap[i0][j0]; + if (bit) { + contextLabel |= bit << shift; + } + } + } + } + } + var pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + return bitmap; + } + function decodeRefinement(width, height, templateIndex, referenceBitmap, offsetX, offsetY, prediction, at, decodingContext) { + var codingTemplate = RefinementTemplates[templateIndex].coding; + if (templateIndex === 0) { + codingTemplate = codingTemplate.concat([at[0]]); + } + var codingTemplateLength = codingTemplate.length; + var codingTemplateX = new Int32Array(codingTemplateLength); + var codingTemplateY = new Int32Array(codingTemplateLength); + var k; + for (k = 0; k < codingTemplateLength; k++) { + codingTemplateX[k] = codingTemplate[k].x; + codingTemplateY[k] = codingTemplate[k].y; + } + var referenceTemplate = RefinementTemplates[templateIndex].reference; + if (templateIndex === 0) { + referenceTemplate = referenceTemplate.concat([at[1]]); + } + var referenceTemplateLength = referenceTemplate.length; + var referenceTemplateX = new Int32Array(referenceTemplateLength); + var referenceTemplateY = new Int32Array(referenceTemplateLength); + for (k = 0; k < referenceTemplateLength; k++) { + referenceTemplateX[k] = referenceTemplate[k].x; + referenceTemplateY[k] = referenceTemplate[k].y; + } + var referenceWidth = referenceBitmap[0].length; + var referenceHeight = referenceBitmap.length; + var pseudoPixelContext = RefinementReusedContexts[templateIndex]; + var bitmap = []; + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GR'); + var ltp = 0; + for (var i = 0; i < height; i++) { + if (prediction) { + var sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + error('JBIG2 error: prediction is not supported'); + } + } + var row = new Uint8Array(width); + bitmap.push(row); + for (var j = 0; j < width; j++) { + var i0, j0; + var contextLabel = 0; + for (k = 0; k < codingTemplateLength; k++) { + i0 = i + codingTemplateY[k]; + j0 = j + codingTemplateX[k]; + if (i0 < 0 || j0 < 0 || j0 >= width) { + contextLabel <<= 1; + } else { + contextLabel = contextLabel << 1 | bitmap[i0][j0]; + } + } + for (k = 0; k < referenceTemplateLength; k++) { + i0 = i + referenceTemplateY[k] + offsetY; + j0 = j + referenceTemplateX[k] + offsetX; + if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) { + contextLabel <<= 1; + } else { + contextLabel = contextLabel << 1 | referenceBitmap[i0][j0]; + } + } + var pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + return bitmap; + } + function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext) { + if (huffman) { + error('JBIG2 error: huffman is not supported'); + } + var newSymbols = []; + var currentHeight = 0; + var symbolCodeLength = log2(symbols.length + numberOfNewSymbols); + var decoder = decodingContext.decoder; + var contextCache = decodingContext.contextCache; + while (newSymbols.length < numberOfNewSymbols) { + var deltaHeight = decodeInteger(contextCache, 'IADH', decoder); + currentHeight += deltaHeight; + var currentWidth = 0; + while (true) { + var deltaWidth = decodeInteger(contextCache, 'IADW', decoder); + if (deltaWidth === null) { + break; + } + currentWidth += deltaWidth; + var bitmap; + if (refinement) { + var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder); + if (numberOfInstances > 1) { + bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext); + } else { + var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); + var rdx = decodeInteger(contextCache, 'IARDX', decoder); + var rdy = decodeInteger(contextCache, 'IARDY', decoder); + var symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length]; + bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext); + } + } else { + bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext); + } + newSymbols.push(bitmap); + } + } + var exportedSymbols = []; + var flags = [], currentFlag = false; + var totalSymbolsLength = symbols.length + numberOfNewSymbols; + while (flags.length < totalSymbolsLength) { + var runLength = decodeInteger(contextCache, 'IAEX', decoder); + while (runLength--) { + flags.push(currentFlag); + } + currentFlag = !currentFlag; + } + for (var i = 0, ii = symbols.length; i < ii; i++) { + if (flags[i]) { + exportedSymbols.push(symbols[i]); + } + } + for (var j = 0; j < numberOfNewSymbols; i++, j++) { + if (flags[i]) { + exportedSymbols.push(newSymbols[j]); + } + } + return exportedSymbols; + } + function decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext) { + if (huffman) { + error('JBIG2 error: huffman is not supported'); + } + var bitmap = []; + var i, row; + for (i = 0; i < height; i++) { + row = new Uint8Array(width); + if (defaultPixelValue) { + for (var j = 0; j < width; j++) { + row[j] = defaultPixelValue; + } + } + bitmap.push(row); + } + var decoder = decodingContext.decoder; + var contextCache = decodingContext.contextCache; + var stripT = -decodeInteger(contextCache, 'IADT', decoder); + var firstS = 0; + i = 0; + while (i < numberOfSymbolInstances) { + var deltaT = decodeInteger(contextCache, 'IADT', decoder); + stripT += deltaT; + var deltaFirstS = decodeInteger(contextCache, 'IAFS', decoder); + firstS += deltaFirstS; + var currentS = firstS; + do { + var currentT = stripSize === 1 ? 0 : decodeInteger(contextCache, 'IAIT', decoder); + var t = stripSize * stripT + currentT; + var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); + var applyRefinement = refinement && decodeInteger(contextCache, 'IARI', decoder); + var symbolBitmap = inputSymbols[symbolId]; + var symbolWidth = symbolBitmap[0].length; + var symbolHeight = symbolBitmap.length; + if (applyRefinement) { + var rdw = decodeInteger(contextCache, 'IARDW', decoder); + var rdh = decodeInteger(contextCache, 'IARDH', decoder); + var rdx = decodeInteger(contextCache, 'IARDX', decoder); + var rdy = decodeInteger(contextCache, 'IARDY', decoder); + symbolWidth += rdw; + symbolHeight += rdh; + symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, (rdh >> 1) + rdy, false, refinementAt, decodingContext); + } + var offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight); + var offsetS = currentS - (referenceCorner & 2 ? symbolWidth : 0); + var s2, t2, symbolRow; + if (transposed) { + for (s2 = 0; s2 < symbolHeight; s2++) { + row = bitmap[offsetS + s2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[s2]; + var maxWidth = Math.min(width - offsetT, symbolWidth); + switch (combinationOperator) { + case 0: + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] |= symbolRow[t2]; + } + break; + case 2: + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] ^= symbolRow[t2]; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + ' is not supported'); + } + } + currentS += symbolHeight - 1; + } else { + for (t2 = 0; t2 < symbolHeight; t2++) { + row = bitmap[offsetT + t2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[t2]; + switch (combinationOperator) { + case 0: + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] |= symbolRow[s2]; + } + break; + case 2: + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] ^= symbolRow[s2]; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + ' is not supported'); + } + } + currentS += symbolWidth - 1; + } + i++; + var deltaS = decodeInteger(contextCache, 'IADS', decoder); + if (deltaS === null) { + break; + } + currentS += deltaS + dsOffset; + } while (true); + } + return bitmap; + } + function readSegmentHeader(data, start) { + var segmentHeader = {}; + segmentHeader.number = readUint32(data, start); + var flags = data[start + 4]; + var segmentType = flags & 0x3F; + if (!SegmentTypes[segmentType]) { + error('JBIG2 error: invalid segment type: ' + segmentType); + } + segmentHeader.type = segmentType; + segmentHeader.typeName = SegmentTypes[segmentType]; + segmentHeader.deferredNonRetain = !!(flags & 0x80); + var pageAssociationFieldSize = !!(flags & 0x40); + var referredFlags = data[start + 5]; + var referredToCount = referredFlags >> 5 & 7; + var retainBits = [referredFlags & 31]; + var position = start + 6; + if (referredFlags === 7) { + referredToCount = readUint32(data, position - 1) & 0x1FFFFFFF; + position += 3; + var bytes = referredToCount + 7 >> 3; + retainBits[0] = data[position++]; + while (--bytes > 0) { + retainBits.push(data[position++]); + } + } else if (referredFlags === 5 || referredFlags === 6) { + error('JBIG2 error: invalid referred-to flags'); + } + segmentHeader.retainBits = retainBits; + var referredToSegmentNumberSize = segmentHeader.number <= 256 ? 1 : segmentHeader.number <= 65536 ? 2 : 4; + var referredTo = []; + var i, ii; + for (i = 0; i < referredToCount; i++) { + var number = referredToSegmentNumberSize === 1 ? data[position] : referredToSegmentNumberSize === 2 ? readUint16(data, position) : readUint32(data, position); + referredTo.push(number); + position += referredToSegmentNumberSize; + } + segmentHeader.referredTo = referredTo; + if (!pageAssociationFieldSize) { + segmentHeader.pageAssociation = data[position++]; + } else { + segmentHeader.pageAssociation = readUint32(data, position); + position += 4; + } + segmentHeader.length = readUint32(data, position); + position += 4; + if (segmentHeader.length === 0xFFFFFFFF) { + if (segmentType === 38) { + var genericRegionInfo = readRegionSegmentInformation(data, position); + var genericRegionSegmentFlags = data[position + RegionSegmentInformationFieldLength]; + var genericRegionMmr = !!(genericRegionSegmentFlags & 1); + var searchPatternLength = 6; + var searchPattern = new Uint8Array(searchPatternLength); + if (!genericRegionMmr) { + searchPattern[0] = 0xFF; + searchPattern[1] = 0xAC; + } + searchPattern[2] = genericRegionInfo.height >>> 24 & 0xFF; + searchPattern[3] = genericRegionInfo.height >> 16 & 0xFF; + searchPattern[4] = genericRegionInfo.height >> 8 & 0xFF; + searchPattern[5] = genericRegionInfo.height & 0xFF; + for (i = position, ii = data.length; i < ii; i++) { + var j = 0; + while (j < searchPatternLength && searchPattern[j] === data[i + j]) { + j++; + } + if (j === searchPatternLength) { + segmentHeader.length = i + searchPatternLength; + break; + } + } + if (segmentHeader.length === 0xFFFFFFFF) { + error('JBIG2 error: segment end was not found'); + } + } else { + error('JBIG2 error: invalid unknown segment length'); + } + } + segmentHeader.headerEnd = position; + return segmentHeader; + } + function readSegments(header, data, start, end) { + var segments = []; + var position = start; + while (position < end) { + var segmentHeader = readSegmentHeader(data, position); + position = segmentHeader.headerEnd; + var segment = { + header: segmentHeader, + data: data + }; + if (!header.randomAccess) { + segment.start = position; + position += segmentHeader.length; + segment.end = position; + } + segments.push(segment); + if (segmentHeader.type === 51) { + break; + } + } + if (header.randomAccess) { + for (var i = 0, ii = segments.length; i < ii; i++) { + segments[i].start = position; + position += segments[i].header.length; + segments[i].end = position; + } + } + return segments; + } + function readRegionSegmentInformation(data, start) { + return { + width: readUint32(data, start), + height: readUint32(data, start + 4), + x: readUint32(data, start + 8), + y: readUint32(data, start + 12), + combinationOperator: data[start + 16] & 7 + }; + } + var RegionSegmentInformationFieldLength = 17; + function processSegment(segment, visitor) { + var header = segment.header; + var data = segment.data, position = segment.start, end = segment.end; + var args, at, i, atLength; + switch (header.type) { + case 0: + var dictionary = {}; + var dictionaryFlags = readUint16(data, position); + dictionary.huffman = !!(dictionaryFlags & 1); + dictionary.refinement = !!(dictionaryFlags & 2); + dictionary.huffmanDHSelector = dictionaryFlags >> 2 & 3; + dictionary.huffmanDWSelector = dictionaryFlags >> 4 & 3; + dictionary.bitmapSizeSelector = dictionaryFlags >> 6 & 1; + dictionary.aggregationInstancesSelector = dictionaryFlags >> 7 & 1; + dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256); + dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512); + dictionary.template = dictionaryFlags >> 10 & 3; + dictionary.refinementTemplate = dictionaryFlags >> 12 & 1; + position += 2; + if (!dictionary.huffman) { + atLength = dictionary.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.at = at; + } + if (dictionary.refinement && !dictionary.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.refinementAt = at; + } + dictionary.numberOfExportedSymbols = readUint32(data, position); + position += 4; + dictionary.numberOfNewSymbols = readUint32(data, position); + position += 4; + args = [ + dictionary, + header.number, + header.referredTo, + data, + position, + end + ]; + break; + case 6: + case 7: + var textRegion = {}; + textRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + var textRegionSegmentFlags = readUint16(data, position); + position += 2; + textRegion.huffman = !!(textRegionSegmentFlags & 1); + textRegion.refinement = !!(textRegionSegmentFlags & 2); + textRegion.stripSize = 1 << (textRegionSegmentFlags >> 2 & 3); + textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3; + textRegion.transposed = !!(textRegionSegmentFlags & 64); + textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3; + textRegion.defaultPixelValue = textRegionSegmentFlags >> 9 & 1; + textRegion.dsOffset = textRegionSegmentFlags << 17 >> 27; + textRegion.refinementTemplate = textRegionSegmentFlags >> 15 & 1; + if (textRegion.huffman) { + var textRegionHuffmanFlags = readUint16(data, position); + position += 2; + textRegion.huffmanFS = textRegionHuffmanFlags & 3; + textRegion.huffmanDS = textRegionHuffmanFlags >> 2 & 3; + textRegion.huffmanDT = textRegionHuffmanFlags >> 4 & 3; + textRegion.huffmanRefinementDW = textRegionHuffmanFlags >> 6 & 3; + textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3; + textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3; + textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3; + textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 14); + } + if (textRegion.refinement && !textRegion.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + textRegion.refinementAt = at; + } + textRegion.numberOfSymbolInstances = readUint32(data, position); + position += 4; + if (textRegion.huffman) { + error('JBIG2 error: huffman is not supported'); + } + args = [ + textRegion, + header.referredTo, + data, + position, + end + ]; + break; + case 38: + case 39: + var genericRegion = {}; + genericRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + var genericRegionSegmentFlags = data[position++]; + genericRegion.mmr = !!(genericRegionSegmentFlags & 1); + genericRegion.template = genericRegionSegmentFlags >> 1 & 3; + genericRegion.prediction = !!(genericRegionSegmentFlags & 8); + if (!genericRegion.mmr) { + atLength = genericRegion.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + genericRegion.at = at; + } + args = [ + genericRegion, + data, + position, + end + ]; + break; + case 48: + var pageInfo = { + width: readUint32(data, position), + height: readUint32(data, position + 4), + resolutionX: readUint32(data, position + 8), + resolutionY: readUint32(data, position + 12) + }; + if (pageInfo.height === 0xFFFFFFFF) { + delete pageInfo.height; + } + var pageSegmentFlags = data[position + 16]; + readUint16(data, position + 17); + pageInfo.lossless = !!(pageSegmentFlags & 1); + pageInfo.refinement = !!(pageSegmentFlags & 2); + pageInfo.defaultPixelValue = pageSegmentFlags >> 2 & 1; + pageInfo.combinationOperator = pageSegmentFlags >> 3 & 3; + pageInfo.requiresBuffer = !!(pageSegmentFlags & 32); + pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64); + args = [pageInfo]; + break; + case 49: + break; + case 50: + break; + case 51: + break; + case 62: + break; + default: + error('JBIG2 error: segment type ' + header.typeName + '(' + header.type + ') is not implemented'); + } + var callbackName = 'on' + header.typeName; + if (callbackName in visitor) { + visitor[callbackName].apply(visitor, args); + } + } + function processSegments(segments, visitor) { + for (var i = 0, ii = segments.length; i < ii; i++) { + processSegment(segments[i], visitor); + } + } + function parseJbig2(data, start, end) { + var position = start; + if (data[position] !== 0x97 || data[position + 1] !== 0x4A || data[position + 2] !== 0x42 || data[position + 3] !== 0x32 || data[position + 4] !== 0x0D || data[position + 5] !== 0x0A || data[position + 6] !== 0x1A || data[position + 7] !== 0x0A) { + error('JBIG2 error: invalid header'); + } + var header = {}; + position += 8; + var flags = data[position++]; + header.randomAccess = !(flags & 1); + if (!(flags & 2)) { + header.numberOfPages = readUint32(data, position); + position += 4; + } + readSegments(header, data, position, end); + error('Not implemented'); + } + function parseJbig2Chunks(chunks) { + var visitor = new SimpleSegmentVisitor(); + for (var i = 0, ii = chunks.length; i < ii; i++) { + var chunk = chunks[i]; + var segments = readSegments({}, chunk.data, chunk.start, chunk.end); + processSegments(segments, visitor); + } + return visitor.buffer; + } + function SimpleSegmentVisitor() { + } + SimpleSegmentVisitor.prototype = { + onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) { + this.currentPageInfo = info; + var rowSize = info.width + 7 >> 3; + var buffer = new Uint8Array(rowSize * info.height); + if (info.defaultPixelValue) { + for (var i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] = 0xFF; + } + } + this.buffer = buffer; + }, + drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) { + var pageInfo = this.currentPageInfo; + var width = regionInfo.width, height = regionInfo.height; + var rowSize = pageInfo.width + 7 >> 3; + var combinationOperator = pageInfo.combinationOperatorOverride ? regionInfo.combinationOperator : pageInfo.combinationOperator; + var buffer = this.buffer; + var mask0 = 128 >> (regionInfo.x & 7); + var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3); + var i, j, mask, offset; + switch (combinationOperator) { + case 0: + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer[offset] |= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + case 2: + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer[offset] ^= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + ' is not supported'); + } + }, + onImmediateGenericRegion: function SimpleSegmentVisitor_onImmediateGenericRegion(region, data, start, end) { + var regionInfo = region.info; + var decodingContext = new DecodingContext(data, start, end); + var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, region.template, region.prediction, null, region.at, decodingContext); + this.drawBitmap(regionInfo, bitmap); + }, + onImmediateLosslessGenericRegion: function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() { + this.onImmediateGenericRegion.apply(this, arguments); + }, + onSymbolDictionary: function SimpleSegmentVisitor_onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) { + var huffmanTables; + if (dictionary.huffman) { + error('JBIG2 error: huffman is not supported'); + } + var symbols = this.symbols; + if (!symbols) { + this.symbols = symbols = {}; + } + var inputSymbols = []; + for (var i = 0, ii = referredSegments.length; i < ii; i++) { + inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); + } + var decodingContext = new DecodingContext(data, start, end); + symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext); + }, + onImmediateTextRegion: function SimpleSegmentVisitor_onImmediateTextRegion(region, referredSegments, data, start, end) { + var regionInfo = region.info; + var huffmanTables; + var symbols = this.symbols; + var inputSymbols = []; + for (var i = 0, ii = referredSegments.length; i < ii; i++) { + inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); + } + var symbolCodeLength = log2(inputSymbols.length); + var decodingContext = new DecodingContext(data, start, end); + var bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext); + this.drawBitmap(regionInfo, bitmap); + }, + onImmediateLosslessTextRegion: function SimpleSegmentVisitor_onImmediateLosslessTextRegion() { + this.onImmediateTextRegion.apply(this, arguments); + } + }; + function Jbig2Image() { + } + Jbig2Image.prototype = { + parseChunks: function Jbig2Image_parseChunks(chunks) { + return parseJbig2Chunks(chunks); + } + }; + return Jbig2Image; +}(); +exports.Jbig2Image = Jbig2Image; + +/***/ }), +/* 29 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var error = sharedUtil.error; +var JpegImage = function JpegImageClosure() { + var dctZigZag = new Uint8Array([ + 0, + 1, + 8, + 16, + 9, + 2, + 3, + 10, + 17, + 24, + 32, + 25, + 18, + 11, + 4, + 5, + 12, + 19, + 26, + 33, + 40, + 48, + 41, + 34, + 27, + 20, + 13, + 6, + 7, + 14, + 21, + 28, + 35, + 42, + 49, + 56, + 57, + 50, + 43, + 36, + 29, + 22, + 15, + 23, + 30, + 37, + 44, + 51, + 58, + 59, + 52, + 45, + 38, + 31, + 39, + 46, + 53, + 60, + 61, + 54, + 47, + 55, + 62, + 63 + ]); + var dctCos1 = 4017; + var dctSin1 = 799; + var dctCos3 = 3406; + var dctSin3 = 2276; + var dctCos6 = 1567; + var dctSin6 = 3784; + var dctSqrt2 = 5793; + var dctSqrt1d2 = 2896; + function JpegImage() { + this.decodeTransform = null; + this.colorTransform = -1; + } + function buildHuffmanTable(codeLengths, values) { + var k = 0, code = [], i, j, length = 16; + while (length > 0 && !codeLengths[length - 1]) { + length--; + } + code.push({ + children: [], + index: 0 + }); + var p = code[0], q; + for (i = 0; i < length; i++) { + for (j = 0; j < codeLengths[i]; j++) { + p = code.pop(); + p.children[p.index] = values[k]; + while (p.index > 0) { + p = code.pop(); + } + p.index++; + code.push(p); + while (code.length <= i) { + code.push(q = { + children: [], + index: 0 + }); + p.children[p.index] = q.children; + p = q; + } + k++; + } + if (i + 1 < length) { + code.push(q = { + children: [], + index: 0 + }); + p.children[p.index] = q.children; + p = q; + } + } + return code[0].children; + } + function getBlockBufferOffset(component, row, col) { + return 64 * ((component.blocksPerLine + 1) * row + col); + } + function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive) { + var mcusPerLine = frame.mcusPerLine; + var progressive = frame.progressive; + var startOffset = offset, bitsData = 0, bitsCount = 0; + function readBit() { + if (bitsCount > 0) { + bitsCount--; + return bitsData >> bitsCount & 1; + } + bitsData = data[offset++]; + if (bitsData === 0xFF) { + var nextByte = data[offset++]; + if (nextByte) { + error('JPEG error: unexpected marker ' + (bitsData << 8 | nextByte).toString(16)); + } + } + bitsCount = 7; + return bitsData >>> 7; + } + function decodeHuffman(tree) { + var node = tree; + while (true) { + node = node[readBit()]; + if (typeof node === 'number') { + return node; + } + if (typeof node !== 'object') { + error('JPEG error: invalid huffman sequence'); + } + } + } + function receive(length) { + var n = 0; + while (length > 0) { + n = n << 1 | readBit(); + length--; + } + return n; + } + function receiveAndExtend(length) { + if (length === 1) { + return readBit() === 1 ? 1 : -1; + } + var n = receive(length); + if (n >= 1 << length - 1) { + return n; + } + return n + (-1 << length) + 1; + } + function decodeBaseline(component, offset) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : receiveAndExtend(t); + component.blockData[offset] = component.pred += diff; + var k = 1; + while (k < 64) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + break; + } + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + component.blockData[offset + z] = receiveAndExtend(s); + k++; + } + } + function decodeDCFirst(component, offset) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : receiveAndExtend(t) << successive; + component.blockData[offset] = component.pred += diff; + } + function decodeDCSuccessive(component, offset) { + component.blockData[offset] |= readBit() << successive; + } + var eobrun = 0; + function decodeACFirst(component, offset) { + if (eobrun > 0) { + eobrun--; + return; + } + var k = spectralStart, e = spectralEnd; + while (k <= e) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r) - 1; + break; + } + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + component.blockData[offset + z] = receiveAndExtend(s) * (1 << successive); + k++; + } + } + var successiveACState = 0, successiveACNextValue; + function decodeACSuccessive(component, offset) { + var k = spectralStart; + var e = spectralEnd; + var r = 0; + var s; + var rs; + while (k <= e) { + var z = dctZigZag[k]; + switch (successiveACState) { + case 0: + rs = decodeHuffman(component.huffmanTableAC); + s = rs & 15; + r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r); + successiveACState = 4; + } else { + r = 16; + successiveACState = 1; + } + } else { + if (s !== 1) { + error('JPEG error: invalid ACn encoding'); + } + successiveACNextValue = receiveAndExtend(s); + successiveACState = r ? 2 : 3; + } + continue; + case 1: + case 2: + if (component.blockData[offset + z]) { + component.blockData[offset + z] += readBit() << successive; + } else { + r--; + if (r === 0) { + successiveACState = successiveACState === 2 ? 3 : 0; + } + } + break; + case 3: + if (component.blockData[offset + z]) { + component.blockData[offset + z] += readBit() << successive; + } else { + component.blockData[offset + z] = successiveACNextValue << successive; + successiveACState = 0; + } + break; + case 4: + if (component.blockData[offset + z]) { + component.blockData[offset + z] += readBit() << successive; + } + break; + } + k++; + } + if (successiveACState === 4) { + eobrun--; + if (eobrun === 0) { + successiveACState = 0; + } + } + } + function decodeMcu(component, decode, mcu, row, col) { + var mcuRow = mcu / mcusPerLine | 0; + var mcuCol = mcu % mcusPerLine; + var blockRow = mcuRow * component.v + row; + var blockCol = mcuCol * component.h + col; + var offset = getBlockBufferOffset(component, blockRow, blockCol); + decode(component, offset); + } + function decodeBlock(component, decode, mcu) { + var blockRow = mcu / component.blocksPerLine | 0; + var blockCol = mcu % component.blocksPerLine; + var offset = getBlockBufferOffset(component, blockRow, blockCol); + decode(component, offset); + } + var componentsLength = components.length; + var component, i, j, k, n; + var decodeFn; + if (progressive) { + if (spectralStart === 0) { + decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; + } else { + decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; + } + } else { + decodeFn = decodeBaseline; + } + var mcu = 0, marker; + var mcuExpected; + if (componentsLength === 1) { + mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn; + } else { + mcuExpected = mcusPerLine * frame.mcusPerColumn; + } + if (!resetInterval) { + resetInterval = mcuExpected; + } + var h, v; + while (mcu < mcuExpected) { + for (i = 0; i < componentsLength; i++) { + components[i].pred = 0; + } + eobrun = 0; + if (componentsLength === 1) { + component = components[0]; + for (n = 0; n < resetInterval; n++) { + decodeBlock(component, decodeFn, mcu); + mcu++; + } + } else { + for (n = 0; n < resetInterval; n++) { + for (i = 0; i < componentsLength; i++) { + component = components[i]; + h = component.h; + v = component.v; + for (j = 0; j < v; j++) { + for (k = 0; k < h; k++) { + decodeMcu(component, decodeFn, mcu, j, k); + } + } + } + mcu++; + } + } + bitsCount = 0; + marker = data[offset] << 8 | data[offset + 1]; + while (data[offset] === 0x00 && offset < data.length - 1) { + offset++; + marker = data[offset] << 8 | data[offset + 1]; + } + if (marker <= 0xFF00) { + error('JPEG error: marker was not found'); + } + if (marker >= 0xFFD0 && marker <= 0xFFD7) { + offset += 2; + } else { + break; + } + } + return offset - startOffset; + } + function quantizeAndInverse(component, blockBufferOffset, p) { + var qt = component.quantizationTable, blockData = component.blockData; + var v0, v1, v2, v3, v4, v5, v6, v7; + var p0, p1, p2, p3, p4, p5, p6, p7; + var t; + if (!qt) { + error('JPEG error: missing required Quantization Table.'); + } + for (var row = 0; row < 64; row += 8) { + p0 = blockData[blockBufferOffset + row]; + p1 = blockData[blockBufferOffset + row + 1]; + p2 = blockData[blockBufferOffset + row + 2]; + p3 = blockData[blockBufferOffset + row + 3]; + p4 = blockData[blockBufferOffset + row + 4]; + p5 = blockData[blockBufferOffset + row + 5]; + p6 = blockData[blockBufferOffset + row + 6]; + p7 = blockData[blockBufferOffset + row + 7]; + p0 *= qt[row]; + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = dctSqrt2 * p0 + 512 >> 10; + p[row] = t; + p[row + 1] = t; + p[row + 2] = t; + p[row + 3] = t; + p[row + 4] = t; + p[row + 5] = t; + p[row + 6] = t; + p[row + 7] = t; + continue; + } + p1 *= qt[row + 1]; + p2 *= qt[row + 2]; + p3 *= qt[row + 3]; + p4 *= qt[row + 4]; + p5 *= qt[row + 5]; + p6 *= qt[row + 6]; + p7 *= qt[row + 7]; + v0 = dctSqrt2 * p0 + 128 >> 8; + v1 = dctSqrt2 * p4 + 128 >> 8; + v2 = p2; + v3 = p6; + v4 = dctSqrt1d2 * (p1 - p7) + 128 >> 8; + v7 = dctSqrt1d2 * (p1 + p7) + 128 >> 8; + v5 = p3 << 4; + v6 = p5 << 4; + v0 = v0 + v1 + 1 >> 1; + v1 = v0 - v1; + t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8; + v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8; + v3 = t; + v4 = v4 + v6 + 1 >> 1; + v6 = v4 - v6; + v7 = v7 + v5 + 1 >> 1; + v5 = v7 - v5; + v0 = v0 + v3 + 1 >> 1; + v3 = v0 - v3; + v1 = v1 + v2 + 1 >> 1; + v2 = v1 - v2; + t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; + v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; + v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; + v6 = t; + p[row] = v0 + v7; + p[row + 7] = v0 - v7; + p[row + 1] = v1 + v6; + p[row + 6] = v1 - v6; + p[row + 2] = v2 + v5; + p[row + 5] = v2 - v5; + p[row + 3] = v3 + v4; + p[row + 4] = v3 - v4; + } + for (var col = 0; col < 8; ++col) { + p0 = p[col]; + p1 = p[col + 8]; + p2 = p[col + 16]; + p3 = p[col + 24]; + p4 = p[col + 32]; + p5 = p[col + 40]; + p6 = p[col + 48]; + p7 = p[col + 56]; + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = dctSqrt2 * p0 + 8192 >> 14; + t = t < -2040 ? 0 : t >= 2024 ? 255 : t + 2056 >> 4; + blockData[blockBufferOffset + col] = t; + blockData[blockBufferOffset + col + 8] = t; + blockData[blockBufferOffset + col + 16] = t; + blockData[blockBufferOffset + col + 24] = t; + blockData[blockBufferOffset + col + 32] = t; + blockData[blockBufferOffset + col + 40] = t; + blockData[blockBufferOffset + col + 48] = t; + blockData[blockBufferOffset + col + 56] = t; + continue; + } + v0 = dctSqrt2 * p0 + 2048 >> 12; + v1 = dctSqrt2 * p4 + 2048 >> 12; + v2 = p2; + v3 = p6; + v4 = dctSqrt1d2 * (p1 - p7) + 2048 >> 12; + v7 = dctSqrt1d2 * (p1 + p7) + 2048 >> 12; + v5 = p3; + v6 = p5; + v0 = (v0 + v1 + 1 >> 1) + 4112; + v1 = v0 - v1; + t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12; + v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12; + v3 = t; + v4 = v4 + v6 + 1 >> 1; + v6 = v4 - v6; + v7 = v7 + v5 + 1 >> 1; + v5 = v7 - v5; + v0 = v0 + v3 + 1 >> 1; + v3 = v0 - v3; + v1 = v1 + v2 + 1 >> 1; + v2 = v1 - v2; + t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; + v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; + v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; + v6 = t; + p0 = v0 + v7; + p7 = v0 - v7; + p1 = v1 + v6; + p6 = v1 - v6; + p2 = v2 + v5; + p5 = v2 - v5; + p3 = v3 + v4; + p4 = v3 - v4; + p0 = p0 < 16 ? 0 : p0 >= 4080 ? 255 : p0 >> 4; + p1 = p1 < 16 ? 0 : p1 >= 4080 ? 255 : p1 >> 4; + p2 = p2 < 16 ? 0 : p2 >= 4080 ? 255 : p2 >> 4; + p3 = p3 < 16 ? 0 : p3 >= 4080 ? 255 : p3 >> 4; + p4 = p4 < 16 ? 0 : p4 >= 4080 ? 255 : p4 >> 4; + p5 = p5 < 16 ? 0 : p5 >= 4080 ? 255 : p5 >> 4; + p6 = p6 < 16 ? 0 : p6 >= 4080 ? 255 : p6 >> 4; + p7 = p7 < 16 ? 0 : p7 >= 4080 ? 255 : p7 >> 4; + blockData[blockBufferOffset + col] = p0; + blockData[blockBufferOffset + col + 8] = p1; + blockData[blockBufferOffset + col + 16] = p2; + blockData[blockBufferOffset + col + 24] = p3; + blockData[blockBufferOffset + col + 32] = p4; + blockData[blockBufferOffset + col + 40] = p5; + blockData[blockBufferOffset + col + 48] = p6; + blockData[blockBufferOffset + col + 56] = p7; + } + } + function buildComponentData(frame, component) { + var blocksPerLine = component.blocksPerLine; + var blocksPerColumn = component.blocksPerColumn; + var computationBuffer = new Int16Array(64); + for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) { + for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) { + var offset = getBlockBufferOffset(component, blockRow, blockCol); + quantizeAndInverse(component, offset, computationBuffer); + } + } + return component.blockData; + } + function clamp0to255(a) { + return a <= 0 ? 0 : a >= 255 ? 255 : a; + } + JpegImage.prototype = { + parse: function parse(data) { + function readUint16() { + var value = data[offset] << 8 | data[offset + 1]; + offset += 2; + return value; + } + function readDataBlock() { + var length = readUint16(); + var array = data.subarray(offset, offset + length - 2); + offset += array.length; + return array; + } + function prepareComponents(frame) { + var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH); + var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV); + for (var i = 0; i < frame.components.length; i++) { + component = frame.components[i]; + var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH); + var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV); + var blocksPerLineForMcu = mcusPerLine * component.h; + var blocksPerColumnForMcu = mcusPerColumn * component.v; + var blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1); + component.blockData = new Int16Array(blocksBufferSize); + component.blocksPerLine = blocksPerLine; + component.blocksPerColumn = blocksPerColumn; + } + frame.mcusPerLine = mcusPerLine; + frame.mcusPerColumn = mcusPerColumn; + } + var offset = 0; + var jfif = null; + var adobe = null; + var frame, resetInterval; + var quantizationTables = []; + var huffmanTablesAC = [], huffmanTablesDC = []; + var fileMarker = readUint16(); + if (fileMarker !== 0xFFD8) { + error('JPEG error: SOI not found'); + } + fileMarker = readUint16(); + while (fileMarker !== 0xFFD9) { + var i, j, l; + switch (fileMarker) { + case 0xFFE0: + case 0xFFE1: + case 0xFFE2: + case 0xFFE3: + case 0xFFE4: + case 0xFFE5: + case 0xFFE6: + case 0xFFE7: + case 0xFFE8: + case 0xFFE9: + case 0xFFEA: + case 0xFFEB: + case 0xFFEC: + case 0xFFED: + case 0xFFEE: + case 0xFFEF: + case 0xFFFE: + var appData = readDataBlock(); + if (fileMarker === 0xFFE0) { + if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 && appData[3] === 0x46 && appData[4] === 0) { + jfif = { + version: { + major: appData[5], + minor: appData[6] + }, + densityUnits: appData[7], + xDensity: appData[8] << 8 | appData[9], + yDensity: appData[10] << 8 | appData[11], + thumbWidth: appData[12], + thumbHeight: appData[13], + thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13]) + }; + } + } + if (fileMarker === 0xFFEE) { + if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F && appData[3] === 0x62 && appData[4] === 0x65) { + adobe = { + version: appData[5] << 8 | appData[6], + flags0: appData[7] << 8 | appData[8], + flags1: appData[9] << 8 | appData[10], + transformCode: appData[11] + }; + } + } + break; + case 0xFFDB: + var quantizationTablesLength = readUint16(); + var quantizationTablesEnd = quantizationTablesLength + offset - 2; + var z; + while (offset < quantizationTablesEnd) { + var quantizationTableSpec = data[offset++]; + var tableData = new Uint16Array(64); + if (quantizationTableSpec >> 4 === 0) { + for (j = 0; j < 64; j++) { + z = dctZigZag[j]; + tableData[z] = data[offset++]; + } + } else if (quantizationTableSpec >> 4 === 1) { + for (j = 0; j < 64; j++) { + z = dctZigZag[j]; + tableData[z] = readUint16(); + } + } else { + error('JPEG error: DQT - invalid table spec'); + } + quantizationTables[quantizationTableSpec & 15] = tableData; + } + break; + case 0xFFC0: + case 0xFFC1: + case 0xFFC2: + if (frame) { + error('JPEG error: Only single frame JPEGs supported'); + } + readUint16(); + frame = {}; + frame.extended = fileMarker === 0xFFC1; + frame.progressive = fileMarker === 0xFFC2; + frame.precision = data[offset++]; + frame.scanLines = readUint16(); + frame.samplesPerLine = readUint16(); + frame.components = []; + frame.componentIds = {}; + var componentsCount = data[offset++], componentId; + var maxH = 0, maxV = 0; + for (i = 0; i < componentsCount; i++) { + componentId = data[offset]; + var h = data[offset + 1] >> 4; + var v = data[offset + 1] & 15; + if (maxH < h) { + maxH = h; + } + if (maxV < v) { + maxV = v; + } + var qId = data[offset + 2]; + l = frame.components.push({ + h: h, + v: v, + quantizationId: qId, + quantizationTable: null + }); + frame.componentIds[componentId] = l - 1; + offset += 3; + } + frame.maxH = maxH; + frame.maxV = maxV; + prepareComponents(frame); + break; + case 0xFFC4: + var huffmanLength = readUint16(); + for (i = 2; i < huffmanLength;) { + var huffmanTableSpec = data[offset++]; + var codeLengths = new Uint8Array(16); + var codeLengthSum = 0; + for (j = 0; j < 16; j++, offset++) { + codeLengthSum += codeLengths[j] = data[offset]; + } + var huffmanValues = new Uint8Array(codeLengthSum); + for (j = 0; j < codeLengthSum; j++, offset++) { + huffmanValues[j] = data[offset]; + } + i += 17 + codeLengthSum; + (huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues); + } + break; + case 0xFFDD: + readUint16(); + resetInterval = readUint16(); + break; + case 0xFFDA: + readUint16(); + var selectorsCount = data[offset++]; + var components = [], component; + for (i = 0; i < selectorsCount; i++) { + var componentIndex = frame.componentIds[data[offset++]]; + component = frame.components[componentIndex]; + var tableSpec = data[offset++]; + component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; + component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; + components.push(component); + } + var spectralStart = data[offset++]; + var spectralEnd = data[offset++]; + var successiveApproximation = data[offset++]; + var processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15); + offset += processed; + break; + case 0xFFFF: + if (data[offset] !== 0xFF) { + offset--; + } + break; + default: + if (data[offset - 3] === 0xFF && data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) { + offset -= 3; + break; + } + error('JPEG error: unknown marker ' + fileMarker.toString(16)); + } + fileMarker = readUint16(); + } + this.width = frame.samplesPerLine; + this.height = frame.scanLines; + this.jfif = jfif; + this.adobe = adobe; + this.components = []; + for (i = 0; i < frame.components.length; i++) { + component = frame.components[i]; + var quantizationTable = quantizationTables[component.quantizationId]; + if (quantizationTable) { + component.quantizationTable = quantizationTable; + } + this.components.push({ + output: buildComponentData(frame, component), + scaleX: component.h / frame.maxH, + scaleY: component.v / frame.maxV, + blocksPerLine: component.blocksPerLine, + blocksPerColumn: component.blocksPerColumn + }); + } + this.numComponents = this.components.length; + }, + _getLinearizedBlockData: function getLinearizedBlockData(width, height) { + var scaleX = this.width / width, scaleY = this.height / height; + var component, componentScaleX, componentScaleY, blocksPerScanline; + var x, y, i, j, k; + var index; + var offset = 0; + var output; + var numComponents = this.components.length; + var dataLength = width * height * numComponents; + var data = new Uint8Array(dataLength); + var xScaleBlockOffset = new Uint32Array(width); + var mask3LSB = 0xfffffff8; + for (i = 0; i < numComponents; i++) { + component = this.components[i]; + componentScaleX = component.scaleX * scaleX; + componentScaleY = component.scaleY * scaleY; + offset = i; + output = component.output; + blocksPerScanline = component.blocksPerLine + 1 << 3; + for (x = 0; x < width; x++) { + j = 0 | x * componentScaleX; + xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7; + } + for (y = 0; y < height; y++) { + j = 0 | y * componentScaleY; + index = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3; + for (x = 0; x < width; x++) { + data[offset] = output[index + xScaleBlockOffset[x]]; + offset += numComponents; + } + } + } + var transform = this.decodeTransform; + if (transform) { + for (i = 0; i < dataLength;) { + for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) { + data[i] = (data[i] * transform[k] >> 8) + transform[k + 1]; + } + } + } + return data; + }, + _isColorConversionNeeded: function isColorConversionNeeded() { + if (this.adobe && this.adobe.transformCode) { + return true; + } else if (this.numComponents === 3) { + if (!this.adobe && this.colorTransform === 0) { + return false; + } + return true; + } + if (!this.adobe && this.colorTransform === 1) { + return true; + } + return false; + }, + _convertYccToRgb: function convertYccToRgb(data) { + var Y, Cb, Cr; + for (var i = 0, length = data.length; i < length; i += 3) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i] = clamp0to255(Y - 179.456 + 1.402 * Cr); + data[i + 1] = clamp0to255(Y + 135.459 - 0.344 * Cb - 0.714 * Cr); + data[i + 2] = clamp0to255(Y - 226.816 + 1.772 * Cb); + } + return data; + }, + _convertYcckToRgb: function convertYcckToRgb(data) { + var Y, Cb, Cr, k; + var offset = 0; + for (var i = 0, length = data.length; i < length; i += 4) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + k = data[i + 3]; + var r = -122.67195406894 + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - 5.4080610064599e-5 * Y + 0.00048449797120281 * k - 0.154362151871126) + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - 0.00477271405408747 * k + 1.53380253221734) + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + 0.48357088451265) + k * (-0.000336197177618394 * k + 0.484791561490776); + var g = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665); + var b = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407); + data[offset++] = clamp0to255(r); + data[offset++] = clamp0to255(g); + data[offset++] = clamp0to255(b); + } + return data; + }, + _convertYcckToCmyk: function convertYcckToCmyk(data) { + var Y, Cb, Cr; + for (var i = 0, length = data.length; i < length; i += 4) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i] = clamp0to255(434.456 - Y - 1.402 * Cr); + data[i + 1] = clamp0to255(119.541 - Y + 0.344 * Cb + 0.714 * Cr); + data[i + 2] = clamp0to255(481.816 - Y - 1.772 * Cb); + } + return data; + }, + _convertCmykToRgb: function convertCmykToRgb(data) { + var c, m, y, k; + var offset = 0; + var min = -255 * 255 * 255; + var scale = 1 / 255 / 255; + for (var i = 0, length = data.length; i < length; i += 4) { + c = data[i]; + m = data[i + 1]; + y = data[i + 2]; + k = data[i + 3]; + var r = c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k - 72734.4411664936) + m * (1.7149763477362134 * m - 5.6096736904047315 * y - 17.873870861415444 * k - 1401.7366389350734) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 4465.541406466231) - k * (21.86122147463605 * k + 48317.86113160301); + var g = c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k - 20220.756542821975) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 48691.05921601825) + y * (4.444339102852739 * y + 9.8632861493405 * k - 6341.191035517494) - k * (20.737325471181034 * k + 47890.15695978492); + var b = c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k - 3616.812083916688) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 28620.90484698408) + y * (0.03296041114873217 * y + 115.60384449646641 * k - 49363.43385999684) - k * (22.33816807309886 * k + 45932.16563550634); + data[offset++] = r >= 0 ? 255 : r <= min ? 0 : 255 + r * scale | 0; + data[offset++] = g >= 0 ? 255 : g <= min ? 0 : 255 + g * scale | 0; + data[offset++] = b >= 0 ? 255 : b <= min ? 0 : 255 + b * scale | 0; + } + return data; + }, + getData: function getData(width, height, forceRGBoutput) { + if (this.numComponents > 4) { + error('JPEG error: Unsupported color mode'); + } + var data = this._getLinearizedBlockData(width, height); + if (this.numComponents === 1 && forceRGBoutput) { + var dataLength = data.length; + var rgbData = new Uint8Array(dataLength * 3); + var offset = 0; + for (var i = 0; i < dataLength; i++) { + var grayColor = data[i]; + rgbData[offset++] = grayColor; + rgbData[offset++] = grayColor; + rgbData[offset++] = grayColor; + } + return rgbData; + } else if (this.numComponents === 3 && this._isColorConversionNeeded()) { + return this._convertYccToRgb(data); + } else if (this.numComponents === 4) { + if (this._isColorConversionNeeded()) { + if (forceRGBoutput) { + return this._convertYcckToRgb(data); + } + return this._convertYcckToCmyk(data); + } else if (forceRGBoutput) { + return this._convertCmykToRgb(data); + } + } + return data; + } + }; + return JpegImage; +}(); +exports.JpegImage = JpegImage; + +/***/ }), +/* 30 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var getLookupTableFactory = sharedUtil.getLookupTableFactory; +var getMetrics = getLookupTableFactory(function (t) { + t['Courier'] = 600; + t['Courier-Bold'] = 600; + t['Courier-BoldOblique'] = 600; + t['Courier-Oblique'] = 600; + t['Helvetica'] = getLookupTableFactory(function (t) { + t['space'] = 278; + t['exclam'] = 278; + t['quotedbl'] = 355; + t['numbersign'] = 556; + t['dollar'] = 556; + t['percent'] = 889; + t['ampersand'] = 667; + t['quoteright'] = 222; + t['parenleft'] = 333; + t['parenright'] = 333; + t['asterisk'] = 389; + t['plus'] = 584; + t['comma'] = 278; + t['hyphen'] = 333; + t['period'] = 278; + t['slash'] = 278; + t['zero'] = 556; + t['one'] = 556; + t['two'] = 556; + t['three'] = 556; + t['four'] = 556; + t['five'] = 556; + t['six'] = 556; + t['seven'] = 556; + t['eight'] = 556; + t['nine'] = 556; + t['colon'] = 278; + t['semicolon'] = 278; + t['less'] = 584; + t['equal'] = 584; + t['greater'] = 584; + t['question'] = 556; + t['at'] = 1015; + t['A'] = 667; + t['B'] = 667; + t['C'] = 722; + t['D'] = 722; + t['E'] = 667; + t['F'] = 611; + t['G'] = 778; + t['H'] = 722; + t['I'] = 278; + t['J'] = 500; + t['K'] = 667; + t['L'] = 556; + t['M'] = 833; + t['N'] = 722; + t['O'] = 778; + t['P'] = 667; + t['Q'] = 778; + t['R'] = 722; + t['S'] = 667; + t['T'] = 611; + t['U'] = 722; + t['V'] = 667; + t['W'] = 944; + t['X'] = 667; + t['Y'] = 667; + t['Z'] = 611; + t['bracketleft'] = 278; + t['backslash'] = 278; + t['bracketright'] = 278; + t['asciicircum'] = 469; + t['underscore'] = 556; + t['quoteleft'] = 222; + t['a'] = 556; + t['b'] = 556; + t['c'] = 500; + t['d'] = 556; + t['e'] = 556; + t['f'] = 278; + t['g'] = 556; + t['h'] = 556; + t['i'] = 222; + t['j'] = 222; + t['k'] = 500; + t['l'] = 222; + t['m'] = 833; + t['n'] = 556; + t['o'] = 556; + t['p'] = 556; + t['q'] = 556; + t['r'] = 333; + t['s'] = 500; + t['t'] = 278; + t['u'] = 556; + t['v'] = 500; + t['w'] = 722; + t['x'] = 500; + t['y'] = 500; + t['z'] = 500; + t['braceleft'] = 334; + t['bar'] = 260; + t['braceright'] = 334; + t['asciitilde'] = 584; + t['exclamdown'] = 333; + t['cent'] = 556; + t['sterling'] = 556; + t['fraction'] = 167; + t['yen'] = 556; + t['florin'] = 556; + t['section'] = 556; + t['currency'] = 556; + t['quotesingle'] = 191; + t['quotedblleft'] = 333; + t['guillemotleft'] = 556; + t['guilsinglleft'] = 333; + t['guilsinglright'] = 333; + t['fi'] = 500; + t['fl'] = 500; + t['endash'] = 556; + t['dagger'] = 556; + t['daggerdbl'] = 556; + t['periodcentered'] = 278; + t['paragraph'] = 537; + t['bullet'] = 350; + t['quotesinglbase'] = 222; + t['quotedblbase'] = 333; + t['quotedblright'] = 333; + t['guillemotright'] = 556; + t['ellipsis'] = 1000; + t['perthousand'] = 1000; + t['questiondown'] = 611; + t['grave'] = 333; + t['acute'] = 333; + t['circumflex'] = 333; + t['tilde'] = 333; + t['macron'] = 333; + t['breve'] = 333; + t['dotaccent'] = 333; + t['dieresis'] = 333; + t['ring'] = 333; + t['cedilla'] = 333; + t['hungarumlaut'] = 333; + t['ogonek'] = 333; + t['caron'] = 333; + t['emdash'] = 1000; + t['AE'] = 1000; + t['ordfeminine'] = 370; + t['Lslash'] = 556; + t['Oslash'] = 778; + t['OE'] = 1000; + t['ordmasculine'] = 365; + t['ae'] = 889; + t['dotlessi'] = 278; + t['lslash'] = 222; + t['oslash'] = 611; + t['oe'] = 944; + t['germandbls'] = 611; + t['Idieresis'] = 278; + t['eacute'] = 556; + t['abreve'] = 556; + t['uhungarumlaut'] = 556; + t['ecaron'] = 556; + t['Ydieresis'] = 667; + t['divide'] = 584; + t['Yacute'] = 667; + t['Acircumflex'] = 667; + t['aacute'] = 556; + t['Ucircumflex'] = 722; + t['yacute'] = 500; + t['scommaaccent'] = 500; + t['ecircumflex'] = 556; + t['Uring'] = 722; + t['Udieresis'] = 722; + t['aogonek'] = 556; + t['Uacute'] = 722; + t['uogonek'] = 556; + t['Edieresis'] = 667; + t['Dcroat'] = 722; + t['commaaccent'] = 250; + t['copyright'] = 737; + t['Emacron'] = 667; + t['ccaron'] = 500; + t['aring'] = 556; + t['Ncommaaccent'] = 722; + t['lacute'] = 222; + t['agrave'] = 556; + t['Tcommaaccent'] = 611; + t['Cacute'] = 722; + t['atilde'] = 556; + t['Edotaccent'] = 667; + t['scaron'] = 500; + t['scedilla'] = 500; + t['iacute'] = 278; + t['lozenge'] = 471; + t['Rcaron'] = 722; + t['Gcommaaccent'] = 778; + t['ucircumflex'] = 556; + t['acircumflex'] = 556; + t['Amacron'] = 667; + t['rcaron'] = 333; + t['ccedilla'] = 500; + t['Zdotaccent'] = 611; + t['Thorn'] = 667; + t['Omacron'] = 778; + t['Racute'] = 722; + t['Sacute'] = 667; + t['dcaron'] = 643; + t['Umacron'] = 722; + t['uring'] = 556; + t['threesuperior'] = 333; + t['Ograve'] = 778; + t['Agrave'] = 667; + t['Abreve'] = 667; + t['multiply'] = 584; + t['uacute'] = 556; + t['Tcaron'] = 611; + t['partialdiff'] = 476; + t['ydieresis'] = 500; + t['Nacute'] = 722; + t['icircumflex'] = 278; + t['Ecircumflex'] = 667; + t['adieresis'] = 556; + t['edieresis'] = 556; + t['cacute'] = 500; + t['nacute'] = 556; + t['umacron'] = 556; + t['Ncaron'] = 722; + t['Iacute'] = 278; + t['plusminus'] = 584; + t['brokenbar'] = 260; + t['registered'] = 737; + t['Gbreve'] = 778; + t['Idotaccent'] = 278; + t['summation'] = 600; + t['Egrave'] = 667; + t['racute'] = 333; + t['omacron'] = 556; + t['Zacute'] = 611; + t['Zcaron'] = 611; + t['greaterequal'] = 549; + t['Eth'] = 722; + t['Ccedilla'] = 722; + t['lcommaaccent'] = 222; + t['tcaron'] = 317; + t['eogonek'] = 556; + t['Uogonek'] = 722; + t['Aacute'] = 667; + t['Adieresis'] = 667; + t['egrave'] = 556; + t['zacute'] = 500; + t['iogonek'] = 222; + t['Oacute'] = 778; + t['oacute'] = 556; + t['amacron'] = 556; + t['sacute'] = 500; + t['idieresis'] = 278; + t['Ocircumflex'] = 778; + t['Ugrave'] = 722; + t['Delta'] = 612; + t['thorn'] = 556; + t['twosuperior'] = 333; + t['Odieresis'] = 778; + t['mu'] = 556; + t['igrave'] = 278; + t['ohungarumlaut'] = 556; + t['Eogonek'] = 667; + t['dcroat'] = 556; + t['threequarters'] = 834; + t['Scedilla'] = 667; + t['lcaron'] = 299; + t['Kcommaaccent'] = 667; + t['Lacute'] = 556; + t['trademark'] = 1000; + t['edotaccent'] = 556; + t['Igrave'] = 278; + t['Imacron'] = 278; + t['Lcaron'] = 556; + t['onehalf'] = 834; + t['lessequal'] = 549; + t['ocircumflex'] = 556; + t['ntilde'] = 556; + t['Uhungarumlaut'] = 722; + t['Eacute'] = 667; + t['emacron'] = 556; + t['gbreve'] = 556; + t['onequarter'] = 834; + t['Scaron'] = 667; + t['Scommaaccent'] = 667; + t['Ohungarumlaut'] = 778; + t['degree'] = 400; + t['ograve'] = 556; + t['Ccaron'] = 722; + t['ugrave'] = 556; + t['radical'] = 453; + t['Dcaron'] = 722; + t['rcommaaccent'] = 333; + t['Ntilde'] = 722; + t['otilde'] = 556; + t['Rcommaaccent'] = 722; + t['Lcommaaccent'] = 556; + t['Atilde'] = 667; + t['Aogonek'] = 667; + t['Aring'] = 667; + t['Otilde'] = 778; + t['zdotaccent'] = 500; + t['Ecaron'] = 667; + t['Iogonek'] = 278; + t['kcommaaccent'] = 500; + t['minus'] = 584; + t['Icircumflex'] = 278; + t['ncaron'] = 556; + t['tcommaaccent'] = 278; + t['logicalnot'] = 584; + t['odieresis'] = 556; + t['udieresis'] = 556; + t['notequal'] = 549; + t['gcommaaccent'] = 556; + t['eth'] = 556; + t['zcaron'] = 500; + t['ncommaaccent'] = 556; + t['onesuperior'] = 333; + t['imacron'] = 278; + t['Euro'] = 556; + }); + t['Helvetica-Bold'] = getLookupTableFactory(function (t) { + t['space'] = 278; + t['exclam'] = 333; + t['quotedbl'] = 474; + t['numbersign'] = 556; + t['dollar'] = 556; + t['percent'] = 889; + t['ampersand'] = 722; + t['quoteright'] = 278; + t['parenleft'] = 333; + t['parenright'] = 333; + t['asterisk'] = 389; + t['plus'] = 584; + t['comma'] = 278; + t['hyphen'] = 333; + t['period'] = 278; + t['slash'] = 278; + t['zero'] = 556; + t['one'] = 556; + t['two'] = 556; + t['three'] = 556; + t['four'] = 556; + t['five'] = 556; + t['six'] = 556; + t['seven'] = 556; + t['eight'] = 556; + t['nine'] = 556; + t['colon'] = 333; + t['semicolon'] = 333; + t['less'] = 584; + t['equal'] = 584; + t['greater'] = 584; + t['question'] = 611; + t['at'] = 975; + t['A'] = 722; + t['B'] = 722; + t['C'] = 722; + t['D'] = 722; + t['E'] = 667; + t['F'] = 611; + t['G'] = 778; + t['H'] = 722; + t['I'] = 278; + t['J'] = 556; + t['K'] = 722; + t['L'] = 611; + t['M'] = 833; + t['N'] = 722; + t['O'] = 778; + t['P'] = 667; + t['Q'] = 778; + t['R'] = 722; + t['S'] = 667; + t['T'] = 611; + t['U'] = 722; + t['V'] = 667; + t['W'] = 944; + t['X'] = 667; + t['Y'] = 667; + t['Z'] = 611; + t['bracketleft'] = 333; + t['backslash'] = 278; + t['bracketright'] = 333; + t['asciicircum'] = 584; + t['underscore'] = 556; + t['quoteleft'] = 278; + t['a'] = 556; + t['b'] = 611; + t['c'] = 556; + t['d'] = 611; + t['e'] = 556; + t['f'] = 333; + t['g'] = 611; + t['h'] = 611; + t['i'] = 278; + t['j'] = 278; + t['k'] = 556; + t['l'] = 278; + t['m'] = 889; + t['n'] = 611; + t['o'] = 611; + t['p'] = 611; + t['q'] = 611; + t['r'] = 389; + t['s'] = 556; + t['t'] = 333; + t['u'] = 611; + t['v'] = 556; + t['w'] = 778; + t['x'] = 556; + t['y'] = 556; + t['z'] = 500; + t['braceleft'] = 389; + t['bar'] = 280; + t['braceright'] = 389; + t['asciitilde'] = 584; + t['exclamdown'] = 333; + t['cent'] = 556; + t['sterling'] = 556; + t['fraction'] = 167; + t['yen'] = 556; + t['florin'] = 556; + t['section'] = 556; + t['currency'] = 556; + t['quotesingle'] = 238; + t['quotedblleft'] = 500; + t['guillemotleft'] = 556; + t['guilsinglleft'] = 333; + t['guilsinglright'] = 333; + t['fi'] = 611; + t['fl'] = 611; + t['endash'] = 556; + t['dagger'] = 556; + t['daggerdbl'] = 556; + t['periodcentered'] = 278; + t['paragraph'] = 556; + t['bullet'] = 350; + t['quotesinglbase'] = 278; + t['quotedblbase'] = 500; + t['quotedblright'] = 500; + t['guillemotright'] = 556; + t['ellipsis'] = 1000; + t['perthousand'] = 1000; + t['questiondown'] = 611; + t['grave'] = 333; + t['acute'] = 333; + t['circumflex'] = 333; + t['tilde'] = 333; + t['macron'] = 333; + t['breve'] = 333; + t['dotaccent'] = 333; + t['dieresis'] = 333; + t['ring'] = 333; + t['cedilla'] = 333; + t['hungarumlaut'] = 333; + t['ogonek'] = 333; + t['caron'] = 333; + t['emdash'] = 1000; + t['AE'] = 1000; + t['ordfeminine'] = 370; + t['Lslash'] = 611; + t['Oslash'] = 778; + t['OE'] = 1000; + t['ordmasculine'] = 365; + t['ae'] = 889; + t['dotlessi'] = 278; + t['lslash'] = 278; + t['oslash'] = 611; + t['oe'] = 944; + t['germandbls'] = 611; + t['Idieresis'] = 278; + t['eacute'] = 556; + t['abreve'] = 556; + t['uhungarumlaut'] = 611; + t['ecaron'] = 556; + t['Ydieresis'] = 667; + t['divide'] = 584; + t['Yacute'] = 667; + t['Acircumflex'] = 722; + t['aacute'] = 556; + t['Ucircumflex'] = 722; + t['yacute'] = 556; + t['scommaaccent'] = 556; + t['ecircumflex'] = 556; + t['Uring'] = 722; + t['Udieresis'] = 722; + t['aogonek'] = 556; + t['Uacute'] = 722; + t['uogonek'] = 611; + t['Edieresis'] = 667; + t['Dcroat'] = 722; + t['commaaccent'] = 250; + t['copyright'] = 737; + t['Emacron'] = 667; + t['ccaron'] = 556; + t['aring'] = 556; + t['Ncommaaccent'] = 722; + t['lacute'] = 278; + t['agrave'] = 556; + t['Tcommaaccent'] = 611; + t['Cacute'] = 722; + t['atilde'] = 556; + t['Edotaccent'] = 667; + t['scaron'] = 556; + t['scedilla'] = 556; + t['iacute'] = 278; + t['lozenge'] = 494; + t['Rcaron'] = 722; + t['Gcommaaccent'] = 778; + t['ucircumflex'] = 611; + t['acircumflex'] = 556; + t['Amacron'] = 722; + t['rcaron'] = 389; + t['ccedilla'] = 556; + t['Zdotaccent'] = 611; + t['Thorn'] = 667; + t['Omacron'] = 778; + t['Racute'] = 722; + t['Sacute'] = 667; + t['dcaron'] = 743; + t['Umacron'] = 722; + t['uring'] = 611; + t['threesuperior'] = 333; + t['Ograve'] = 778; + t['Agrave'] = 722; + t['Abreve'] = 722; + t['multiply'] = 584; + t['uacute'] = 611; + t['Tcaron'] = 611; + t['partialdiff'] = 494; + t['ydieresis'] = 556; + t['Nacute'] = 722; + t['icircumflex'] = 278; + t['Ecircumflex'] = 667; + t['adieresis'] = 556; + t['edieresis'] = 556; + t['cacute'] = 556; + t['nacute'] = 611; + t['umacron'] = 611; + t['Ncaron'] = 722; + t['Iacute'] = 278; + t['plusminus'] = 584; + t['brokenbar'] = 280; + t['registered'] = 737; + t['Gbreve'] = 778; + t['Idotaccent'] = 278; + t['summation'] = 600; + t['Egrave'] = 667; + t['racute'] = 389; + t['omacron'] = 611; + t['Zacute'] = 611; + t['Zcaron'] = 611; + t['greaterequal'] = 549; + t['Eth'] = 722; + t['Ccedilla'] = 722; + t['lcommaaccent'] = 278; + t['tcaron'] = 389; + t['eogonek'] = 556; + t['Uogonek'] = 722; + t['Aacute'] = 722; + t['Adieresis'] = 722; + t['egrave'] = 556; + t['zacute'] = 500; + t['iogonek'] = 278; + t['Oacute'] = 778; + t['oacute'] = 611; + t['amacron'] = 556; + t['sacute'] = 556; + t['idieresis'] = 278; + t['Ocircumflex'] = 778; + t['Ugrave'] = 722; + t['Delta'] = 612; + t['thorn'] = 611; + t['twosuperior'] = 333; + t['Odieresis'] = 778; + t['mu'] = 611; + t['igrave'] = 278; + t['ohungarumlaut'] = 611; + t['Eogonek'] = 667; + t['dcroat'] = 611; + t['threequarters'] = 834; + t['Scedilla'] = 667; + t['lcaron'] = 400; + t['Kcommaaccent'] = 722; + t['Lacute'] = 611; + t['trademark'] = 1000; + t['edotaccent'] = 556; + t['Igrave'] = 278; + t['Imacron'] = 278; + t['Lcaron'] = 611; + t['onehalf'] = 834; + t['lessequal'] = 549; + t['ocircumflex'] = 611; + t['ntilde'] = 611; + t['Uhungarumlaut'] = 722; + t['Eacute'] = 667; + t['emacron'] = 556; + t['gbreve'] = 611; + t['onequarter'] = 834; + t['Scaron'] = 667; + t['Scommaaccent'] = 667; + t['Ohungarumlaut'] = 778; + t['degree'] = 400; + t['ograve'] = 611; + t['Ccaron'] = 722; + t['ugrave'] = 611; + t['radical'] = 549; + t['Dcaron'] = 722; + t['rcommaaccent'] = 389; + t['Ntilde'] = 722; + t['otilde'] = 611; + t['Rcommaaccent'] = 722; + t['Lcommaaccent'] = 611; + t['Atilde'] = 722; + t['Aogonek'] = 722; + t['Aring'] = 722; + t['Otilde'] = 778; + t['zdotaccent'] = 500; + t['Ecaron'] = 667; + t['Iogonek'] = 278; + t['kcommaaccent'] = 556; + t['minus'] = 584; + t['Icircumflex'] = 278; + t['ncaron'] = 611; + t['tcommaaccent'] = 333; + t['logicalnot'] = 584; + t['odieresis'] = 611; + t['udieresis'] = 611; + t['notequal'] = 549; + t['gcommaaccent'] = 611; + t['eth'] = 611; + t['zcaron'] = 500; + t['ncommaaccent'] = 611; + t['onesuperior'] = 333; + t['imacron'] = 278; + t['Euro'] = 556; + }); + t['Helvetica-BoldOblique'] = getLookupTableFactory(function (t) { + t['space'] = 278; + t['exclam'] = 333; + t['quotedbl'] = 474; + t['numbersign'] = 556; + t['dollar'] = 556; + t['percent'] = 889; + t['ampersand'] = 722; + t['quoteright'] = 278; + t['parenleft'] = 333; + t['parenright'] = 333; + t['asterisk'] = 389; + t['plus'] = 584; + t['comma'] = 278; + t['hyphen'] = 333; + t['period'] = 278; + t['slash'] = 278; + t['zero'] = 556; + t['one'] = 556; + t['two'] = 556; + t['three'] = 556; + t['four'] = 556; + t['five'] = 556; + t['six'] = 556; + t['seven'] = 556; + t['eight'] = 556; + t['nine'] = 556; + t['colon'] = 333; + t['semicolon'] = 333; + t['less'] = 584; + t['equal'] = 584; + t['greater'] = 584; + t['question'] = 611; + t['at'] = 975; + t['A'] = 722; + t['B'] = 722; + t['C'] = 722; + t['D'] = 722; + t['E'] = 667; + t['F'] = 611; + t['G'] = 778; + t['H'] = 722; + t['I'] = 278; + t['J'] = 556; + t['K'] = 722; + t['L'] = 611; + t['M'] = 833; + t['N'] = 722; + t['O'] = 778; + t['P'] = 667; + t['Q'] = 778; + t['R'] = 722; + t['S'] = 667; + t['T'] = 611; + t['U'] = 722; + t['V'] = 667; + t['W'] = 944; + t['X'] = 667; + t['Y'] = 667; + t['Z'] = 611; + t['bracketleft'] = 333; + t['backslash'] = 278; + t['bracketright'] = 333; + t['asciicircum'] = 584; + t['underscore'] = 556; + t['quoteleft'] = 278; + t['a'] = 556; + t['b'] = 611; + t['c'] = 556; + t['d'] = 611; + t['e'] = 556; + t['f'] = 333; + t['g'] = 611; + t['h'] = 611; + t['i'] = 278; + t['j'] = 278; + t['k'] = 556; + t['l'] = 278; + t['m'] = 889; + t['n'] = 611; + t['o'] = 611; + t['p'] = 611; + t['q'] = 611; + t['r'] = 389; + t['s'] = 556; + t['t'] = 333; + t['u'] = 611; + t['v'] = 556; + t['w'] = 778; + t['x'] = 556; + t['y'] = 556; + t['z'] = 500; + t['braceleft'] = 389; + t['bar'] = 280; + t['braceright'] = 389; + t['asciitilde'] = 584; + t['exclamdown'] = 333; + t['cent'] = 556; + t['sterling'] = 556; + t['fraction'] = 167; + t['yen'] = 556; + t['florin'] = 556; + t['section'] = 556; + t['currency'] = 556; + t['quotesingle'] = 238; + t['quotedblleft'] = 500; + t['guillemotleft'] = 556; + t['guilsinglleft'] = 333; + t['guilsinglright'] = 333; + t['fi'] = 611; + t['fl'] = 611; + t['endash'] = 556; + t['dagger'] = 556; + t['daggerdbl'] = 556; + t['periodcentered'] = 278; + t['paragraph'] = 556; + t['bullet'] = 350; + t['quotesinglbase'] = 278; + t['quotedblbase'] = 500; + t['quotedblright'] = 500; + t['guillemotright'] = 556; + t['ellipsis'] = 1000; + t['perthousand'] = 1000; + t['questiondown'] = 611; + t['grave'] = 333; + t['acute'] = 333; + t['circumflex'] = 333; + t['tilde'] = 333; + t['macron'] = 333; + t['breve'] = 333; + t['dotaccent'] = 333; + t['dieresis'] = 333; + t['ring'] = 333; + t['cedilla'] = 333; + t['hungarumlaut'] = 333; + t['ogonek'] = 333; + t['caron'] = 333; + t['emdash'] = 1000; + t['AE'] = 1000; + t['ordfeminine'] = 370; + t['Lslash'] = 611; + t['Oslash'] = 778; + t['OE'] = 1000; + t['ordmasculine'] = 365; + t['ae'] = 889; + t['dotlessi'] = 278; + t['lslash'] = 278; + t['oslash'] = 611; + t['oe'] = 944; + t['germandbls'] = 611; + t['Idieresis'] = 278; + t['eacute'] = 556; + t['abreve'] = 556; + t['uhungarumlaut'] = 611; + t['ecaron'] = 556; + t['Ydieresis'] = 667; + t['divide'] = 584; + t['Yacute'] = 667; + t['Acircumflex'] = 722; + t['aacute'] = 556; + t['Ucircumflex'] = 722; + t['yacute'] = 556; + t['scommaaccent'] = 556; + t['ecircumflex'] = 556; + t['Uring'] = 722; + t['Udieresis'] = 722; + t['aogonek'] = 556; + t['Uacute'] = 722; + t['uogonek'] = 611; + t['Edieresis'] = 667; + t['Dcroat'] = 722; + t['commaaccent'] = 250; + t['copyright'] = 737; + t['Emacron'] = 667; + t['ccaron'] = 556; + t['aring'] = 556; + t['Ncommaaccent'] = 722; + t['lacute'] = 278; + t['agrave'] = 556; + t['Tcommaaccent'] = 611; + t['Cacute'] = 722; + t['atilde'] = 556; + t['Edotaccent'] = 667; + t['scaron'] = 556; + t['scedilla'] = 556; + t['iacute'] = 278; + t['lozenge'] = 494; + t['Rcaron'] = 722; + t['Gcommaaccent'] = 778; + t['ucircumflex'] = 611; + t['acircumflex'] = 556; + t['Amacron'] = 722; + t['rcaron'] = 389; + t['ccedilla'] = 556; + t['Zdotaccent'] = 611; + t['Thorn'] = 667; + t['Omacron'] = 778; + t['Racute'] = 722; + t['Sacute'] = 667; + t['dcaron'] = 743; + t['Umacron'] = 722; + t['uring'] = 611; + t['threesuperior'] = 333; + t['Ograve'] = 778; + t['Agrave'] = 722; + t['Abreve'] = 722; + t['multiply'] = 584; + t['uacute'] = 611; + t['Tcaron'] = 611; + t['partialdiff'] = 494; + t['ydieresis'] = 556; + t['Nacute'] = 722; + t['icircumflex'] = 278; + t['Ecircumflex'] = 667; + t['adieresis'] = 556; + t['edieresis'] = 556; + t['cacute'] = 556; + t['nacute'] = 611; + t['umacron'] = 611; + t['Ncaron'] = 722; + t['Iacute'] = 278; + t['plusminus'] = 584; + t['brokenbar'] = 280; + t['registered'] = 737; + t['Gbreve'] = 778; + t['Idotaccent'] = 278; + t['summation'] = 600; + t['Egrave'] = 667; + t['racute'] = 389; + t['omacron'] = 611; + t['Zacute'] = 611; + t['Zcaron'] = 611; + t['greaterequal'] = 549; + t['Eth'] = 722; + t['Ccedilla'] = 722; + t['lcommaaccent'] = 278; + t['tcaron'] = 389; + t['eogonek'] = 556; + t['Uogonek'] = 722; + t['Aacute'] = 722; + t['Adieresis'] = 722; + t['egrave'] = 556; + t['zacute'] = 500; + t['iogonek'] = 278; + t['Oacute'] = 778; + t['oacute'] = 611; + t['amacron'] = 556; + t['sacute'] = 556; + t['idieresis'] = 278; + t['Ocircumflex'] = 778; + t['Ugrave'] = 722; + t['Delta'] = 612; + t['thorn'] = 611; + t['twosuperior'] = 333; + t['Odieresis'] = 778; + t['mu'] = 611; + t['igrave'] = 278; + t['ohungarumlaut'] = 611; + t['Eogonek'] = 667; + t['dcroat'] = 611; + t['threequarters'] = 834; + t['Scedilla'] = 667; + t['lcaron'] = 400; + t['Kcommaaccent'] = 722; + t['Lacute'] = 611; + t['trademark'] = 1000; + t['edotaccent'] = 556; + t['Igrave'] = 278; + t['Imacron'] = 278; + t['Lcaron'] = 611; + t['onehalf'] = 834; + t['lessequal'] = 549; + t['ocircumflex'] = 611; + t['ntilde'] = 611; + t['Uhungarumlaut'] = 722; + t['Eacute'] = 667; + t['emacron'] = 556; + t['gbreve'] = 611; + t['onequarter'] = 834; + t['Scaron'] = 667; + t['Scommaaccent'] = 667; + t['Ohungarumlaut'] = 778; + t['degree'] = 400; + t['ograve'] = 611; + t['Ccaron'] = 722; + t['ugrave'] = 611; + t['radical'] = 549; + t['Dcaron'] = 722; + t['rcommaaccent'] = 389; + t['Ntilde'] = 722; + t['otilde'] = 611; + t['Rcommaaccent'] = 722; + t['Lcommaaccent'] = 611; + t['Atilde'] = 722; + t['Aogonek'] = 722; + t['Aring'] = 722; + t['Otilde'] = 778; + t['zdotaccent'] = 500; + t['Ecaron'] = 667; + t['Iogonek'] = 278; + t['kcommaaccent'] = 556; + t['minus'] = 584; + t['Icircumflex'] = 278; + t['ncaron'] = 611; + t['tcommaaccent'] = 333; + t['logicalnot'] = 584; + t['odieresis'] = 611; + t['udieresis'] = 611; + t['notequal'] = 549; + t['gcommaaccent'] = 611; + t['eth'] = 611; + t['zcaron'] = 500; + t['ncommaaccent'] = 611; + t['onesuperior'] = 333; + t['imacron'] = 278; + t['Euro'] = 556; + }); + t['Helvetica-Oblique'] = getLookupTableFactory(function (t) { + t['space'] = 278; + t['exclam'] = 278; + t['quotedbl'] = 355; + t['numbersign'] = 556; + t['dollar'] = 556; + t['percent'] = 889; + t['ampersand'] = 667; + t['quoteright'] = 222; + t['parenleft'] = 333; + t['parenright'] = 333; + t['asterisk'] = 389; + t['plus'] = 584; + t['comma'] = 278; + t['hyphen'] = 333; + t['period'] = 278; + t['slash'] = 278; + t['zero'] = 556; + t['one'] = 556; + t['two'] = 556; + t['three'] = 556; + t['four'] = 556; + t['five'] = 556; + t['six'] = 556; + t['seven'] = 556; + t['eight'] = 556; + t['nine'] = 556; + t['colon'] = 278; + t['semicolon'] = 278; + t['less'] = 584; + t['equal'] = 584; + t['greater'] = 584; + t['question'] = 556; + t['at'] = 1015; + t['A'] = 667; + t['B'] = 667; + t['C'] = 722; + t['D'] = 722; + t['E'] = 667; + t['F'] = 611; + t['G'] = 778; + t['H'] = 722; + t['I'] = 278; + t['J'] = 500; + t['K'] = 667; + t['L'] = 556; + t['M'] = 833; + t['N'] = 722; + t['O'] = 778; + t['P'] = 667; + t['Q'] = 778; + t['R'] = 722; + t['S'] = 667; + t['T'] = 611; + t['U'] = 722; + t['V'] = 667; + t['W'] = 944; + t['X'] = 667; + t['Y'] = 667; + t['Z'] = 611; + t['bracketleft'] = 278; + t['backslash'] = 278; + t['bracketright'] = 278; + t['asciicircum'] = 469; + t['underscore'] = 556; + t['quoteleft'] = 222; + t['a'] = 556; + t['b'] = 556; + t['c'] = 500; + t['d'] = 556; + t['e'] = 556; + t['f'] = 278; + t['g'] = 556; + t['h'] = 556; + t['i'] = 222; + t['j'] = 222; + t['k'] = 500; + t['l'] = 222; + t['m'] = 833; + t['n'] = 556; + t['o'] = 556; + t['p'] = 556; + t['q'] = 556; + t['r'] = 333; + t['s'] = 500; + t['t'] = 278; + t['u'] = 556; + t['v'] = 500; + t['w'] = 722; + t['x'] = 500; + t['y'] = 500; + t['z'] = 500; + t['braceleft'] = 334; + t['bar'] = 260; + t['braceright'] = 334; + t['asciitilde'] = 584; + t['exclamdown'] = 333; + t['cent'] = 556; + t['sterling'] = 556; + t['fraction'] = 167; + t['yen'] = 556; + t['florin'] = 556; + t['section'] = 556; + t['currency'] = 556; + t['quotesingle'] = 191; + t['quotedblleft'] = 333; + t['guillemotleft'] = 556; + t['guilsinglleft'] = 333; + t['guilsinglright'] = 333; + t['fi'] = 500; + t['fl'] = 500; + t['endash'] = 556; + t['dagger'] = 556; + t['daggerdbl'] = 556; + t['periodcentered'] = 278; + t['paragraph'] = 537; + t['bullet'] = 350; + t['quotesinglbase'] = 222; + t['quotedblbase'] = 333; + t['quotedblright'] = 333; + t['guillemotright'] = 556; + t['ellipsis'] = 1000; + t['perthousand'] = 1000; + t['questiondown'] = 611; + t['grave'] = 333; + t['acute'] = 333; + t['circumflex'] = 333; + t['tilde'] = 333; + t['macron'] = 333; + t['breve'] = 333; + t['dotaccent'] = 333; + t['dieresis'] = 333; + t['ring'] = 333; + t['cedilla'] = 333; + t['hungarumlaut'] = 333; + t['ogonek'] = 333; + t['caron'] = 333; + t['emdash'] = 1000; + t['AE'] = 1000; + t['ordfeminine'] = 370; + t['Lslash'] = 556; + t['Oslash'] = 778; + t['OE'] = 1000; + t['ordmasculine'] = 365; + t['ae'] = 889; + t['dotlessi'] = 278; + t['lslash'] = 222; + t['oslash'] = 611; + t['oe'] = 944; + t['germandbls'] = 611; + t['Idieresis'] = 278; + t['eacute'] = 556; + t['abreve'] = 556; + t['uhungarumlaut'] = 556; + t['ecaron'] = 556; + t['Ydieresis'] = 667; + t['divide'] = 584; + t['Yacute'] = 667; + t['Acircumflex'] = 667; + t['aacute'] = 556; + t['Ucircumflex'] = 722; + t['yacute'] = 500; + t['scommaaccent'] = 500; + t['ecircumflex'] = 556; + t['Uring'] = 722; + t['Udieresis'] = 722; + t['aogonek'] = 556; + t['Uacute'] = 722; + t['uogonek'] = 556; + t['Edieresis'] = 667; + t['Dcroat'] = 722; + t['commaaccent'] = 250; + t['copyright'] = 737; + t['Emacron'] = 667; + t['ccaron'] = 500; + t['aring'] = 556; + t['Ncommaaccent'] = 722; + t['lacute'] = 222; + t['agrave'] = 556; + t['Tcommaaccent'] = 611; + t['Cacute'] = 722; + t['atilde'] = 556; + t['Edotaccent'] = 667; + t['scaron'] = 500; + t['scedilla'] = 500; + t['iacute'] = 278; + t['lozenge'] = 471; + t['Rcaron'] = 722; + t['Gcommaaccent'] = 778; + t['ucircumflex'] = 556; + t['acircumflex'] = 556; + t['Amacron'] = 667; + t['rcaron'] = 333; + t['ccedilla'] = 500; + t['Zdotaccent'] = 611; + t['Thorn'] = 667; + t['Omacron'] = 778; + t['Racute'] = 722; + t['Sacute'] = 667; + t['dcaron'] = 643; + t['Umacron'] = 722; + t['uring'] = 556; + t['threesuperior'] = 333; + t['Ograve'] = 778; + t['Agrave'] = 667; + t['Abreve'] = 667; + t['multiply'] = 584; + t['uacute'] = 556; + t['Tcaron'] = 611; + t['partialdiff'] = 476; + t['ydieresis'] = 500; + t['Nacute'] = 722; + t['icircumflex'] = 278; + t['Ecircumflex'] = 667; + t['adieresis'] = 556; + t['edieresis'] = 556; + t['cacute'] = 500; + t['nacute'] = 556; + t['umacron'] = 556; + t['Ncaron'] = 722; + t['Iacute'] = 278; + t['plusminus'] = 584; + t['brokenbar'] = 260; + t['registered'] = 737; + t['Gbreve'] = 778; + t['Idotaccent'] = 278; + t['summation'] = 600; + t['Egrave'] = 667; + t['racute'] = 333; + t['omacron'] = 556; + t['Zacute'] = 611; + t['Zcaron'] = 611; + t['greaterequal'] = 549; + t['Eth'] = 722; + t['Ccedilla'] = 722; + t['lcommaaccent'] = 222; + t['tcaron'] = 317; + t['eogonek'] = 556; + t['Uogonek'] = 722; + t['Aacute'] = 667; + t['Adieresis'] = 667; + t['egrave'] = 556; + t['zacute'] = 500; + t['iogonek'] = 222; + t['Oacute'] = 778; + t['oacute'] = 556; + t['amacron'] = 556; + t['sacute'] = 500; + t['idieresis'] = 278; + t['Ocircumflex'] = 778; + t['Ugrave'] = 722; + t['Delta'] = 612; + t['thorn'] = 556; + t['twosuperior'] = 333; + t['Odieresis'] = 778; + t['mu'] = 556; + t['igrave'] = 278; + t['ohungarumlaut'] = 556; + t['Eogonek'] = 667; + t['dcroat'] = 556; + t['threequarters'] = 834; + t['Scedilla'] = 667; + t['lcaron'] = 299; + t['Kcommaaccent'] = 667; + t['Lacute'] = 556; + t['trademark'] = 1000; + t['edotaccent'] = 556; + t['Igrave'] = 278; + t['Imacron'] = 278; + t['Lcaron'] = 556; + t['onehalf'] = 834; + t['lessequal'] = 549; + t['ocircumflex'] = 556; + t['ntilde'] = 556; + t['Uhungarumlaut'] = 722; + t['Eacute'] = 667; + t['emacron'] = 556; + t['gbreve'] = 556; + t['onequarter'] = 834; + t['Scaron'] = 667; + t['Scommaaccent'] = 667; + t['Ohungarumlaut'] = 778; + t['degree'] = 400; + t['ograve'] = 556; + t['Ccaron'] = 722; + t['ugrave'] = 556; + t['radical'] = 453; + t['Dcaron'] = 722; + t['rcommaaccent'] = 333; + t['Ntilde'] = 722; + t['otilde'] = 556; + t['Rcommaaccent'] = 722; + t['Lcommaaccent'] = 556; + t['Atilde'] = 667; + t['Aogonek'] = 667; + t['Aring'] = 667; + t['Otilde'] = 778; + t['zdotaccent'] = 500; + t['Ecaron'] = 667; + t['Iogonek'] = 278; + t['kcommaaccent'] = 500; + t['minus'] = 584; + t['Icircumflex'] = 278; + t['ncaron'] = 556; + t['tcommaaccent'] = 278; + t['logicalnot'] = 584; + t['odieresis'] = 556; + t['udieresis'] = 556; + t['notequal'] = 549; + t['gcommaaccent'] = 556; + t['eth'] = 556; + t['zcaron'] = 500; + t['ncommaaccent'] = 556; + t['onesuperior'] = 333; + t['imacron'] = 278; + t['Euro'] = 556; + }); + t['Symbol'] = getLookupTableFactory(function (t) { + t['space'] = 250; + t['exclam'] = 333; + t['universal'] = 713; + t['numbersign'] = 500; + t['existential'] = 549; + t['percent'] = 833; + t['ampersand'] = 778; + t['suchthat'] = 439; + t['parenleft'] = 333; + t['parenright'] = 333; + t['asteriskmath'] = 500; + t['plus'] = 549; + t['comma'] = 250; + t['minus'] = 549; + t['period'] = 250; + t['slash'] = 278; + t['zero'] = 500; + t['one'] = 500; + t['two'] = 500; + t['three'] = 500; + t['four'] = 500; + t['five'] = 500; + t['six'] = 500; + t['seven'] = 500; + t['eight'] = 500; + t['nine'] = 500; + t['colon'] = 278; + t['semicolon'] = 278; + t['less'] = 549; + t['equal'] = 549; + t['greater'] = 549; + t['question'] = 444; + t['congruent'] = 549; + t['Alpha'] = 722; + t['Beta'] = 667; + t['Chi'] = 722; + t['Delta'] = 612; + t['Epsilon'] = 611; + t['Phi'] = 763; + t['Gamma'] = 603; + t['Eta'] = 722; + t['Iota'] = 333; + t['theta1'] = 631; + t['Kappa'] = 722; + t['Lambda'] = 686; + t['Mu'] = 889; + t['Nu'] = 722; + t['Omicron'] = 722; + t['Pi'] = 768; + t['Theta'] = 741; + t['Rho'] = 556; + t['Sigma'] = 592; + t['Tau'] = 611; + t['Upsilon'] = 690; + t['sigma1'] = 439; + t['Omega'] = 768; + t['Xi'] = 645; + t['Psi'] = 795; + t['Zeta'] = 611; + t['bracketleft'] = 333; + t['therefore'] = 863; + t['bracketright'] = 333; + t['perpendicular'] = 658; + t['underscore'] = 500; + t['radicalex'] = 500; + t['alpha'] = 631; + t['beta'] = 549; + t['chi'] = 549; + t['delta'] = 494; + t['epsilon'] = 439; + t['phi'] = 521; + t['gamma'] = 411; + t['eta'] = 603; + t['iota'] = 329; + t['phi1'] = 603; + t['kappa'] = 549; + t['lambda'] = 549; + t['mu'] = 576; + t['nu'] = 521; + t['omicron'] = 549; + t['pi'] = 549; + t['theta'] = 521; + t['rho'] = 549; + t['sigma'] = 603; + t['tau'] = 439; + t['upsilon'] = 576; + t['omega1'] = 713; + t['omega'] = 686; + t['xi'] = 493; + t['psi'] = 686; + t['zeta'] = 494; + t['braceleft'] = 480; + t['bar'] = 200; + t['braceright'] = 480; + t['similar'] = 549; + t['Euro'] = 750; + t['Upsilon1'] = 620; + t['minute'] = 247; + t['lessequal'] = 549; + t['fraction'] = 167; + t['infinity'] = 713; + t['florin'] = 500; + t['club'] = 753; + t['diamond'] = 753; + t['heart'] = 753; + t['spade'] = 753; + t['arrowboth'] = 1042; + t['arrowleft'] = 987; + t['arrowup'] = 603; + t['arrowright'] = 987; + t['arrowdown'] = 603; + t['degree'] = 400; + t['plusminus'] = 549; + t['second'] = 411; + t['greaterequal'] = 549; + t['multiply'] = 549; + t['proportional'] = 713; + t['partialdiff'] = 494; + t['bullet'] = 460; + t['divide'] = 549; + t['notequal'] = 549; + t['equivalence'] = 549; + t['approxequal'] = 549; + t['ellipsis'] = 1000; + t['arrowvertex'] = 603; + t['arrowhorizex'] = 1000; + t['carriagereturn'] = 658; + t['aleph'] = 823; + t['Ifraktur'] = 686; + t['Rfraktur'] = 795; + t['weierstrass'] = 987; + t['circlemultiply'] = 768; + t['circleplus'] = 768; + t['emptyset'] = 823; + t['intersection'] = 768; + t['union'] = 768; + t['propersuperset'] = 713; + t['reflexsuperset'] = 713; + t['notsubset'] = 713; + t['propersubset'] = 713; + t['reflexsubset'] = 713; + t['element'] = 713; + t['notelement'] = 713; + t['angle'] = 768; + t['gradient'] = 713; + t['registerserif'] = 790; + t['copyrightserif'] = 790; + t['trademarkserif'] = 890; + t['product'] = 823; + t['radical'] = 549; + t['dotmath'] = 250; + t['logicalnot'] = 713; + t['logicaland'] = 603; + t['logicalor'] = 603; + t['arrowdblboth'] = 1042; + t['arrowdblleft'] = 987; + t['arrowdblup'] = 603; + t['arrowdblright'] = 987; + t['arrowdbldown'] = 603; + t['lozenge'] = 494; + t['angleleft'] = 329; + t['registersans'] = 790; + t['copyrightsans'] = 790; + t['trademarksans'] = 786; + t['summation'] = 713; + t['parenlefttp'] = 384; + t['parenleftex'] = 384; + t['parenleftbt'] = 384; + t['bracketlefttp'] = 384; + t['bracketleftex'] = 384; + t['bracketleftbt'] = 384; + t['bracelefttp'] = 494; + t['braceleftmid'] = 494; + t['braceleftbt'] = 494; + t['braceex'] = 494; + t['angleright'] = 329; + t['integral'] = 274; + t['integraltp'] = 686; + t['integralex'] = 686; + t['integralbt'] = 686; + t['parenrighttp'] = 384; + t['parenrightex'] = 384; + t['parenrightbt'] = 384; + t['bracketrighttp'] = 384; + t['bracketrightex'] = 384; + t['bracketrightbt'] = 384; + t['bracerighttp'] = 494; + t['bracerightmid'] = 494; + t['bracerightbt'] = 494; + t['apple'] = 790; + }); + t['Times-Roman'] = getLookupTableFactory(function (t) { + t['space'] = 250; + t['exclam'] = 333; + t['quotedbl'] = 408; + t['numbersign'] = 500; + t['dollar'] = 500; + t['percent'] = 833; + t['ampersand'] = 778; + t['quoteright'] = 333; + t['parenleft'] = 333; + t['parenright'] = 333; + t['asterisk'] = 500; + t['plus'] = 564; + t['comma'] = 250; + t['hyphen'] = 333; + t['period'] = 250; + t['slash'] = 278; + t['zero'] = 500; + t['one'] = 500; + t['two'] = 500; + t['three'] = 500; + t['four'] = 500; + t['five'] = 500; + t['six'] = 500; + t['seven'] = 500; + t['eight'] = 500; + t['nine'] = 500; + t['colon'] = 278; + t['semicolon'] = 278; + t['less'] = 564; + t['equal'] = 564; + t['greater'] = 564; + t['question'] = 444; + t['at'] = 921; + t['A'] = 722; + t['B'] = 667; + t['C'] = 667; + t['D'] = 722; + t['E'] = 611; + t['F'] = 556; + t['G'] = 722; + t['H'] = 722; + t['I'] = 333; + t['J'] = 389; + t['K'] = 722; + t['L'] = 611; + t['M'] = 889; + t['N'] = 722; + t['O'] = 722; + t['P'] = 556; + t['Q'] = 722; + t['R'] = 667; + t['S'] = 556; + t['T'] = 611; + t['U'] = 722; + t['V'] = 722; + t['W'] = 944; + t['X'] = 722; + t['Y'] = 722; + t['Z'] = 611; + t['bracketleft'] = 333; + t['backslash'] = 278; + t['bracketright'] = 333; + t['asciicircum'] = 469; + t['underscore'] = 500; + t['quoteleft'] = 333; + t['a'] = 444; + t['b'] = 500; + t['c'] = 444; + t['d'] = 500; + t['e'] = 444; + t['f'] = 333; + t['g'] = 500; + t['h'] = 500; + t['i'] = 278; + t['j'] = 278; + t['k'] = 500; + t['l'] = 278; + t['m'] = 778; + t['n'] = 500; + t['o'] = 500; + t['p'] = 500; + t['q'] = 500; + t['r'] = 333; + t['s'] = 389; + t['t'] = 278; + t['u'] = 500; + t['v'] = 500; + t['w'] = 722; + t['x'] = 500; + t['y'] = 500; + t['z'] = 444; + t['braceleft'] = 480; + t['bar'] = 200; + t['braceright'] = 480; + t['asciitilde'] = 541; + t['exclamdown'] = 333; + t['cent'] = 500; + t['sterling'] = 500; + t['fraction'] = 167; + t['yen'] = 500; + t['florin'] = 500; + t['section'] = 500; + t['currency'] = 500; + t['quotesingle'] = 180; + t['quotedblleft'] = 444; + t['guillemotleft'] = 500; + t['guilsinglleft'] = 333; + t['guilsinglright'] = 333; + t['fi'] = 556; + t['fl'] = 556; + t['endash'] = 500; + t['dagger'] = 500; + t['daggerdbl'] = 500; + t['periodcentered'] = 250; + t['paragraph'] = 453; + t['bullet'] = 350; + t['quotesinglbase'] = 333; + t['quotedblbase'] = 444; + t['quotedblright'] = 444; + t['guillemotright'] = 500; + t['ellipsis'] = 1000; + t['perthousand'] = 1000; + t['questiondown'] = 444; + t['grave'] = 333; + t['acute'] = 333; + t['circumflex'] = 333; + t['tilde'] = 333; + t['macron'] = 333; + t['breve'] = 333; + t['dotaccent'] = 333; + t['dieresis'] = 333; + t['ring'] = 333; + t['cedilla'] = 333; + t['hungarumlaut'] = 333; + t['ogonek'] = 333; + t['caron'] = 333; + t['emdash'] = 1000; + t['AE'] = 889; + t['ordfeminine'] = 276; + t['Lslash'] = 611; + t['Oslash'] = 722; + t['OE'] = 889; + t['ordmasculine'] = 310; + t['ae'] = 667; + t['dotlessi'] = 278; + t['lslash'] = 278; + t['oslash'] = 500; + t['oe'] = 722; + t['germandbls'] = 500; + t['Idieresis'] = 333; + t['eacute'] = 444; + t['abreve'] = 444; + t['uhungarumlaut'] = 500; + t['ecaron'] = 444; + t['Ydieresis'] = 722; + t['divide'] = 564; + t['Yacute'] = 722; + t['Acircumflex'] = 722; + t['aacute'] = 444; + t['Ucircumflex'] = 722; + t['yacute'] = 500; + t['scommaaccent'] = 389; + t['ecircumflex'] = 444; + t['Uring'] = 722; + t['Udieresis'] = 722; + t['aogonek'] = 444; + t['Uacute'] = 722; + t['uogonek'] = 500; + t['Edieresis'] = 611; + t['Dcroat'] = 722; + t['commaaccent'] = 250; + t['copyright'] = 760; + t['Emacron'] = 611; + t['ccaron'] = 444; + t['aring'] = 444; + t['Ncommaaccent'] = 722; + t['lacute'] = 278; + t['agrave'] = 444; + t['Tcommaaccent'] = 611; + t['Cacute'] = 667; + t['atilde'] = 444; + t['Edotaccent'] = 611; + t['scaron'] = 389; + t['scedilla'] = 389; + t['iacute'] = 278; + t['lozenge'] = 471; + t['Rcaron'] = 667; + t['Gcommaaccent'] = 722; + t['ucircumflex'] = 500; + t['acircumflex'] = 444; + t['Amacron'] = 722; + t['rcaron'] = 333; + t['ccedilla'] = 444; + t['Zdotaccent'] = 611; + t['Thorn'] = 556; + t['Omacron'] = 722; + t['Racute'] = 667; + t['Sacute'] = 556; + t['dcaron'] = 588; + t['Umacron'] = 722; + t['uring'] = 500; + t['threesuperior'] = 300; + t['Ograve'] = 722; + t['Agrave'] = 722; + t['Abreve'] = 722; + t['multiply'] = 564; + t['uacute'] = 500; + t['Tcaron'] = 611; + t['partialdiff'] = 476; + t['ydieresis'] = 500; + t['Nacute'] = 722; + t['icircumflex'] = 278; + t['Ecircumflex'] = 611; + t['adieresis'] = 444; + t['edieresis'] = 444; + t['cacute'] = 444; + t['nacute'] = 500; + t['umacron'] = 500; + t['Ncaron'] = 722; + t['Iacute'] = 333; + t['plusminus'] = 564; + t['brokenbar'] = 200; + t['registered'] = 760; + t['Gbreve'] = 722; + t['Idotaccent'] = 333; + t['summation'] = 600; + t['Egrave'] = 611; + t['racute'] = 333; + t['omacron'] = 500; + t['Zacute'] = 611; + t['Zcaron'] = 611; + t['greaterequal'] = 549; + t['Eth'] = 722; + t['Ccedilla'] = 667; + t['lcommaaccent'] = 278; + t['tcaron'] = 326; + t['eogonek'] = 444; + t['Uogonek'] = 722; + t['Aacute'] = 722; + t['Adieresis'] = 722; + t['egrave'] = 444; + t['zacute'] = 444; + t['iogonek'] = 278; + t['Oacute'] = 722; + t['oacute'] = 500; + t['amacron'] = 444; + t['sacute'] = 389; + t['idieresis'] = 278; + t['Ocircumflex'] = 722; + t['Ugrave'] = 722; + t['Delta'] = 612; + t['thorn'] = 500; + t['twosuperior'] = 300; + t['Odieresis'] = 722; + t['mu'] = 500; + t['igrave'] = 278; + t['ohungarumlaut'] = 500; + t['Eogonek'] = 611; + t['dcroat'] = 500; + t['threequarters'] = 750; + t['Scedilla'] = 556; + t['lcaron'] = 344; + t['Kcommaaccent'] = 722; + t['Lacute'] = 611; + t['trademark'] = 980; + t['edotaccent'] = 444; + t['Igrave'] = 333; + t['Imacron'] = 333; + t['Lcaron'] = 611; + t['onehalf'] = 750; + t['lessequal'] = 549; + t['ocircumflex'] = 500; + t['ntilde'] = 500; + t['Uhungarumlaut'] = 722; + t['Eacute'] = 611; + t['emacron'] = 444; + t['gbreve'] = 500; + t['onequarter'] = 750; + t['Scaron'] = 556; + t['Scommaaccent'] = 556; + t['Ohungarumlaut'] = 722; + t['degree'] = 400; + t['ograve'] = 500; + t['Ccaron'] = 667; + t['ugrave'] = 500; + t['radical'] = 453; + t['Dcaron'] = 722; + t['rcommaaccent'] = 333; + t['Ntilde'] = 722; + t['otilde'] = 500; + t['Rcommaaccent'] = 667; + t['Lcommaaccent'] = 611; + t['Atilde'] = 722; + t['Aogonek'] = 722; + t['Aring'] = 722; + t['Otilde'] = 722; + t['zdotaccent'] = 444; + t['Ecaron'] = 611; + t['Iogonek'] = 333; + t['kcommaaccent'] = 500; + t['minus'] = 564; + t['Icircumflex'] = 333; + t['ncaron'] = 500; + t['tcommaaccent'] = 278; + t['logicalnot'] = 564; + t['odieresis'] = 500; + t['udieresis'] = 500; + t['notequal'] = 549; + t['gcommaaccent'] = 500; + t['eth'] = 500; + t['zcaron'] = 444; + t['ncommaaccent'] = 500; + t['onesuperior'] = 300; + t['imacron'] = 278; + t['Euro'] = 500; + }); + t['Times-Bold'] = getLookupTableFactory(function (t) { + t['space'] = 250; + t['exclam'] = 333; + t['quotedbl'] = 555; + t['numbersign'] = 500; + t['dollar'] = 500; + t['percent'] = 1000; + t['ampersand'] = 833; + t['quoteright'] = 333; + t['parenleft'] = 333; + t['parenright'] = 333; + t['asterisk'] = 500; + t['plus'] = 570; + t['comma'] = 250; + t['hyphen'] = 333; + t['period'] = 250; + t['slash'] = 278; + t['zero'] = 500; + t['one'] = 500; + t['two'] = 500; + t['three'] = 500; + t['four'] = 500; + t['five'] = 500; + t['six'] = 500; + t['seven'] = 500; + t['eight'] = 500; + t['nine'] = 500; + t['colon'] = 333; + t['semicolon'] = 333; + t['less'] = 570; + t['equal'] = 570; + t['greater'] = 570; + t['question'] = 500; + t['at'] = 930; + t['A'] = 722; + t['B'] = 667; + t['C'] = 722; + t['D'] = 722; + t['E'] = 667; + t['F'] = 611; + t['G'] = 778; + t['H'] = 778; + t['I'] = 389; + t['J'] = 500; + t['K'] = 778; + t['L'] = 667; + t['M'] = 944; + t['N'] = 722; + t['O'] = 778; + t['P'] = 611; + t['Q'] = 778; + t['R'] = 722; + t['S'] = 556; + t['T'] = 667; + t['U'] = 722; + t['V'] = 722; + t['W'] = 1000; + t['X'] = 722; + t['Y'] = 722; + t['Z'] = 667; + t['bracketleft'] = 333; + t['backslash'] = 278; + t['bracketright'] = 333; + t['asciicircum'] = 581; + t['underscore'] = 500; + t['quoteleft'] = 333; + t['a'] = 500; + t['b'] = 556; + t['c'] = 444; + t['d'] = 556; + t['e'] = 444; + t['f'] = 333; + t['g'] = 500; + t['h'] = 556; + t['i'] = 278; + t['j'] = 333; + t['k'] = 556; + t['l'] = 278; + t['m'] = 833; + t['n'] = 556; + t['o'] = 500; + t['p'] = 556; + t['q'] = 556; + t['r'] = 444; + t['s'] = 389; + t['t'] = 333; + t['u'] = 556; + t['v'] = 500; + t['w'] = 722; + t['x'] = 500; + t['y'] = 500; + t['z'] = 444; + t['braceleft'] = 394; + t['bar'] = 220; + t['braceright'] = 394; + t['asciitilde'] = 520; + t['exclamdown'] = 333; + t['cent'] = 500; + t['sterling'] = 500; + t['fraction'] = 167; + t['yen'] = 500; + t['florin'] = 500; + t['section'] = 500; + t['currency'] = 500; + t['quotesingle'] = 278; + t['quotedblleft'] = 500; + t['guillemotleft'] = 500; + t['guilsinglleft'] = 333; + t['guilsinglright'] = 333; + t['fi'] = 556; + t['fl'] = 556; + t['endash'] = 500; + t['dagger'] = 500; + t['daggerdbl'] = 500; + t['periodcentered'] = 250; + t['paragraph'] = 540; + t['bullet'] = 350; + t['quotesinglbase'] = 333; + t['quotedblbase'] = 500; + t['quotedblright'] = 500; + t['guillemotright'] = 500; + t['ellipsis'] = 1000; + t['perthousand'] = 1000; + t['questiondown'] = 500; + t['grave'] = 333; + t['acute'] = 333; + t['circumflex'] = 333; + t['tilde'] = 333; + t['macron'] = 333; + t['breve'] = 333; + t['dotaccent'] = 333; + t['dieresis'] = 333; + t['ring'] = 333; + t['cedilla'] = 333; + t['hungarumlaut'] = 333; + t['ogonek'] = 333; + t['caron'] = 333; + t['emdash'] = 1000; + t['AE'] = 1000; + t['ordfeminine'] = 300; + t['Lslash'] = 667; + t['Oslash'] = 778; + t['OE'] = 1000; + t['ordmasculine'] = 330; + t['ae'] = 722; + t['dotlessi'] = 278; + t['lslash'] = 278; + t['oslash'] = 500; + t['oe'] = 722; + t['germandbls'] = 556; + t['Idieresis'] = 389; + t['eacute'] = 444; + t['abreve'] = 500; + t['uhungarumlaut'] = 556; + t['ecaron'] = 444; + t['Ydieresis'] = 722; + t['divide'] = 570; + t['Yacute'] = 722; + t['Acircumflex'] = 722; + t['aacute'] = 500; + t['Ucircumflex'] = 722; + t['yacute'] = 500; + t['scommaaccent'] = 389; + t['ecircumflex'] = 444; + t['Uring'] = 722; + t['Udieresis'] = 722; + t['aogonek'] = 500; + t['Uacute'] = 722; + t['uogonek'] = 556; + t['Edieresis'] = 667; + t['Dcroat'] = 722; + t['commaaccent'] = 250; + t['copyright'] = 747; + t['Emacron'] = 667; + t['ccaron'] = 444; + t['aring'] = 500; + t['Ncommaaccent'] = 722; + t['lacute'] = 278; + t['agrave'] = 500; + t['Tcommaaccent'] = 667; + t['Cacute'] = 722; + t['atilde'] = 500; + t['Edotaccent'] = 667; + t['scaron'] = 389; + t['scedilla'] = 389; + t['iacute'] = 278; + t['lozenge'] = 494; + t['Rcaron'] = 722; + t['Gcommaaccent'] = 778; + t['ucircumflex'] = 556; + t['acircumflex'] = 500; + t['Amacron'] = 722; + t['rcaron'] = 444; + t['ccedilla'] = 444; + t['Zdotaccent'] = 667; + t['Thorn'] = 611; + t['Omacron'] = 778; + t['Racute'] = 722; + t['Sacute'] = 556; + t['dcaron'] = 672; + t['Umacron'] = 722; + t['uring'] = 556; + t['threesuperior'] = 300; + t['Ograve'] = 778; + t['Agrave'] = 722; + t['Abreve'] = 722; + t['multiply'] = 570; + t['uacute'] = 556; + t['Tcaron'] = 667; + t['partialdiff'] = 494; + t['ydieresis'] = 500; + t['Nacute'] = 722; + t['icircumflex'] = 278; + t['Ecircumflex'] = 667; + t['adieresis'] = 500; + t['edieresis'] = 444; + t['cacute'] = 444; + t['nacute'] = 556; + t['umacron'] = 556; + t['Ncaron'] = 722; + t['Iacute'] = 389; + t['plusminus'] = 570; + t['brokenbar'] = 220; + t['registered'] = 747; + t['Gbreve'] = 778; + t['Idotaccent'] = 389; + t['summation'] = 600; + t['Egrave'] = 667; + t['racute'] = 444; + t['omacron'] = 500; + t['Zacute'] = 667; + t['Zcaron'] = 667; + t['greaterequal'] = 549; + t['Eth'] = 722; + t['Ccedilla'] = 722; + t['lcommaaccent'] = 278; + t['tcaron'] = 416; + t['eogonek'] = 444; + t['Uogonek'] = 722; + t['Aacute'] = 722; + t['Adieresis'] = 722; + t['egrave'] = 444; + t['zacute'] = 444; + t['iogonek'] = 278; + t['Oacute'] = 778; + t['oacute'] = 500; + t['amacron'] = 500; + t['sacute'] = 389; + t['idieresis'] = 278; + t['Ocircumflex'] = 778; + t['Ugrave'] = 722; + t['Delta'] = 612; + t['thorn'] = 556; + t['twosuperior'] = 300; + t['Odieresis'] = 778; + t['mu'] = 556; + t['igrave'] = 278; + t['ohungarumlaut'] = 500; + t['Eogonek'] = 667; + t['dcroat'] = 556; + t['threequarters'] = 750; + t['Scedilla'] = 556; + t['lcaron'] = 394; + t['Kcommaaccent'] = 778; + t['Lacute'] = 667; + t['trademark'] = 1000; + t['edotaccent'] = 444; + t['Igrave'] = 389; + t['Imacron'] = 389; + t['Lcaron'] = 667; + t['onehalf'] = 750; + t['lessequal'] = 549; + t['ocircumflex'] = 500; + t['ntilde'] = 556; + t['Uhungarumlaut'] = 722; + t['Eacute'] = 667; + t['emacron'] = 444; + t['gbreve'] = 500; + t['onequarter'] = 750; + t['Scaron'] = 556; + t['Scommaaccent'] = 556; + t['Ohungarumlaut'] = 778; + t['degree'] = 400; + t['ograve'] = 500; + t['Ccaron'] = 722; + t['ugrave'] = 556; + t['radical'] = 549; + t['Dcaron'] = 722; + t['rcommaaccent'] = 444; + t['Ntilde'] = 722; + t['otilde'] = 500; + t['Rcommaaccent'] = 722; + t['Lcommaaccent'] = 667; + t['Atilde'] = 722; + t['Aogonek'] = 722; + t['Aring'] = 722; + t['Otilde'] = 778; + t['zdotaccent'] = 444; + t['Ecaron'] = 667; + t['Iogonek'] = 389; + t['kcommaaccent'] = 556; + t['minus'] = 570; + t['Icircumflex'] = 389; + t['ncaron'] = 556; + t['tcommaaccent'] = 333; + t['logicalnot'] = 570; + t['odieresis'] = 500; + t['udieresis'] = 556; + t['notequal'] = 549; + t['gcommaaccent'] = 500; + t['eth'] = 500; + t['zcaron'] = 444; + t['ncommaaccent'] = 556; + t['onesuperior'] = 300; + t['imacron'] = 278; + t['Euro'] = 500; + }); + t['Times-BoldItalic'] = getLookupTableFactory(function (t) { + t['space'] = 250; + t['exclam'] = 389; + t['quotedbl'] = 555; + t['numbersign'] = 500; + t['dollar'] = 500; + t['percent'] = 833; + t['ampersand'] = 778; + t['quoteright'] = 333; + t['parenleft'] = 333; + t['parenright'] = 333; + t['asterisk'] = 500; + t['plus'] = 570; + t['comma'] = 250; + t['hyphen'] = 333; + t['period'] = 250; + t['slash'] = 278; + t['zero'] = 500; + t['one'] = 500; + t['two'] = 500; + t['three'] = 500; + t['four'] = 500; + t['five'] = 500; + t['six'] = 500; + t['seven'] = 500; + t['eight'] = 500; + t['nine'] = 500; + t['colon'] = 333; + t['semicolon'] = 333; + t['less'] = 570; + t['equal'] = 570; + t['greater'] = 570; + t['question'] = 500; + t['at'] = 832; + t['A'] = 667; + t['B'] = 667; + t['C'] = 667; + t['D'] = 722; + t['E'] = 667; + t['F'] = 667; + t['G'] = 722; + t['H'] = 778; + t['I'] = 389; + t['J'] = 500; + t['K'] = 667; + t['L'] = 611; + t['M'] = 889; + t['N'] = 722; + t['O'] = 722; + t['P'] = 611; + t['Q'] = 722; + t['R'] = 667; + t['S'] = 556; + t['T'] = 611; + t['U'] = 722; + t['V'] = 667; + t['W'] = 889; + t['X'] = 667; + t['Y'] = 611; + t['Z'] = 611; + t['bracketleft'] = 333; + t['backslash'] = 278; + t['bracketright'] = 333; + t['asciicircum'] = 570; + t['underscore'] = 500; + t['quoteleft'] = 333; + t['a'] = 500; + t['b'] = 500; + t['c'] = 444; + t['d'] = 500; + t['e'] = 444; + t['f'] = 333; + t['g'] = 500; + t['h'] = 556; + t['i'] = 278; + t['j'] = 278; + t['k'] = 500; + t['l'] = 278; + t['m'] = 778; + t['n'] = 556; + t['o'] = 500; + t['p'] = 500; + t['q'] = 500; + t['r'] = 389; + t['s'] = 389; + t['t'] = 278; + t['u'] = 556; + t['v'] = 444; + t['w'] = 667; + t['x'] = 500; + t['y'] = 444; + t['z'] = 389; + t['braceleft'] = 348; + t['bar'] = 220; + t['braceright'] = 348; + t['asciitilde'] = 570; + t['exclamdown'] = 389; + t['cent'] = 500; + t['sterling'] = 500; + t['fraction'] = 167; + t['yen'] = 500; + t['florin'] = 500; + t['section'] = 500; + t['currency'] = 500; + t['quotesingle'] = 278; + t['quotedblleft'] = 500; + t['guillemotleft'] = 500; + t['guilsinglleft'] = 333; + t['guilsinglright'] = 333; + t['fi'] = 556; + t['fl'] = 556; + t['endash'] = 500; + t['dagger'] = 500; + t['daggerdbl'] = 500; + t['periodcentered'] = 250; + t['paragraph'] = 500; + t['bullet'] = 350; + t['quotesinglbase'] = 333; + t['quotedblbase'] = 500; + t['quotedblright'] = 500; + t['guillemotright'] = 500; + t['ellipsis'] = 1000; + t['perthousand'] = 1000; + t['questiondown'] = 500; + t['grave'] = 333; + t['acute'] = 333; + t['circumflex'] = 333; + t['tilde'] = 333; + t['macron'] = 333; + t['breve'] = 333; + t['dotaccent'] = 333; + t['dieresis'] = 333; + t['ring'] = 333; + t['cedilla'] = 333; + t['hungarumlaut'] = 333; + t['ogonek'] = 333; + t['caron'] = 333; + t['emdash'] = 1000; + t['AE'] = 944; + t['ordfeminine'] = 266; + t['Lslash'] = 611; + t['Oslash'] = 722; + t['OE'] = 944; + t['ordmasculine'] = 300; + t['ae'] = 722; + t['dotlessi'] = 278; + t['lslash'] = 278; + t['oslash'] = 500; + t['oe'] = 722; + t['germandbls'] = 500; + t['Idieresis'] = 389; + t['eacute'] = 444; + t['abreve'] = 500; + t['uhungarumlaut'] = 556; + t['ecaron'] = 444; + t['Ydieresis'] = 611; + t['divide'] = 570; + t['Yacute'] = 611; + t['Acircumflex'] = 667; + t['aacute'] = 500; + t['Ucircumflex'] = 722; + t['yacute'] = 444; + t['scommaaccent'] = 389; + t['ecircumflex'] = 444; + t['Uring'] = 722; + t['Udieresis'] = 722; + t['aogonek'] = 500; + t['Uacute'] = 722; + t['uogonek'] = 556; + t['Edieresis'] = 667; + t['Dcroat'] = 722; + t['commaaccent'] = 250; + t['copyright'] = 747; + t['Emacron'] = 667; + t['ccaron'] = 444; + t['aring'] = 500; + t['Ncommaaccent'] = 722; + t['lacute'] = 278; + t['agrave'] = 500; + t['Tcommaaccent'] = 611; + t['Cacute'] = 667; + t['atilde'] = 500; + t['Edotaccent'] = 667; + t['scaron'] = 389; + t['scedilla'] = 389; + t['iacute'] = 278; + t['lozenge'] = 494; + t['Rcaron'] = 667; + t['Gcommaaccent'] = 722; + t['ucircumflex'] = 556; + t['acircumflex'] = 500; + t['Amacron'] = 667; + t['rcaron'] = 389; + t['ccedilla'] = 444; + t['Zdotaccent'] = 611; + t['Thorn'] = 611; + t['Omacron'] = 722; + t['Racute'] = 667; + t['Sacute'] = 556; + t['dcaron'] = 608; + t['Umacron'] = 722; + t['uring'] = 556; + t['threesuperior'] = 300; + t['Ograve'] = 722; + t['Agrave'] = 667; + t['Abreve'] = 667; + t['multiply'] = 570; + t['uacute'] = 556; + t['Tcaron'] = 611; + t['partialdiff'] = 494; + t['ydieresis'] = 444; + t['Nacute'] = 722; + t['icircumflex'] = 278; + t['Ecircumflex'] = 667; + t['adieresis'] = 500; + t['edieresis'] = 444; + t['cacute'] = 444; + t['nacute'] = 556; + t['umacron'] = 556; + t['Ncaron'] = 722; + t['Iacute'] = 389; + t['plusminus'] = 570; + t['brokenbar'] = 220; + t['registered'] = 747; + t['Gbreve'] = 722; + t['Idotaccent'] = 389; + t['summation'] = 600; + t['Egrave'] = 667; + t['racute'] = 389; + t['omacron'] = 500; + t['Zacute'] = 611; + t['Zcaron'] = 611; + t['greaterequal'] = 549; + t['Eth'] = 722; + t['Ccedilla'] = 667; + t['lcommaaccent'] = 278; + t['tcaron'] = 366; + t['eogonek'] = 444; + t['Uogonek'] = 722; + t['Aacute'] = 667; + t['Adieresis'] = 667; + t['egrave'] = 444; + t['zacute'] = 389; + t['iogonek'] = 278; + t['Oacute'] = 722; + t['oacute'] = 500; + t['amacron'] = 500; + t['sacute'] = 389; + t['idieresis'] = 278; + t['Ocircumflex'] = 722; + t['Ugrave'] = 722; + t['Delta'] = 612; + t['thorn'] = 500; + t['twosuperior'] = 300; + t['Odieresis'] = 722; + t['mu'] = 576; + t['igrave'] = 278; + t['ohungarumlaut'] = 500; + t['Eogonek'] = 667; + t['dcroat'] = 500; + t['threequarters'] = 750; + t['Scedilla'] = 556; + t['lcaron'] = 382; + t['Kcommaaccent'] = 667; + t['Lacute'] = 611; + t['trademark'] = 1000; + t['edotaccent'] = 444; + t['Igrave'] = 389; + t['Imacron'] = 389; + t['Lcaron'] = 611; + t['onehalf'] = 750; + t['lessequal'] = 549; + t['ocircumflex'] = 500; + t['ntilde'] = 556; + t['Uhungarumlaut'] = 722; + t['Eacute'] = 667; + t['emacron'] = 444; + t['gbreve'] = 500; + t['onequarter'] = 750; + t['Scaron'] = 556; + t['Scommaaccent'] = 556; + t['Ohungarumlaut'] = 722; + t['degree'] = 400; + t['ograve'] = 500; + t['Ccaron'] = 667; + t['ugrave'] = 556; + t['radical'] = 549; + t['Dcaron'] = 722; + t['rcommaaccent'] = 389; + t['Ntilde'] = 722; + t['otilde'] = 500; + t['Rcommaaccent'] = 667; + t['Lcommaaccent'] = 611; + t['Atilde'] = 667; + t['Aogonek'] = 667; + t['Aring'] = 667; + t['Otilde'] = 722; + t['zdotaccent'] = 389; + t['Ecaron'] = 667; + t['Iogonek'] = 389; + t['kcommaaccent'] = 500; + t['minus'] = 606; + t['Icircumflex'] = 389; + t['ncaron'] = 556; + t['tcommaaccent'] = 278; + t['logicalnot'] = 606; + t['odieresis'] = 500; + t['udieresis'] = 556; + t['notequal'] = 549; + t['gcommaaccent'] = 500; + t['eth'] = 500; + t['zcaron'] = 389; + t['ncommaaccent'] = 556; + t['onesuperior'] = 300; + t['imacron'] = 278; + t['Euro'] = 500; + }); + t['Times-Italic'] = getLookupTableFactory(function (t) { + t['space'] = 250; + t['exclam'] = 333; + t['quotedbl'] = 420; + t['numbersign'] = 500; + t['dollar'] = 500; + t['percent'] = 833; + t['ampersand'] = 778; + t['quoteright'] = 333; + t['parenleft'] = 333; + t['parenright'] = 333; + t['asterisk'] = 500; + t['plus'] = 675; + t['comma'] = 250; + t['hyphen'] = 333; + t['period'] = 250; + t['slash'] = 278; + t['zero'] = 500; + t['one'] = 500; + t['two'] = 500; + t['three'] = 500; + t['four'] = 500; + t['five'] = 500; + t['six'] = 500; + t['seven'] = 500; + t['eight'] = 500; + t['nine'] = 500; + t['colon'] = 333; + t['semicolon'] = 333; + t['less'] = 675; + t['equal'] = 675; + t['greater'] = 675; + t['question'] = 500; + t['at'] = 920; + t['A'] = 611; + t['B'] = 611; + t['C'] = 667; + t['D'] = 722; + t['E'] = 611; + t['F'] = 611; + t['G'] = 722; + t['H'] = 722; + t['I'] = 333; + t['J'] = 444; + t['K'] = 667; + t['L'] = 556; + t['M'] = 833; + t['N'] = 667; + t['O'] = 722; + t['P'] = 611; + t['Q'] = 722; + t['R'] = 611; + t['S'] = 500; + t['T'] = 556; + t['U'] = 722; + t['V'] = 611; + t['W'] = 833; + t['X'] = 611; + t['Y'] = 556; + t['Z'] = 556; + t['bracketleft'] = 389; + t['backslash'] = 278; + t['bracketright'] = 389; + t['asciicircum'] = 422; + t['underscore'] = 500; + t['quoteleft'] = 333; + t['a'] = 500; + t['b'] = 500; + t['c'] = 444; + t['d'] = 500; + t['e'] = 444; + t['f'] = 278; + t['g'] = 500; + t['h'] = 500; + t['i'] = 278; + t['j'] = 278; + t['k'] = 444; + t['l'] = 278; + t['m'] = 722; + t['n'] = 500; + t['o'] = 500; + t['p'] = 500; + t['q'] = 500; + t['r'] = 389; + t['s'] = 389; + t['t'] = 278; + t['u'] = 500; + t['v'] = 444; + t['w'] = 667; + t['x'] = 444; + t['y'] = 444; + t['z'] = 389; + t['braceleft'] = 400; + t['bar'] = 275; + t['braceright'] = 400; + t['asciitilde'] = 541; + t['exclamdown'] = 389; + t['cent'] = 500; + t['sterling'] = 500; + t['fraction'] = 167; + t['yen'] = 500; + t['florin'] = 500; + t['section'] = 500; + t['currency'] = 500; + t['quotesingle'] = 214; + t['quotedblleft'] = 556; + t['guillemotleft'] = 500; + t['guilsinglleft'] = 333; + t['guilsinglright'] = 333; + t['fi'] = 500; + t['fl'] = 500; + t['endash'] = 500; + t['dagger'] = 500; + t['daggerdbl'] = 500; + t['periodcentered'] = 250; + t['paragraph'] = 523; + t['bullet'] = 350; + t['quotesinglbase'] = 333; + t['quotedblbase'] = 556; + t['quotedblright'] = 556; + t['guillemotright'] = 500; + t['ellipsis'] = 889; + t['perthousand'] = 1000; + t['questiondown'] = 500; + t['grave'] = 333; + t['acute'] = 333; + t['circumflex'] = 333; + t['tilde'] = 333; + t['macron'] = 333; + t['breve'] = 333; + t['dotaccent'] = 333; + t['dieresis'] = 333; + t['ring'] = 333; + t['cedilla'] = 333; + t['hungarumlaut'] = 333; + t['ogonek'] = 333; + t['caron'] = 333; + t['emdash'] = 889; + t['AE'] = 889; + t['ordfeminine'] = 276; + t['Lslash'] = 556; + t['Oslash'] = 722; + t['OE'] = 944; + t['ordmasculine'] = 310; + t['ae'] = 667; + t['dotlessi'] = 278; + t['lslash'] = 278; + t['oslash'] = 500; + t['oe'] = 667; + t['germandbls'] = 500; + t['Idieresis'] = 333; + t['eacute'] = 444; + t['abreve'] = 500; + t['uhungarumlaut'] = 500; + t['ecaron'] = 444; + t['Ydieresis'] = 556; + t['divide'] = 675; + t['Yacute'] = 556; + t['Acircumflex'] = 611; + t['aacute'] = 500; + t['Ucircumflex'] = 722; + t['yacute'] = 444; + t['scommaaccent'] = 389; + t['ecircumflex'] = 444; + t['Uring'] = 722; + t['Udieresis'] = 722; + t['aogonek'] = 500; + t['Uacute'] = 722; + t['uogonek'] = 500; + t['Edieresis'] = 611; + t['Dcroat'] = 722; + t['commaaccent'] = 250; + t['copyright'] = 760; + t['Emacron'] = 611; + t['ccaron'] = 444; + t['aring'] = 500; + t['Ncommaaccent'] = 667; + t['lacute'] = 278; + t['agrave'] = 500; + t['Tcommaaccent'] = 556; + t['Cacute'] = 667; + t['atilde'] = 500; + t['Edotaccent'] = 611; + t['scaron'] = 389; + t['scedilla'] = 389; + t['iacute'] = 278; + t['lozenge'] = 471; + t['Rcaron'] = 611; + t['Gcommaaccent'] = 722; + t['ucircumflex'] = 500; + t['acircumflex'] = 500; + t['Amacron'] = 611; + t['rcaron'] = 389; + t['ccedilla'] = 444; + t['Zdotaccent'] = 556; + t['Thorn'] = 611; + t['Omacron'] = 722; + t['Racute'] = 611; + t['Sacute'] = 500; + t['dcaron'] = 544; + t['Umacron'] = 722; + t['uring'] = 500; + t['threesuperior'] = 300; + t['Ograve'] = 722; + t['Agrave'] = 611; + t['Abreve'] = 611; + t['multiply'] = 675; + t['uacute'] = 500; + t['Tcaron'] = 556; + t['partialdiff'] = 476; + t['ydieresis'] = 444; + t['Nacute'] = 667; + t['icircumflex'] = 278; + t['Ecircumflex'] = 611; + t['adieresis'] = 500; + t['edieresis'] = 444; + t['cacute'] = 444; + t['nacute'] = 500; + t['umacron'] = 500; + t['Ncaron'] = 667; + t['Iacute'] = 333; + t['plusminus'] = 675; + t['brokenbar'] = 275; + t['registered'] = 760; + t['Gbreve'] = 722; + t['Idotaccent'] = 333; + t['summation'] = 600; + t['Egrave'] = 611; + t['racute'] = 389; + t['omacron'] = 500; + t['Zacute'] = 556; + t['Zcaron'] = 556; + t['greaterequal'] = 549; + t['Eth'] = 722; + t['Ccedilla'] = 667; + t['lcommaaccent'] = 278; + t['tcaron'] = 300; + t['eogonek'] = 444; + t['Uogonek'] = 722; + t['Aacute'] = 611; + t['Adieresis'] = 611; + t['egrave'] = 444; + t['zacute'] = 389; + t['iogonek'] = 278; + t['Oacute'] = 722; + t['oacute'] = 500; + t['amacron'] = 500; + t['sacute'] = 389; + t['idieresis'] = 278; + t['Ocircumflex'] = 722; + t['Ugrave'] = 722; + t['Delta'] = 612; + t['thorn'] = 500; + t['twosuperior'] = 300; + t['Odieresis'] = 722; + t['mu'] = 500; + t['igrave'] = 278; + t['ohungarumlaut'] = 500; + t['Eogonek'] = 611; + t['dcroat'] = 500; + t['threequarters'] = 750; + t['Scedilla'] = 500; + t['lcaron'] = 300; + t['Kcommaaccent'] = 667; + t['Lacute'] = 556; + t['trademark'] = 980; + t['edotaccent'] = 444; + t['Igrave'] = 333; + t['Imacron'] = 333; + t['Lcaron'] = 611; + t['onehalf'] = 750; + t['lessequal'] = 549; + t['ocircumflex'] = 500; + t['ntilde'] = 500; + t['Uhungarumlaut'] = 722; + t['Eacute'] = 611; + t['emacron'] = 444; + t['gbreve'] = 500; + t['onequarter'] = 750; + t['Scaron'] = 500; + t['Scommaaccent'] = 500; + t['Ohungarumlaut'] = 722; + t['degree'] = 400; + t['ograve'] = 500; + t['Ccaron'] = 667; + t['ugrave'] = 500; + t['radical'] = 453; + t['Dcaron'] = 722; + t['rcommaaccent'] = 389; + t['Ntilde'] = 667; + t['otilde'] = 500; + t['Rcommaaccent'] = 611; + t['Lcommaaccent'] = 556; + t['Atilde'] = 611; + t['Aogonek'] = 611; + t['Aring'] = 611; + t['Otilde'] = 722; + t['zdotaccent'] = 389; + t['Ecaron'] = 611; + t['Iogonek'] = 333; + t['kcommaaccent'] = 444; + t['minus'] = 675; + t['Icircumflex'] = 333; + t['ncaron'] = 500; + t['tcommaaccent'] = 278; + t['logicalnot'] = 675; + t['odieresis'] = 500; + t['udieresis'] = 500; + t['notequal'] = 549; + t['gcommaaccent'] = 500; + t['eth'] = 500; + t['zcaron'] = 389; + t['ncommaaccent'] = 500; + t['onesuperior'] = 300; + t['imacron'] = 278; + t['Euro'] = 500; + }); + t['ZapfDingbats'] = getLookupTableFactory(function (t) { + t['space'] = 278; + t['a1'] = 974; + t['a2'] = 961; + t['a202'] = 974; + t['a3'] = 980; + t['a4'] = 719; + t['a5'] = 789; + t['a119'] = 790; + t['a118'] = 791; + t['a117'] = 690; + t['a11'] = 960; + t['a12'] = 939; + t['a13'] = 549; + t['a14'] = 855; + t['a15'] = 911; + t['a16'] = 933; + t['a105'] = 911; + t['a17'] = 945; + t['a18'] = 974; + t['a19'] = 755; + t['a20'] = 846; + t['a21'] = 762; + t['a22'] = 761; + t['a23'] = 571; + t['a24'] = 677; + t['a25'] = 763; + t['a26'] = 760; + t['a27'] = 759; + t['a28'] = 754; + t['a6'] = 494; + t['a7'] = 552; + t['a8'] = 537; + t['a9'] = 577; + t['a10'] = 692; + t['a29'] = 786; + t['a30'] = 788; + t['a31'] = 788; + t['a32'] = 790; + t['a33'] = 793; + t['a34'] = 794; + t['a35'] = 816; + t['a36'] = 823; + t['a37'] = 789; + t['a38'] = 841; + t['a39'] = 823; + t['a40'] = 833; + t['a41'] = 816; + t['a42'] = 831; + t['a43'] = 923; + t['a44'] = 744; + t['a45'] = 723; + t['a46'] = 749; + t['a47'] = 790; + t['a48'] = 792; + t['a49'] = 695; + t['a50'] = 776; + t['a51'] = 768; + t['a52'] = 792; + t['a53'] = 759; + t['a54'] = 707; + t['a55'] = 708; + t['a56'] = 682; + t['a57'] = 701; + t['a58'] = 826; + t['a59'] = 815; + t['a60'] = 789; + t['a61'] = 789; + t['a62'] = 707; + t['a63'] = 687; + t['a64'] = 696; + t['a65'] = 689; + t['a66'] = 786; + t['a67'] = 787; + t['a68'] = 713; + t['a69'] = 791; + t['a70'] = 785; + t['a71'] = 791; + t['a72'] = 873; + t['a73'] = 761; + t['a74'] = 762; + t['a203'] = 762; + t['a75'] = 759; + t['a204'] = 759; + t['a76'] = 892; + t['a77'] = 892; + t['a78'] = 788; + t['a79'] = 784; + t['a81'] = 438; + t['a82'] = 138; + t['a83'] = 277; + t['a84'] = 415; + t['a97'] = 392; + t['a98'] = 392; + t['a99'] = 668; + t['a100'] = 668; + t['a89'] = 390; + t['a90'] = 390; + t['a93'] = 317; + t['a94'] = 317; + t['a91'] = 276; + t['a92'] = 276; + t['a205'] = 509; + t['a85'] = 509; + t['a206'] = 410; + t['a86'] = 410; + t['a87'] = 234; + t['a88'] = 234; + t['a95'] = 334; + t['a96'] = 334; + t['a101'] = 732; + t['a102'] = 544; + t['a103'] = 544; + t['a104'] = 910; + t['a106'] = 667; + t['a107'] = 760; + t['a108'] = 760; + t['a112'] = 776; + t['a111'] = 595; + t['a110'] = 694; + t['a109'] = 626; + t['a120'] = 788; + t['a121'] = 788; + t['a122'] = 788; + t['a123'] = 788; + t['a124'] = 788; + t['a125'] = 788; + t['a126'] = 788; + t['a127'] = 788; + t['a128'] = 788; + t['a129'] = 788; + t['a130'] = 788; + t['a131'] = 788; + t['a132'] = 788; + t['a133'] = 788; + t['a134'] = 788; + t['a135'] = 788; + t['a136'] = 788; + t['a137'] = 788; + t['a138'] = 788; + t['a139'] = 788; + t['a140'] = 788; + t['a141'] = 788; + t['a142'] = 788; + t['a143'] = 788; + t['a144'] = 788; + t['a145'] = 788; + t['a146'] = 788; + t['a147'] = 788; + t['a148'] = 788; + t['a149'] = 788; + t['a150'] = 788; + t['a151'] = 788; + t['a152'] = 788; + t['a153'] = 788; + t['a154'] = 788; + t['a155'] = 788; + t['a156'] = 788; + t['a157'] = 788; + t['a158'] = 788; + t['a159'] = 788; + t['a160'] = 894; + t['a161'] = 838; + t['a163'] = 1016; + t['a164'] = 458; + t['a196'] = 748; + t['a165'] = 924; + t['a192'] = 748; + t['a166'] = 918; + t['a167'] = 927; + t['a168'] = 928; + t['a169'] = 928; + t['a170'] = 834; + t['a171'] = 873; + t['a172'] = 828; + t['a173'] = 924; + t['a162'] = 924; + t['a174'] = 917; + t['a175'] = 930; + t['a176'] = 931; + t['a177'] = 463; + t['a178'] = 883; + t['a179'] = 836; + t['a193'] = 836; + t['a180'] = 867; + t['a199'] = 867; + t['a181'] = 696; + t['a200'] = 696; + t['a182'] = 874; + t['a201'] = 874; + t['a183'] = 760; + t['a184'] = 946; + t['a197'] = 771; + t['a185'] = 865; + t['a194'] = 771; + t['a198'] = 888; + t['a186'] = 967; + t['a195'] = 888; + t['a187'] = 831; + t['a188'] = 873; + t['a189'] = 927; + t['a190'] = 970; + t['a191'] = 918; + }); +}); +exports.getMetrics = getMetrics; + +/***/ }), +/* 31 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var Uint32ArrayView = sharedUtil.Uint32ArrayView; +var MurmurHash3_64 = function MurmurHash3_64Closure(seed) { + var MASK_HIGH = 0xffff0000; + var MASK_LOW = 0xffff; + function MurmurHash3_64(seed) { + var SEED = 0xc3d2e1f0; + this.h1 = seed ? seed & 0xffffffff : SEED; + this.h2 = seed ? seed & 0xffffffff : SEED; + } + var alwaysUseUint32ArrayView = false; + try { + new Uint32Array(new Uint8Array(5).buffer, 0, 1); + } catch (e) { + alwaysUseUint32ArrayView = true; + } + MurmurHash3_64.prototype = { + update: function MurmurHash3_64_update(input) { + var useUint32ArrayView = alwaysUseUint32ArrayView; + var i; + if (typeof input === 'string') { + var data = new Uint8Array(input.length * 2); + var length = 0; + for (i = 0; i < input.length; i++) { + var code = input.charCodeAt(i); + if (code <= 0xff) { + data[length++] = code; + } else { + data[length++] = code >>> 8; + data[length++] = code & 0xff; + } + } + } else if (input instanceof Uint8Array) { + data = input; + length = data.length; + } else if (typeof input === 'object' && 'length' in input) { + data = input; + length = data.length; + useUint32ArrayView = true; + } else { + throw new Error('Wrong data format in MurmurHash3_64_update. ' + 'Input must be a string or array.'); + } + var blockCounts = length >> 2; + var tailLength = length - blockCounts * 4; + var dataUint32 = useUint32ArrayView ? new Uint32ArrayView(data, blockCounts) : new Uint32Array(data.buffer, 0, blockCounts); + var k1 = 0; + var k2 = 0; + var h1 = this.h1; + var h2 = this.h2; + var C1 = 0xcc9e2d51; + var C2 = 0x1b873593; + var C1_LOW = C1 & MASK_LOW; + var C2_LOW = C2 & MASK_LOW; + for (i = 0; i < blockCounts; i++) { + if (i & 1) { + k1 = dataUint32[i]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + h1 ^= k1; + h1 = h1 << 13 | h1 >>> 19; + h1 = h1 * 5 + 0xe6546b64; + } else { + k2 = dataUint32[i]; + k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW; + k2 = k2 << 15 | k2 >>> 17; + k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW; + h2 ^= k2; + h2 = h2 << 13 | h2 >>> 19; + h2 = h2 * 5 + 0xe6546b64; + } + } + k1 = 0; + switch (tailLength) { + case 3: + k1 ^= data[blockCounts * 4 + 2] << 16; + case 2: + k1 ^= data[blockCounts * 4 + 1] << 8; + case 1: + k1 ^= data[blockCounts * 4]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + if (blockCounts & 1) { + h1 ^= k1; + } else { + h2 ^= k1; + } + } + this.h1 = h1; + this.h2 = h2; + return this; + }, + hexdigest: function MurmurHash3_64_hexdigest() { + var h1 = this.h1; + var h2 = this.h2; + h1 ^= h2 >>> 1; + h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW; + h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW; + h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + for (var i = 0, arr = [ + h1, + h2 + ], str = ''; i < arr.length; i++) { + var hex = (arr[i] >>> 0).toString(16); + while (hex.length < 8) { + hex = '0' + hex; + } + str += hex; + } + return str; + } + }; + return MurmurHash3_64; +}(); +exports.MurmurHash3_64 = MurmurHash3_64; + +/***/ }), +/* 32 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var coreFunction = __w_pdfjs_require__(6); +var coreColorSpace = __w_pdfjs_require__(3); +var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES; +var MissingDataException = sharedUtil.MissingDataException; +var Util = sharedUtil.Util; +var assert = sharedUtil.assert; +var error = sharedUtil.error; +var info = sharedUtil.info; +var warn = sharedUtil.warn; +var isStream = corePrimitives.isStream; +var PDFFunction = coreFunction.PDFFunction; +var ColorSpace = coreColorSpace.ColorSpace; +var ShadingType = { + FUNCTION_BASED: 1, + AXIAL: 2, + RADIAL: 3, + FREE_FORM_MESH: 4, + LATTICE_FORM_MESH: 5, + COONS_PATCH_MESH: 6, + TENSOR_PATCH_MESH: 7 +}; +var Pattern = function PatternClosure() { + function Pattern() { + error('should not call Pattern constructor'); + } + Pattern.prototype = { + getPattern: function Pattern_getPattern(ctx) { + error('Should not call Pattern.getStyle: ' + ctx); + } + }; + Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref, res, handler) { + var dict = isStream(shading) ? shading.dict : shading; + var type = dict.get('ShadingType'); + try { + switch (type) { + case ShadingType.AXIAL: + case ShadingType.RADIAL: + return new Shadings.RadialAxial(dict, matrix, xref, res); + case ShadingType.FREE_FORM_MESH: + case ShadingType.LATTICE_FORM_MESH: + case ShadingType.COONS_PATCH_MESH: + case ShadingType.TENSOR_PATCH_MESH: + return new Shadings.Mesh(shading, matrix, xref, res); + default: + throw new Error('Unsupported ShadingType: ' + type); + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + handler.send('UnsupportedFeature', { featureId: UNSUPPORTED_FEATURES.shadingPattern }); + warn(ex); + return new Shadings.Dummy(); + } + }; + return Pattern; +}(); +var Shadings = {}; +Shadings.SMALL_NUMBER = 1e-6; +Shadings.RadialAxial = function RadialAxialClosure() { + function RadialAxial(dict, matrix, xref, res) { + this.matrix = matrix; + this.coordsArr = dict.getArray('Coords'); + this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; + var cs = dict.get('ColorSpace', 'CS'); + cs = ColorSpace.parse(cs, xref, res); + this.cs = cs; + var t0 = 0.0, t1 = 1.0; + if (dict.has('Domain')) { + var domainArr = dict.getArray('Domain'); + t0 = domainArr[0]; + t1 = domainArr[1]; + } + var extendStart = false, extendEnd = false; + if (dict.has('Extend')) { + var extendArr = dict.getArray('Extend'); + extendStart = extendArr[0]; + extendEnd = extendArr[1]; + } + if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) { + var x1 = this.coordsArr[0]; + var y1 = this.coordsArr[1]; + var r1 = this.coordsArr[2]; + var x2 = this.coordsArr[3]; + var y2 = this.coordsArr[4]; + var r2 = this.coordsArr[5]; + var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + if (r1 <= r2 + distance && r2 <= r1 + distance) { + warn('Unsupported radial gradient.'); + } + } + this.extendStart = extendStart; + this.extendEnd = extendEnd; + var fnObj = dict.get('Function'); + var fn = PDFFunction.parseArray(xref, fnObj); + var diff = t1 - t0; + var step = diff / 10; + var colorStops = this.colorStops = []; + if (t0 >= t1 || step <= 0) { + info('Bad shading domain.'); + return; + } + var color = new Float32Array(cs.numComps), ratio = new Float32Array(1); + var rgbColor; + for (var i = t0; i <= t1; i += step) { + ratio[0] = i; + fn(ratio, 0, color, 0); + rgbColor = cs.getRgb(color, 0); + var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); + colorStops.push([ + (i - t0) / diff, + cssColor + ]); + } + var background = 'transparent'; + if (dict.has('Background')) { + rgbColor = cs.getRgb(dict.get('Background'), 0); + background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); + } + if (!extendStart) { + colorStops.unshift([ + 0, + background + ]); + colorStops[1][0] += Shadings.SMALL_NUMBER; + } + if (!extendEnd) { + colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER; + colorStops.push([ + 1, + background + ]); + } + this.colorStops = colorStops; + } + RadialAxial.prototype = { + getIR: function RadialAxial_getIR() { + var coordsArr = this.coordsArr; + var shadingType = this.shadingType; + var type, p0, p1, r0, r1; + if (shadingType === ShadingType.AXIAL) { + p0 = [ + coordsArr[0], + coordsArr[1] + ]; + p1 = [ + coordsArr[2], + coordsArr[3] + ]; + r0 = null; + r1 = null; + type = 'axial'; + } else if (shadingType === ShadingType.RADIAL) { + p0 = [ + coordsArr[0], + coordsArr[1] + ]; + p1 = [ + coordsArr[3], + coordsArr[4] + ]; + r0 = coordsArr[2]; + r1 = coordsArr[5]; + type = 'radial'; + } else { + error('getPattern type unknown: ' + shadingType); + } + var matrix = this.matrix; + if (matrix) { + p0 = Util.applyTransform(p0, matrix); + p1 = Util.applyTransform(p1, matrix); + if (shadingType === ShadingType.RADIAL) { + var scale = Util.singularValueDecompose2dScale(matrix); + r0 *= scale[0]; + r1 *= scale[1]; + } + } + return [ + 'RadialAxial', + type, + this.colorStops, + p0, + p1, + r0, + r1 + ]; + } + }; + return RadialAxial; +}(); +Shadings.Mesh = function MeshClosure() { + function MeshStreamReader(stream, context) { + this.stream = stream; + this.context = context; + this.buffer = 0; + this.bufferLength = 0; + var numComps = context.numComps; + this.tmpCompsBuf = new Float32Array(numComps); + var csNumComps = context.colorSpace.numComps; + this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf; + } + MeshStreamReader.prototype = { + get hasData() { + if (this.stream.end) { + return this.stream.pos < this.stream.end; + } + if (this.bufferLength > 0) { + return true; + } + var nextByte = this.stream.getByte(); + if (nextByte < 0) { + return false; + } + this.buffer = nextByte; + this.bufferLength = 8; + return true; + }, + readBits: function MeshStreamReader_readBits(n) { + var buffer = this.buffer; + var bufferLength = this.bufferLength; + if (n === 32) { + if (bufferLength === 0) { + return (this.stream.getByte() << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte()) >>> 0; + } + buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte(); + var nextByte = this.stream.getByte(); + this.buffer = nextByte & (1 << bufferLength) - 1; + return (buffer << 8 - bufferLength | (nextByte & 0xFF) >> bufferLength) >>> 0; + } + if (n === 8 && bufferLength === 0) { + return this.stream.getByte(); + } + while (bufferLength < n) { + buffer = buffer << 8 | this.stream.getByte(); + bufferLength += 8; + } + bufferLength -= n; + this.bufferLength = bufferLength; + this.buffer = buffer & (1 << bufferLength) - 1; + return buffer >> bufferLength; + }, + align: function MeshStreamReader_align() { + this.buffer = 0; + this.bufferLength = 0; + }, + readFlag: function MeshStreamReader_readFlag() { + return this.readBits(this.context.bitsPerFlag); + }, + readCoordinate: function MeshStreamReader_readCoordinate() { + var bitsPerCoordinate = this.context.bitsPerCoordinate; + var xi = this.readBits(bitsPerCoordinate); + var yi = this.readBits(bitsPerCoordinate); + var decode = this.context.decode; + var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10; + return [ + xi * scale * (decode[1] - decode[0]) + decode[0], + yi * scale * (decode[3] - decode[2]) + decode[2] + ]; + }, + readComponents: function MeshStreamReader_readComponents() { + var numComps = this.context.numComps; + var bitsPerComponent = this.context.bitsPerComponent; + var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10; + var decode = this.context.decode; + var components = this.tmpCompsBuf; + for (var i = 0, j = 4; i < numComps; i++, j += 2) { + var ci = this.readBits(bitsPerComponent); + components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j]; + } + var color = this.tmpCsCompsBuf; + if (this.context.colorFn) { + this.context.colorFn(components, 0, color, 0); + } + return this.context.colorSpace.getRgb(color, 0); + } + }; + function decodeType4Shading(mesh, reader) { + var coords = mesh.coords; + var colors = mesh.colors; + var operators = []; + var ps = []; + var verticesLeft = 0; + while (reader.hasData) { + var f = reader.readFlag(); + var coord = reader.readCoordinate(); + var color = reader.readComponents(); + if (verticesLeft === 0) { + assert(0 <= f && f <= 2, 'Unknown type4 flag'); + switch (f) { + case 0: + verticesLeft = 3; + break; + case 1: + ps.push(ps[ps.length - 2], ps[ps.length - 1]); + verticesLeft = 1; + break; + case 2: + ps.push(ps[ps.length - 3], ps[ps.length - 1]); + verticesLeft = 1; + break; + } + operators.push(f); + } + ps.push(coords.length); + coords.push(coord); + colors.push(color); + verticesLeft--; + reader.align(); + } + mesh.figures.push({ + type: 'triangles', + coords: new Int32Array(ps), + colors: new Int32Array(ps) + }); + } + function decodeType5Shading(mesh, reader, verticesPerRow) { + var coords = mesh.coords; + var colors = mesh.colors; + var ps = []; + while (reader.hasData) { + var coord = reader.readCoordinate(); + var color = reader.readComponents(); + ps.push(coords.length); + coords.push(coord); + colors.push(color); + } + mesh.figures.push({ + type: 'lattice', + coords: new Int32Array(ps), + colors: new Int32Array(ps), + verticesPerRow: verticesPerRow + }); + } + var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3; + var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20; + var TRIANGLE_DENSITY = 20; + var getB = function getBClosure() { + function buildB(count) { + var lut = []; + for (var i = 0; i <= count; i++) { + var t = i / count, t_ = 1 - t; + lut.push(new Float32Array([ + t_ * t_ * t_, + 3 * t * t_ * t_, + 3 * t * t * t_, + t * t * t + ])); + } + return lut; + } + var cache = []; + return function getB(count) { + if (!cache[count]) { + cache[count] = buildB(count); + } + return cache[count]; + }; + }(); + function buildFigureFromPatch(mesh, index) { + var figure = mesh.figures[index]; + assert(figure.type === 'patch', 'Unexpected patch mesh figure'); + var coords = mesh.coords, colors = mesh.colors; + var pi = figure.coords; + var ci = figure.colors; + var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]); + var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]); + var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]); + var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]); + var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / (mesh.bounds[2] - mesh.bounds[0])); + splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy)); + var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / (mesh.bounds[3] - mesh.bounds[1])); + splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy)); + var verticesPerRow = splitXBy + 1; + var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow); + var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow); + var k = 0; + var cl = new Uint8Array(3), cr = new Uint8Array(3); + var c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]]; + var bRow = getB(splitYBy), bCol = getB(splitXBy); + for (var row = 0; row <= splitYBy; row++) { + cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0; + cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0; + cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0; + cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0; + cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0; + cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0; + for (var col = 0; col <= splitXBy; col++, k++) { + if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) { + continue; + } + var x = 0, y = 0; + var q = 0; + for (var i = 0; i <= 3; i++) { + for (var j = 0; j <= 3; j++, q++) { + var m = bRow[row][i] * bCol[col][j]; + x += coords[pi[q]][0] * m; + y += coords[pi[q]][1] * m; + } + } + figureCoords[k] = coords.length; + coords.push([ + x, + y + ]); + figureColors[k] = colors.length; + var newColor = new Uint8Array(3); + newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0; + newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0; + newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0; + colors.push(newColor); + } + } + figureCoords[0] = pi[0]; + figureColors[0] = ci[0]; + figureCoords[splitXBy] = pi[3]; + figureColors[splitXBy] = ci[1]; + figureCoords[verticesPerRow * splitYBy] = pi[12]; + figureColors[verticesPerRow * splitYBy] = ci[2]; + figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15]; + figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3]; + mesh.figures[index] = { + type: 'lattice', + coords: figureCoords, + colors: figureColors, + verticesPerRow: verticesPerRow + }; + } + function decodeType6Shading(mesh, reader) { + var coords = mesh.coords; + var colors = mesh.colors; + var ps = new Int32Array(16); + var cs = new Int32Array(4); + while (reader.hasData) { + var f = reader.readFlag(); + assert(0 <= f && f <= 3, 'Unknown type6 flag'); + var i, ii; + var pi = coords.length; + for (i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) { + coords.push(reader.readCoordinate()); + } + var ci = colors.length; + for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) { + colors.push(reader.readComponents()); + } + var tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; + ps[13] = pi + 4; + ps[14] = pi + 5; + ps[15] = pi + 6; + ps[8] = pi + 2; + ps[11] = pi + 7; + ps[4] = pi + 1; + ps[7] = pi + 8; + ps[0] = pi; + ps[1] = pi + 11; + ps[2] = pi + 10; + ps[3] = pi + 9; + cs[2] = ci + 1; + cs[3] = ci + 2; + cs[0] = ci; + cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; + tmp2 = ps[13]; + tmp3 = ps[14]; + tmp4 = ps[15]; + ps[12] = tmp4; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = tmp3; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[2]; + tmp2 = cs[3]; + cs[2] = tmp2; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 2: + tmp1 = ps[15]; + tmp2 = ps[11]; + ps[12] = ps[3]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[7]; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[3]; + cs[2] = cs[1]; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 3: + ps[12] = ps[0]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[1]; + ps[11] = pi + 3; + ps[4] = ps[2]; + ps[7] = pi + 4; + ps[0] = ps[3]; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + cs[2] = cs[0]; + cs[3] = ci; + cs[0] = cs[1]; + cs[1] = ci + 1; + break; + } + ps[5] = coords.length; + coords.push([ + (-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, + (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9 + ]); + ps[6] = coords.length; + coords.push([ + (-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, + (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9 + ]); + ps[9] = coords.length; + coords.push([ + (-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, + (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9 + ]); + ps[10] = coords.length; + coords.push([ + (-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, + (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9 + ]); + mesh.figures.push({ + type: 'patch', + coords: new Int32Array(ps), + colors: new Int32Array(cs) + }); + } + } + function decodeType7Shading(mesh, reader) { + var coords = mesh.coords; + var colors = mesh.colors; + var ps = new Int32Array(16); + var cs = new Int32Array(4); + while (reader.hasData) { + var f = reader.readFlag(); + assert(0 <= f && f <= 3, 'Unknown type7 flag'); + var i, ii; + var pi = coords.length; + for (i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) { + coords.push(reader.readCoordinate()); + } + var ci = colors.length; + for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) { + colors.push(reader.readComponents()); + } + var tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; + ps[13] = pi + 4; + ps[14] = pi + 5; + ps[15] = pi + 6; + ps[8] = pi + 2; + ps[9] = pi + 13; + ps[10] = pi + 14; + ps[11] = pi + 7; + ps[4] = pi + 1; + ps[5] = pi + 12; + ps[6] = pi + 15; + ps[7] = pi + 8; + ps[0] = pi; + ps[1] = pi + 11; + ps[2] = pi + 10; + ps[3] = pi + 9; + cs[2] = ci + 1; + cs[3] = ci + 2; + cs[0] = ci; + cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; + tmp2 = ps[13]; + tmp3 = ps[14]; + tmp4 = ps[15]; + ps[12] = tmp4; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = tmp3; + ps[9] = pi + 9; + ps[10] = pi + 10; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[5] = pi + 8; + ps[6] = pi + 11; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[2]; + tmp2 = cs[3]; + cs[2] = tmp2; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 2: + tmp1 = ps[15]; + tmp2 = ps[11]; + ps[12] = ps[3]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[7]; + ps[9] = pi + 9; + ps[10] = pi + 10; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[5] = pi + 8; + ps[6] = pi + 11; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[3]; + cs[2] = cs[1]; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 3: + ps[12] = ps[0]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[1]; + ps[9] = pi + 9; + ps[10] = pi + 10; + ps[11] = pi + 3; + ps[4] = ps[2]; + ps[5] = pi + 8; + ps[6] = pi + 11; + ps[7] = pi + 4; + ps[0] = ps[3]; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + cs[2] = cs[0]; + cs[3] = ci; + cs[0] = cs[1]; + cs[1] = ci + 1; + break; + } + mesh.figures.push({ + type: 'patch', + coords: new Int32Array(ps), + colors: new Int32Array(cs) + }); + } + } + function updateBounds(mesh) { + var minX = mesh.coords[0][0], minY = mesh.coords[0][1], maxX = minX, maxY = minY; + for (var i = 1, ii = mesh.coords.length; i < ii; i++) { + var x = mesh.coords[i][0], y = mesh.coords[i][1]; + minX = minX > x ? x : minX; + minY = minY > y ? y : minY; + maxX = maxX < x ? x : maxX; + maxY = maxY < y ? y : maxY; + } + mesh.bounds = [ + minX, + minY, + maxX, + maxY + ]; + } + function packData(mesh) { + var i, ii, j, jj; + var coords = mesh.coords; + var coordsPacked = new Float32Array(coords.length * 2); + for (i = 0, j = 0, ii = coords.length; i < ii; i++) { + var xy = coords[i]; + coordsPacked[j++] = xy[0]; + coordsPacked[j++] = xy[1]; + } + mesh.coords = coordsPacked; + var colors = mesh.colors; + var colorsPacked = new Uint8Array(colors.length * 3); + for (i = 0, j = 0, ii = colors.length; i < ii; i++) { + var c = colors[i]; + colorsPacked[j++] = c[0]; + colorsPacked[j++] = c[1]; + colorsPacked[j++] = c[2]; + } + mesh.colors = colorsPacked; + var figures = mesh.figures; + for (i = 0, ii = figures.length; i < ii; i++) { + var figure = figures[i], ps = figure.coords, cs = figure.colors; + for (j = 0, jj = ps.length; j < jj; j++) { + ps[j] *= 2; + cs[j] *= 3; + } + } + } + function Mesh(stream, matrix, xref, res) { + assert(isStream(stream), 'Mesh data is not a stream'); + var dict = stream.dict; + this.matrix = matrix; + this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; + this.bbox = dict.getArray('BBox'); + var cs = dict.get('ColorSpace', 'CS'); + cs = ColorSpace.parse(cs, xref, res); + this.cs = cs; + this.background = dict.has('Background') ? cs.getRgb(dict.get('Background'), 0) : null; + var fnObj = dict.get('Function'); + var fn = fnObj ? PDFFunction.parseArray(xref, fnObj) : null; + this.coords = []; + this.colors = []; + this.figures = []; + var decodeContext = { + bitsPerCoordinate: dict.get('BitsPerCoordinate'), + bitsPerComponent: dict.get('BitsPerComponent'), + bitsPerFlag: dict.get('BitsPerFlag'), + decode: dict.getArray('Decode'), + colorFn: fn, + colorSpace: cs, + numComps: fn ? 1 : cs.numComps + }; + var reader = new MeshStreamReader(stream, decodeContext); + var patchMesh = false; + switch (this.shadingType) { + case ShadingType.FREE_FORM_MESH: + decodeType4Shading(this, reader); + break; + case ShadingType.LATTICE_FORM_MESH: + var verticesPerRow = dict.get('VerticesPerRow') | 0; + assert(verticesPerRow >= 2, 'Invalid VerticesPerRow'); + decodeType5Shading(this, reader, verticesPerRow); + break; + case ShadingType.COONS_PATCH_MESH: + decodeType6Shading(this, reader); + patchMesh = true; + break; + case ShadingType.TENSOR_PATCH_MESH: + decodeType7Shading(this, reader); + patchMesh = true; + break; + default: + error('Unsupported mesh type.'); + break; + } + if (patchMesh) { + updateBounds(this); + for (var i = 0, ii = this.figures.length; i < ii; i++) { + buildFigureFromPatch(this, i); + } + } + updateBounds(this); + packData(this); + } + Mesh.prototype = { + getIR: function Mesh_getIR() { + return [ + 'Mesh', + this.shadingType, + this.coords, + this.colors, + this.figures, + this.bounds, + this.matrix, + this.bbox, + this.background + ]; + } + }; + return Mesh; +}(); +Shadings.Dummy = function DummyClosure() { + function Dummy() { + this.type = 'Pattern'; + } + Dummy.prototype = { + getIR: function Dummy_getIR() { + return ['Dummy']; + } + }; + return Dummy; +}(); +function getTilingPatternIR(operatorList, dict, args) { + var matrix = dict.getArray('Matrix'); + var bbox = dict.getArray('BBox'); + var xstep = dict.get('XStep'); + var ystep = dict.get('YStep'); + var paintType = dict.get('PaintType'); + var tilingType = dict.get('TilingType'); + return [ + 'TilingPattern', + args, + operatorList, + matrix, + bbox, + xstep, + ystep, + paintType, + tilingType + ]; +} +exports.Pattern = Pattern; +exports.getTilingPatternIR = getTilingPatternIR; + +/***/ }), +/* 33 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var coreStream = __w_pdfjs_require__(2); +var coreChunkedStream = __w_pdfjs_require__(12); +var coreDocument = __w_pdfjs_require__(24); +var warn = sharedUtil.warn; +var createValidAbsoluteUrl = sharedUtil.createValidAbsoluteUrl; +var shadow = sharedUtil.shadow; +var NotImplementedException = sharedUtil.NotImplementedException; +var MissingDataException = sharedUtil.MissingDataException; +var createPromiseCapability = sharedUtil.createPromiseCapability; +var Util = sharedUtil.Util; +var Stream = coreStream.Stream; +var ChunkedStreamManager = coreChunkedStream.ChunkedStreamManager; +var PDFDocument = coreDocument.PDFDocument; +var BasePdfManager = function BasePdfManagerClosure() { + function BasePdfManager() { + throw new Error('Cannot initialize BaseManagerManager'); + } + BasePdfManager.prototype = { + get docId() { + return this._docId; + }, + get password() { + return this._password; + }, + get docBaseUrl() { + var docBaseUrl = null; + if (this._docBaseUrl) { + var absoluteUrl = createValidAbsoluteUrl(this._docBaseUrl); + if (absoluteUrl) { + docBaseUrl = absoluteUrl.href; + } else { + warn('Invalid absolute docBaseUrl: "' + this._docBaseUrl + '".'); + } + } + return shadow(this, 'docBaseUrl', docBaseUrl); + }, + onLoadedStream: function BasePdfManager_onLoadedStream() { + throw new NotImplementedException(); + }, + ensureDoc: function BasePdfManager_ensureDoc(prop, args) { + return this.ensure(this.pdfDocument, prop, args); + }, + ensureXRef: function BasePdfManager_ensureXRef(prop, args) { + return this.ensure(this.pdfDocument.xref, prop, args); + }, + ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) { + return this.ensure(this.pdfDocument.catalog, prop, args); + }, + getPage: function BasePdfManager_getPage(pageIndex) { + return this.pdfDocument.getPage(pageIndex); + }, + cleanup: function BasePdfManager_cleanup() { + return this.pdfDocument.cleanup(); + }, + ensure: function BasePdfManager_ensure(obj, prop, args) { + return new NotImplementedException(); + }, + requestRange: function BasePdfManager_requestRange(begin, end) { + return new NotImplementedException(); + }, + requestLoadedStream: function BasePdfManager_requestLoadedStream() { + return new NotImplementedException(); + }, + sendProgressiveData: function BasePdfManager_sendProgressiveData(chunk) { + return new NotImplementedException(); + }, + updatePassword: function BasePdfManager_updatePassword(password) { + this._password = password; + }, + terminate: function BasePdfManager_terminate() { + return new NotImplementedException(); + } + }; + return BasePdfManager; +}(); +var LocalPdfManager = function LocalPdfManagerClosure() { + function LocalPdfManager(docId, data, password, evaluatorOptions, docBaseUrl) { + this._docId = docId; + this._password = password; + this._docBaseUrl = docBaseUrl; + this.evaluatorOptions = evaluatorOptions; + var stream = new Stream(data); + this.pdfDocument = new PDFDocument(this, stream); + this._loadedStreamCapability = createPromiseCapability(); + this._loadedStreamCapability.resolve(stream); + } + Util.inherit(LocalPdfManager, BasePdfManager, { + ensure: function LocalPdfManager_ensure(obj, prop, args) { + return new Promise(function (resolve, reject) { + try { + var value = obj[prop]; + var result; + if (typeof value === 'function') { + result = value.apply(obj, args); + } else { + result = value; + } + resolve(result); + } catch (e) { + reject(e); + } + }); + }, + requestRange: function LocalPdfManager_requestRange(begin, end) { + return Promise.resolve(); + }, + requestLoadedStream: function LocalPdfManager_requestLoadedStream() { + }, + onLoadedStream: function LocalPdfManager_onLoadedStream() { + return this._loadedStreamCapability.promise; + }, + terminate: function LocalPdfManager_terminate() { + } + }); + return LocalPdfManager; +}(); +var NetworkPdfManager = function NetworkPdfManagerClosure() { + function NetworkPdfManager(docId, pdfNetworkStream, args, evaluatorOptions, docBaseUrl) { + this._docId = docId; + this._password = args.password; + this._docBaseUrl = docBaseUrl; + this.msgHandler = args.msgHandler; + this.evaluatorOptions = evaluatorOptions; + var params = { + msgHandler: args.msgHandler, + url: args.url, + length: args.length, + disableAutoFetch: args.disableAutoFetch, + rangeChunkSize: args.rangeChunkSize + }; + this.streamManager = new ChunkedStreamManager(pdfNetworkStream, params); + this.pdfDocument = new PDFDocument(this, this.streamManager.getStream()); + } + Util.inherit(NetworkPdfManager, BasePdfManager, { + ensure: function NetworkPdfManager_ensure(obj, prop, args) { + var pdfManager = this; + return new Promise(function (resolve, reject) { + function ensureHelper() { + try { + var result; + var value = obj[prop]; + if (typeof value === 'function') { + result = value.apply(obj, args); + } else { + result = value; + } + resolve(result); + } catch (e) { + if (!(e instanceof MissingDataException)) { + reject(e); + return; + } + pdfManager.streamManager.requestRange(e.begin, e.end).then(ensureHelper, reject); + } + } + ensureHelper(); + }); + }, + requestRange: function NetworkPdfManager_requestRange(begin, end) { + return this.streamManager.requestRange(begin, end); + }, + requestLoadedStream: function NetworkPdfManager_requestLoadedStream() { + this.streamManager.requestAllChunks(); + }, + sendProgressiveData: function NetworkPdfManager_sendProgressiveData(chunk) { + this.streamManager.onReceiveData({ chunk: chunk }); + }, + onLoadedStream: function NetworkPdfManager_onLoadedStream() { + return this.streamManager.onLoadedStream(); + }, + terminate: function NetworkPdfManager_terminate() { + this.streamManager.abort(); + } + }); + return NetworkPdfManager; +}(); +exports.LocalPdfManager = LocalPdfManager; +exports.NetworkPdfManager = NetworkPdfManager; + +/***/ }), +/* 34 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var corePrimitives = __w_pdfjs_require__(1); +var error = sharedUtil.error; +var isSpace = sharedUtil.isSpace; +var EOF = corePrimitives.EOF; +var PostScriptParser = function PostScriptParserClosure() { + function PostScriptParser(lexer) { + this.lexer = lexer; + this.operators = []; + this.token = null; + this.prev = null; + } + PostScriptParser.prototype = { + nextToken: function PostScriptParser_nextToken() { + this.prev = this.token; + this.token = this.lexer.getToken(); + }, + accept: function PostScriptParser_accept(type) { + if (this.token.type === type) { + this.nextToken(); + return true; + } + return false; + }, + expect: function PostScriptParser_expect(type) { + if (this.accept(type)) { + return true; + } + error('Unexpected symbol: found ' + this.token.type + ' expected ' + type + '.'); + }, + parse: function PostScriptParser_parse() { + this.nextToken(); + this.expect(PostScriptTokenTypes.LBRACE); + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + return this.operators; + }, + parseBlock: function PostScriptParser_parseBlock() { + while (true) { + if (this.accept(PostScriptTokenTypes.NUMBER)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.OPERATOR)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + this.parseCondition(); + } else { + return; + } + } + }, + parseCondition: function PostScriptParser_parseCondition() { + var conditionLocation = this.operators.length; + this.operators.push(null, null); + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + if (this.accept(PostScriptTokenTypes.IF)) { + this.operators[conditionLocation] = this.operators.length; + this.operators[conditionLocation + 1] = 'jz'; + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + var jumpLocation = this.operators.length; + this.operators.push(null, null); + var endOfTrue = this.operators.length; + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + this.expect(PostScriptTokenTypes.IFELSE); + this.operators[jumpLocation] = this.operators.length; + this.operators[jumpLocation + 1] = 'j'; + this.operators[conditionLocation] = endOfTrue; + this.operators[conditionLocation + 1] = 'jz'; + } else { + error('PS Function: error parsing conditional.'); + } + } + }; + return PostScriptParser; +}(); +var PostScriptTokenTypes = { + LBRACE: 0, + RBRACE: 1, + NUMBER: 2, + OPERATOR: 3, + IF: 4, + IFELSE: 5 +}; +var PostScriptToken = function PostScriptTokenClosure() { + function PostScriptToken(type, value) { + this.type = type; + this.value = value; + } + var opCache = Object.create(null); + PostScriptToken.getOperator = function PostScriptToken_getOperator(op) { + var opValue = opCache[op]; + if (opValue) { + return opValue; + } + return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op); + }; + PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE, '{'); + PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE, '}'); + PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF'); + PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE, 'IFELSE'); + return PostScriptToken; +}(); +var PostScriptLexer = function PostScriptLexerClosure() { + function PostScriptLexer(stream) { + this.stream = stream; + this.nextChar(); + this.strBuf = []; + } + PostScriptLexer.prototype = { + nextChar: function PostScriptLexer_nextChar() { + return this.currentChar = this.stream.getByte(); + }, + getToken: function PostScriptLexer_getToken() { + var comment = false; + var ch = this.currentChar; + while (true) { + if (ch < 0) { + return EOF; + } + if (comment) { + if (ch === 0x0A || ch === 0x0D) { + comment = false; + } + } else if (ch === 0x25) { + comment = true; + } else if (!isSpace(ch)) { + break; + } + ch = this.nextChar(); + } + switch (ch | 0) { + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x2B: + case 0x2D: + case 0x2E: + return new PostScriptToken(PostScriptTokenTypes.NUMBER, this.getNumber()); + case 0x7B: + this.nextChar(); + return PostScriptToken.LBRACE; + case 0x7D: + this.nextChar(); + return PostScriptToken.RBRACE; + } + var strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch); + while ((ch = this.nextChar()) >= 0 && (ch >= 0x41 && ch <= 0x5A || ch >= 0x61 && ch <= 0x7A)) { + strBuf.push(String.fromCharCode(ch)); + } + var str = strBuf.join(''); + switch (str.toLowerCase()) { + case 'if': + return PostScriptToken.IF; + case 'ifelse': + return PostScriptToken.IFELSE; + default: + return PostScriptToken.getOperator(str); + } + }, + getNumber: function PostScriptLexer_getNumber() { + var ch = this.currentChar; + var strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch); + while ((ch = this.nextChar()) >= 0) { + if (ch >= 0x30 && ch <= 0x39 || ch === 0x2D || ch === 0x2E) { + strBuf.push(String.fromCharCode(ch)); + } else { + break; + } + } + var value = parseFloat(strBuf.join('')); + if (isNaN(value)) { + error('Invalid floating point number: ' + value); + } + return value; + } + }; + return PostScriptLexer; +}(); +exports.PostScriptLexer = PostScriptLexer; +exports.PostScriptParser = PostScriptParser; + +/***/ }), +/* 35 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var sharedUtil = __w_pdfjs_require__(0); +var coreStream = __w_pdfjs_require__(2); +var coreEncodings = __w_pdfjs_require__(4); +var warn = sharedUtil.warn; +var isSpace = sharedUtil.isSpace; +var Stream = coreStream.Stream; +var getEncoding = coreEncodings.getEncoding; +var HINTING_ENABLED = false; +var Type1CharString = function Type1CharStringClosure() { + var COMMAND_MAP = { + 'hstem': [1], + 'vstem': [3], + 'vmoveto': [4], + 'rlineto': [5], + 'hlineto': [6], + 'vlineto': [7], + 'rrcurveto': [8], + 'callsubr': [10], + 'flex': [ + 12, + 35 + ], + 'drop': [ + 12, + 18 + ], + 'endchar': [14], + 'rmoveto': [21], + 'hmoveto': [22], + 'vhcurveto': [30], + 'hvcurveto': [31] + }; + function Type1CharString() { + this.width = 0; + this.lsb = 0; + this.flexing = false; + this.output = []; + this.stack = []; + } + Type1CharString.prototype = { + convert: function Type1CharString_convert(encoded, subrs, seacAnalysisEnabled) { + var count = encoded.length; + var error = false; + var wx, sbx, subrNumber; + for (var i = 0; i < count; i++) { + var value = encoded[i]; + if (value < 32) { + if (value === 12) { + value = (value << 8) + encoded[++i]; + } + switch (value) { + case 1: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case 3: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case 4: + if (this.flexing) { + if (this.stack.length < 1) { + error = true; + break; + } + var dy = this.stack.pop(); + this.stack.push(0, dy); + break; + } + error = this.executeCommand(1, COMMAND_MAP.vmoveto); + break; + case 5: + error = this.executeCommand(2, COMMAND_MAP.rlineto); + break; + case 6: + error = this.executeCommand(1, COMMAND_MAP.hlineto); + break; + case 7: + error = this.executeCommand(1, COMMAND_MAP.vlineto); + break; + case 8: + error = this.executeCommand(6, COMMAND_MAP.rrcurveto); + break; + case 9: + this.stack = []; + break; + case 10: + if (this.stack.length < 1) { + error = true; + break; + } + subrNumber = this.stack.pop(); + error = this.convert(subrs[subrNumber], subrs, seacAnalysisEnabled); + break; + case 11: + return error; + case 13: + if (this.stack.length < 2) { + error = true; + break; + } + wx = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx); + error = this.executeCommand(2, COMMAND_MAP.hmoveto); + break; + case 14: + this.output.push(COMMAND_MAP.endchar[0]); + break; + case 21: + if (this.flexing) { + break; + } + error = this.executeCommand(2, COMMAND_MAP.rmoveto); + break; + case 22: + if (this.flexing) { + this.stack.push(0); + break; + } + error = this.executeCommand(1, COMMAND_MAP.hmoveto); + break; + case 30: + error = this.executeCommand(4, COMMAND_MAP.vhcurveto); + break; + case 31: + error = this.executeCommand(4, COMMAND_MAP.hvcurveto); + break; + case (12 << 8) + 0: + this.stack = []; + break; + case (12 << 8) + 1: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case (12 << 8) + 2: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case (12 << 8) + 6: + if (seacAnalysisEnabled) { + this.seac = this.stack.splice(-4, 4); + error = this.executeCommand(0, COMMAND_MAP.endchar); + } else { + error = this.executeCommand(4, COMMAND_MAP.endchar); + } + break; + case (12 << 8) + 7: + if (this.stack.length < 4) { + error = true; + break; + } + this.stack.pop(); + wx = this.stack.pop(); + var sby = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx, sby); + error = this.executeCommand(3, COMMAND_MAP.rmoveto); + break; + case (12 << 8) + 12: + if (this.stack.length < 2) { + error = true; + break; + } + var num2 = this.stack.pop(); + var num1 = this.stack.pop(); + this.stack.push(num1 / num2); + break; + case (12 << 8) + 16: + if (this.stack.length < 2) { + error = true; + break; + } + subrNumber = this.stack.pop(); + var numArgs = this.stack.pop(); + if (subrNumber === 0 && numArgs === 3) { + var flexArgs = this.stack.splice(this.stack.length - 17, 17); + this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]); + error = this.executeCommand(13, COMMAND_MAP.flex, true); + this.flexing = false; + this.stack.push(flexArgs[15], flexArgs[16]); + } else if (subrNumber === 1 && numArgs === 0) { + this.flexing = true; + } + break; + case (12 << 8) + 17: + break; + case (12 << 8) + 33: + this.stack = []; + break; + default: + warn('Unknown type 1 charstring command of "' + value + '"'); + break; + } + if (error) { + break; + } + continue; + } else if (value <= 246) { + value = value - 139; + } else if (value <= 250) { + value = (value - 247) * 256 + encoded[++i] + 108; + } else if (value <= 254) { + value = -((value - 251) * 256) - encoded[++i] - 108; + } else { + value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0; + } + this.stack.push(value); + } + return error; + }, + executeCommand: function (howManyArgs, command, keepStack) { + var stackLength = this.stack.length; + if (howManyArgs > stackLength) { + return true; + } + var start = stackLength - howManyArgs; + for (var i = start; i < stackLength; i++) { + var value = this.stack[i]; + if (value === (value | 0)) { + this.output.push(28, value >> 8 & 0xff, value & 0xff); + } else { + value = 65536 * value | 0; + this.output.push(255, value >> 24 & 0xFF, value >> 16 & 0xFF, value >> 8 & 0xFF, value & 0xFF); + } + } + this.output.push.apply(this.output, command); + if (keepStack) { + this.stack.splice(start, howManyArgs); + } else { + this.stack.length = 0; + } + return false; + } + }; + return Type1CharString; +}(); +var Type1Parser = function Type1ParserClosure() { + var EEXEC_ENCRYPT_KEY = 55665; + var CHAR_STRS_ENCRYPT_KEY = 4330; + function isHexDigit(code) { + return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102; + } + function decrypt(data, key, discardNumber) { + if (discardNumber >= data.length) { + return new Uint8Array(0); + } + var r = key | 0, c1 = 52845, c2 = 22719, i, j; + for (i = 0; i < discardNumber; i++) { + r = (data[i] + r) * c1 + c2 & (1 << 16) - 1; + } + var count = data.length - discardNumber; + var decrypted = new Uint8Array(count); + for (i = discardNumber, j = 0; j < count; i++, j++) { + var value = data[i]; + decrypted[j] = value ^ r >> 8; + r = (value + r) * c1 + c2 & (1 << 16) - 1; + } + return decrypted; + } + function decryptAscii(data, key, discardNumber) { + var r = key | 0, c1 = 52845, c2 = 22719; + var count = data.length, maybeLength = count >>> 1; + var decrypted = new Uint8Array(maybeLength); + var i, j; + for (i = 0, j = 0; i < count; i++) { + var digit1 = data[i]; + if (!isHexDigit(digit1)) { + continue; + } + i++; + var digit2; + while (i < count && !isHexDigit(digit2 = data[i])) { + i++; + } + if (i < count) { + var value = parseInt(String.fromCharCode(digit1, digit2), 16); + decrypted[j++] = value ^ r >> 8; + r = (value + r) * c1 + c2 & (1 << 16) - 1; + } + } + return Array.prototype.slice.call(decrypted, discardNumber, j); + } + function isSpecial(c) { + return c === 0x2F || c === 0x5B || c === 0x5D || c === 0x7B || c === 0x7D || c === 0x28 || c === 0x29; + } + function Type1Parser(stream, encrypted, seacAnalysisEnabled) { + if (encrypted) { + var data = stream.getBytes(); + var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3])); + stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4)); + } + this.seacAnalysisEnabled = !!seacAnalysisEnabled; + this.stream = stream; + this.nextChar(); + } + Type1Parser.prototype = { + readNumberArray: function Type1Parser_readNumberArray() { + this.getToken(); + var array = []; + while (true) { + var token = this.getToken(); + if (token === null || token === ']' || token === '}') { + break; + } + array.push(parseFloat(token || 0)); + } + return array; + }, + readNumber: function Type1Parser_readNumber() { + var token = this.getToken(); + return parseFloat(token || 0); + }, + readInt: function Type1Parser_readInt() { + var token = this.getToken(); + return parseInt(token || 0, 10) | 0; + }, + readBoolean: function Type1Parser_readBoolean() { + var token = this.getToken(); + return token === 'true' ? 1 : 0; + }, + nextChar: function Type1_nextChar() { + return this.currentChar = this.stream.getByte(); + }, + getToken: function Type1Parser_getToken() { + var comment = false; + var ch = this.currentChar; + while (true) { + if (ch === -1) { + return null; + } + if (comment) { + if (ch === 0x0A || ch === 0x0D) { + comment = false; + } + } else if (ch === 0x25) { + comment = true; + } else if (!isSpace(ch)) { + break; + } + ch = this.nextChar(); + } + if (isSpecial(ch)) { + this.nextChar(); + return String.fromCharCode(ch); + } + var token = ''; + do { + token += String.fromCharCode(ch); + ch = this.nextChar(); + } while (ch >= 0 && !isSpace(ch) && !isSpecial(ch)); + return token; + }, + extractFontProgram: function Type1Parser_extractFontProgram() { + var stream = this.stream; + var subrs = [], charstrings = []; + var privateData = Object.create(null); + privateData['lenIV'] = 4; + var program = { + subrs: [], + charstrings: [], + properties: { 'privateData': privateData } + }; + var token, length, data, lenIV, encoded; + while ((token = this.getToken()) !== null) { + if (token !== '/') { + continue; + } + token = this.getToken(); + switch (token) { + case 'CharStrings': + this.getToken(); + this.getToken(); + this.getToken(); + this.getToken(); + while (true) { + token = this.getToken(); + if (token === null || token === 'end') { + break; + } + if (token !== '/') { + continue; + } + var glyph = this.getToken(); + length = this.readInt(); + this.getToken(); + data = stream.makeSubStream(stream.pos, length); + lenIV = program.properties.privateData['lenIV']; + encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV); + stream.skip(length); + this.nextChar(); + token = this.getToken(); + if (token === 'noaccess') { + this.getToken(); + } + charstrings.push({ + glyph: glyph, + encoded: encoded + }); + } + break; + case 'Subrs': + this.readInt(); + this.getToken(); + while ((token = this.getToken()) === 'dup') { + var index = this.readInt(); + length = this.readInt(); + this.getToken(); + data = stream.makeSubStream(stream.pos, length); + lenIV = program.properties.privateData['lenIV']; + encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV); + stream.skip(length); + this.nextChar(); + token = this.getToken(); + if (token === 'noaccess') { + this.getToken(); + } + subrs[index] = encoded; + } + break; + case 'BlueValues': + case 'OtherBlues': + case 'FamilyBlues': + case 'FamilyOtherBlues': + var blueArray = this.readNumberArray(); + if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) { + program.properties.privateData[token] = blueArray; + } + break; + case 'StemSnapH': + case 'StemSnapV': + program.properties.privateData[token] = this.readNumberArray(); + break; + case 'StdHW': + case 'StdVW': + program.properties.privateData[token] = this.readNumberArray()[0]; + break; + case 'BlueShift': + case 'lenIV': + case 'BlueFuzz': + case 'BlueScale': + case 'LanguageGroup': + case 'ExpansionFactor': + program.properties.privateData[token] = this.readNumber(); + break; + case 'ForceBold': + program.properties.privateData[token] = this.readBoolean(); + break; + } + } + for (var i = 0; i < charstrings.length; i++) { + glyph = charstrings[i].glyph; + encoded = charstrings[i].encoded; + var charString = new Type1CharString(); + var error = charString.convert(encoded, subrs, this.seacAnalysisEnabled); + var output = charString.output; + if (error) { + output = [14]; + } + program.charstrings.push({ + glyphName: glyph, + charstring: output, + width: charString.width, + lsb: charString.lsb, + seac: charString.seac + }); + } + return program; + }, + extractFontHeader: function Type1Parser_extractFontHeader(properties) { + var token; + while ((token = this.getToken()) !== null) { + if (token !== '/') { + continue; + } + token = this.getToken(); + switch (token) { + case 'FontMatrix': + var matrix = this.readNumberArray(); + properties.fontMatrix = matrix; + break; + case 'Encoding': + var encodingArg = this.getToken(); + var encoding; + if (!/^\d+$/.test(encodingArg)) { + encoding = getEncoding(encodingArg); + } else { + encoding = []; + var size = parseInt(encodingArg, 10) | 0; + this.getToken(); + for (var j = 0; j < size; j++) { + token = this.getToken(); + while (token !== 'dup' && token !== 'def') { + token = this.getToken(); + if (token === null) { + return; + } + } + if (token === 'def') { + break; + } + var index = this.readInt(); + this.getToken(); + var glyph = this.getToken(); + encoding[index] = glyph; + this.getToken(); + } + } + properties.builtInEncoding = encoding; + break; + case 'FontBBox': + var fontBBox = this.readNumberArray(); + properties.ascent = Math.max(fontBBox[3], fontBBox[1]); + properties.descent = Math.min(fontBBox[1], fontBBox[3]); + properties.ascentScaled = true; + break; + } + } + } + }; + return Type1Parser; +}(); +exports.Type1Parser = Type1Parser; + +/***/ }), +/* 36 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) { +if (typeof PDFJS === 'undefined' || !PDFJS.compatibilityChecked) { + var globalScope = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this; + var userAgent = typeof navigator !== 'undefined' && navigator.userAgent || ''; + var isAndroid = /Android/.test(userAgent); + var isAndroidPre3 = /Android\s[0-2][^\d]/.test(userAgent); + var isAndroidPre5 = /Android\s[0-4][^\d]/.test(userAgent); + var isChrome = userAgent.indexOf('Chrom') >= 0; + var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(userAgent); + var isIOSChrome = userAgent.indexOf('CriOS') >= 0; + var isIE = userAgent.indexOf('Trident') >= 0; + var isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent); + var isOpera = userAgent.indexOf('Opera') >= 0; + var isSafari = /Safari\//.test(userAgent) && !/(Chrome\/|Android\s)/.test(userAgent); + var hasDOM = typeof window === 'object' && typeof document === 'object'; + if (typeof PDFJS === 'undefined') { + globalScope.PDFJS = {}; + } + PDFJS.compatibilityChecked = true; + (function checkTypedArrayCompatibility() { + if (typeof Uint8Array !== 'undefined') { + if (typeof Uint8Array.prototype.subarray === 'undefined') { + Uint8Array.prototype.subarray = function subarray(start, end) { + return new Uint8Array(this.slice(start, end)); + }; + Float32Array.prototype.subarray = function subarray(start, end) { + return new Float32Array(this.slice(start, end)); + }; + } + if (typeof Float64Array === 'undefined') { + globalScope.Float64Array = Float32Array; + } + return; + } + function subarray(start, end) { + return new TypedArray(this.slice(start, end)); + } + function setArrayOffset(array, offset) { + if (arguments.length < 2) { + offset = 0; + } + for (var i = 0, n = array.length; i < n; ++i, ++offset) { + this[offset] = array[i] & 0xFF; + } + } + function TypedArray(arg1) { + var result, i, n; + if (typeof arg1 === 'number') { + result = []; + for (i = 0; i < arg1; ++i) { + result[i] = 0; + } + } else if ('slice' in arg1) { + result = arg1.slice(0); + } else { + result = []; + for (i = 0, n = arg1.length; i < n; ++i) { + result[i] = arg1[i]; + } + } + result.subarray = subarray; + result.buffer = result; + result.byteLength = result.length; + result.set = setArrayOffset; + if (typeof arg1 === 'object' && arg1.buffer) { + result.buffer = arg1.buffer; + } + return result; + } + globalScope.Uint8Array = TypedArray; + globalScope.Int8Array = TypedArray; + globalScope.Uint32Array = TypedArray; + globalScope.Int32Array = TypedArray; + globalScope.Uint16Array = TypedArray; + globalScope.Float32Array = TypedArray; + globalScope.Float64Array = TypedArray; + }()); + (function normalizeURLObject() { + if (!globalScope.URL) { + globalScope.URL = globalScope.webkitURL; + } + }()); + (function checkObjectDefinePropertyCompatibility() { + if (typeof Object.defineProperty !== 'undefined') { + var definePropertyPossible = true; + try { + if (hasDOM) { + Object.defineProperty(new Image(), 'id', { value: 'test' }); + } + var Test = function Test() { + }; + Test.prototype = { + get id() { + } + }; + Object.defineProperty(new Test(), 'id', { + value: '', + configurable: true, + enumerable: true, + writable: false + }); + } catch (e) { + definePropertyPossible = false; + } + if (definePropertyPossible) { + return; + } + } + Object.defineProperty = function objectDefineProperty(obj, name, def) { + delete obj[name]; + if ('get' in def) { + obj.__defineGetter__(name, def['get']); + } + if ('set' in def) { + obj.__defineSetter__(name, def['set']); + } + if ('value' in def) { + obj.__defineSetter__(name, function objectDefinePropertySetter(value) { + this.__defineGetter__(name, function objectDefinePropertyGetter() { + return value; + }); + return value; + }); + obj[name] = def.value; + } + }; + }()); + (function checkXMLHttpRequestResponseCompatibility() { + if (typeof XMLHttpRequest === 'undefined') { + return; + } + var xhrPrototype = XMLHttpRequest.prototype; + var xhr = new XMLHttpRequest(); + if (!('overrideMimeType' in xhr)) { + Object.defineProperty(xhrPrototype, 'overrideMimeType', { + value: function xmlHttpRequestOverrideMimeType(mimeType) { + } + }); + } + if ('responseType' in xhr) { + return; + } + Object.defineProperty(xhrPrototype, 'responseType', { + get: function xmlHttpRequestGetResponseType() { + return this._responseType || 'text'; + }, + set: function xmlHttpRequestSetResponseType(value) { + if (value === 'text' || value === 'arraybuffer') { + this._responseType = value; + if (value === 'arraybuffer' && typeof this.overrideMimeType === 'function') { + this.overrideMimeType('text/plain; charset=x-user-defined'); + } + } + } + }); + if (typeof VBArray !== 'undefined') { + Object.defineProperty(xhrPrototype, 'response', { + get: function xmlHttpRequestResponseGet() { + if (this.responseType === 'arraybuffer') { + return new Uint8Array(new VBArray(this.responseBody).toArray()); + } + return this.responseText; + } + }); + return; + } + Object.defineProperty(xhrPrototype, 'response', { + get: function xmlHttpRequestResponseGet() { + if (this.responseType !== 'arraybuffer') { + return this.responseText; + } + var text = this.responseText; + var i, n = text.length; + var result = new Uint8Array(n); + for (i = 0; i < n; ++i) { + result[i] = text.charCodeAt(i) & 0xFF; + } + return result.buffer; + } + }); + }()); + (function checkWindowBtoaCompatibility() { + if ('btoa' in globalScope) { + return; + } + var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + globalScope.btoa = function (chars) { + var buffer = ''; + var i, n; + for (i = 0, n = chars.length; i < n; i += 3) { + var b1 = chars.charCodeAt(i) & 0xFF; + var b2 = chars.charCodeAt(i + 1) & 0xFF; + var b3 = chars.charCodeAt(i + 2) & 0xFF; + var d1 = b1 >> 2, d2 = (b1 & 3) << 4 | b2 >> 4; + var d3 = i + 1 < n ? (b2 & 0xF) << 2 | b3 >> 6 : 64; + var d4 = i + 2 < n ? b3 & 0x3F : 64; + buffer += digits.charAt(d1) + digits.charAt(d2) + digits.charAt(d3) + digits.charAt(d4); + } + return buffer; + }; + }()); + (function checkWindowAtobCompatibility() { + if ('atob' in globalScope) { + return; + } + var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + globalScope.atob = function (input) { + input = input.replace(/=+$/, ''); + if (input.length % 4 === 1) { + throw new Error('bad atob input'); + } + for (var bc = 0, bs, buffer, idx = 0, output = ''; buffer = input.charAt(idx++); ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0) { + buffer = digits.indexOf(buffer); + } + return output; + }; + }()); + (function checkFunctionPrototypeBindCompatibility() { + if (typeof Function.prototype.bind !== 'undefined') { + return; + } + Function.prototype.bind = function functionPrototypeBind(obj) { + var fn = this, headArgs = Array.prototype.slice.call(arguments, 1); + var bound = function functionPrototypeBindBound() { + var args = headArgs.concat(Array.prototype.slice.call(arguments)); + return fn.apply(obj, args); + }; + return bound; + }; + }()); + (function checkDatasetProperty() { + if (!hasDOM) { + return; + } + var div = document.createElement('div'); + if ('dataset' in div) { + return; + } + Object.defineProperty(HTMLElement.prototype, 'dataset', { + get: function () { + if (this._dataset) { + return this._dataset; + } + var dataset = {}; + for (var j = 0, jj = this.attributes.length; j < jj; j++) { + var attribute = this.attributes[j]; + if (attribute.name.substring(0, 5) !== 'data-') { + continue; + } + var key = attribute.name.substring(5).replace(/\-([a-z])/g, function (all, ch) { + return ch.toUpperCase(); + }); + dataset[key] = attribute.value; + } + Object.defineProperty(this, '_dataset', { + value: dataset, + writable: false, + enumerable: false + }); + return dataset; + }, + enumerable: true + }); + }()); + (function checkClassListProperty() { + function changeList(element, itemName, add, remove) { + var s = element.className || ''; + var list = s.split(/\s+/g); + if (list[0] === '') { + list.shift(); + } + var index = list.indexOf(itemName); + if (index < 0 && add) { + list.push(itemName); + } + if (index >= 0 && remove) { + list.splice(index, 1); + } + element.className = list.join(' '); + return index >= 0; + } + if (!hasDOM) { + return; + } + var div = document.createElement('div'); + if ('classList' in div) { + return; + } + var classListPrototype = { + add: function (name) { + changeList(this.element, name, true, false); + }, + contains: function (name) { + return changeList(this.element, name, false, false); + }, + remove: function (name) { + changeList(this.element, name, false, true); + }, + toggle: function (name) { + changeList(this.element, name, true, true); + } + }; + Object.defineProperty(HTMLElement.prototype, 'classList', { + get: function () { + if (this._classList) { + return this._classList; + } + var classList = Object.create(classListPrototype, { + element: { + value: this, + writable: false, + enumerable: true + } + }); + Object.defineProperty(this, '_classList', { + value: classList, + writable: false, + enumerable: false + }); + return classList; + }, + enumerable: true + }); + }()); + (function checkWorkerConsoleCompatibility() { + if (typeof importScripts === 'undefined' || 'console' in globalScope) { + return; + } + var consoleTimer = {}; + var workerConsole = { + log: function log() { + var args = Array.prototype.slice.call(arguments); + globalScope.postMessage({ + targetName: 'main', + action: 'console_log', + data: args + }); + }, + error: function error() { + var args = Array.prototype.slice.call(arguments); + globalScope.postMessage({ + targetName: 'main', + action: 'console_error', + data: args + }); + }, + time: function time(name) { + consoleTimer[name] = Date.now(); + }, + timeEnd: function timeEnd(name) { + var time = consoleTimer[name]; + if (!time) { + throw new Error('Unknown timer name ' + name); + } + this.log('Timer:', name, Date.now() - time); + } + }; + globalScope.console = workerConsole; + }()); + (function checkConsoleCompatibility() { + if (!hasDOM) { + return; + } + if (!('console' in window)) { + window.console = { + log: function () { + }, + error: function () { + }, + warn: function () { + } + }; + return; + } + if (!('bind' in console.log)) { + console.log = function (fn) { + return function (msg) { + return fn(msg); + }; + }(console.log); + console.error = function (fn) { + return function (msg) { + return fn(msg); + }; + }(console.error); + console.warn = function (fn) { + return function (msg) { + return fn(msg); + }; + }(console.warn); + return; + } + }()); + (function checkOnClickCompatibility() { + function ignoreIfTargetDisabled(event) { + if (isDisabled(event.target)) { + event.stopPropagation(); + } + } + function isDisabled(node) { + return node.disabled || node.parentNode && isDisabled(node.parentNode); + } + if (isOpera) { + document.addEventListener('click', ignoreIfTargetDisabled, true); + } + }()); + (function checkOnBlobSupport() { + if (isIE || isIOSChrome) { + PDFJS.disableCreateObjectURL = true; + } + }()); + (function checkNavigatorLanguage() { + if (typeof navigator === 'undefined') { + return; + } + if ('language' in navigator) { + return; + } + PDFJS.locale = navigator.userLanguage || 'en-US'; + }()); + (function checkRangeRequests() { + if (isSafari || isAndroidPre3 || isChromeWithRangeBug || isIOS) { + PDFJS.disableRange = true; + PDFJS.disableStream = true; + } + }()); + (function checkHistoryManipulation() { + if (!hasDOM) { + return; + } + if (!history.pushState || isAndroidPre3) { + PDFJS.disableHistory = true; + } + }()); + (function checkSetPresenceInImageData() { + if (!hasDOM) { + return; + } + if (window.CanvasPixelArray) { + if (typeof window.CanvasPixelArray.prototype.set !== 'function') { + window.CanvasPixelArray.prototype.set = function (arr) { + for (var i = 0, ii = this.length; i < ii; i++) { + this[i] = arr[i]; + } + }; + } + } else { + var polyfill = false, versionMatch; + if (isChrome) { + versionMatch = userAgent.match(/Chrom(e|ium)\/([0-9]+)\./); + polyfill = versionMatch && parseInt(versionMatch[2]) < 21; + } else if (isAndroid) { + polyfill = isAndroidPre5; + } else if (isSafari) { + versionMatch = userAgent.match(/Version\/([0-9]+)\.([0-9]+)\.([0-9]+) Safari\//); + polyfill = versionMatch && parseInt(versionMatch[1]) < 6; + } + if (polyfill) { + var contextPrototype = window.CanvasRenderingContext2D.prototype; + var createImageData = contextPrototype.createImageData; + contextPrototype.createImageData = function (w, h) { + var imageData = createImageData.call(this, w, h); + imageData.data.set = function (arr) { + for (var i = 0, ii = this.length; i < ii; i++) { + this[i] = arr[i]; + } + }; + return imageData; + }; + contextPrototype = null; + } + } + }()); + (function checkRequestAnimationFrame() { + function fakeRequestAnimationFrame(callback) { + window.setTimeout(callback, 20); + } + if (!hasDOM) { + return; + } + if (isIOS) { + window.requestAnimationFrame = fakeRequestAnimationFrame; + return; + } + if ('requestAnimationFrame' in window) { + return; + } + window.requestAnimationFrame = window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || fakeRequestAnimationFrame; + }()); + (function checkCanvasSizeLimitation() { + if (isIOS || isAndroid) { + PDFJS.maxCanvasPixels = 5242880; + } + }()); + (function checkFullscreenSupport() { + if (!hasDOM) { + return; + } + if (isIE && window.parent !== window) { + PDFJS.disableFullscreen = true; + } + }()); + (function checkCurrentScript() { + if (!hasDOM) { + return; + } + if ('currentScript' in document) { + return; + } + Object.defineProperty(document, 'currentScript', { + get: function () { + var scripts = document.getElementsByTagName('script'); + return scripts[scripts.length - 1]; + }, + enumerable: true, + configurable: true + }); + }()); + (function checkInputTypeNumberAssign() { + if (!hasDOM) { + return; + } + var el = document.createElement('input'); + try { + el.type = 'number'; + } catch (ex) { + var inputProto = el.constructor.prototype; + var typeProperty = Object.getOwnPropertyDescriptor(inputProto, 'type'); + Object.defineProperty(inputProto, 'type', { + get: function () { + return typeProperty.get.call(this); + }, + set: function (value) { + typeProperty.set.call(this, value === 'number' ? 'text' : value); + }, + enumerable: true, + configurable: true + }); + } + }()); + (function checkDocumentReadyState() { + if (!hasDOM) { + return; + } + if (!document.attachEvent) { + return; + } + var documentProto = document.constructor.prototype; + var readyStateProto = Object.getOwnPropertyDescriptor(documentProto, 'readyState'); + Object.defineProperty(documentProto, 'readyState', { + get: function () { + var value = readyStateProto.get.call(this); + return value === 'interactive' ? 'loading' : value; + }, + set: function (value) { + readyStateProto.set.call(this, value); + }, + enumerable: true, + configurable: true + }); + }()); + (function checkChildNodeRemove() { + if (!hasDOM) { + return; + } + if (typeof Element.prototype.remove !== 'undefined') { + return; + } + Element.prototype.remove = function () { + if (this.parentNode) { + this.parentNode.removeChild(this); + } + }; + }()); + (function checkPromise() { + if (globalScope.Promise) { + if (typeof globalScope.Promise.all !== 'function') { + globalScope.Promise.all = function (iterable) { + var count = 0, results = [], resolve, reject; + var promise = new globalScope.Promise(function (resolve_, reject_) { + resolve = resolve_; + reject = reject_; + }); + iterable.forEach(function (p, i) { + count++; + p.then(function (result) { + results[i] = result; + count--; + if (count === 0) { + resolve(results); + } + }, reject); + }); + if (count === 0) { + resolve(results); + } + return promise; + }; + } + if (typeof globalScope.Promise.resolve !== 'function') { + globalScope.Promise.resolve = function (value) { + return new globalScope.Promise(function (resolve) { + resolve(value); + }); + }; + } + if (typeof globalScope.Promise.reject !== 'function') { + globalScope.Promise.reject = function (reason) { + return new globalScope.Promise(function (resolve, reject) { + reject(reason); + }); + }; + } + if (typeof globalScope.Promise.prototype.catch !== 'function') { + globalScope.Promise.prototype.catch = function (onReject) { + return globalScope.Promise.prototype.then(undefined, onReject); + }; + } + return; + } + var STATUS_PENDING = 0; + var STATUS_RESOLVED = 1; + var STATUS_REJECTED = 2; + var REJECTION_TIMEOUT = 500; + var HandlerManager = { + handlers: [], + running: false, + unhandledRejections: [], + pendingRejectionCheck: false, + scheduleHandlers: function scheduleHandlers(promise) { + if (promise._status === STATUS_PENDING) { + return; + } + this.handlers = this.handlers.concat(promise._handlers); + promise._handlers = []; + if (this.running) { + return; + } + this.running = true; + setTimeout(this.runHandlers.bind(this), 0); + }, + runHandlers: function runHandlers() { + var RUN_TIMEOUT = 1; + var timeoutAt = Date.now() + RUN_TIMEOUT; + while (this.handlers.length > 0) { + var handler = this.handlers.shift(); + var nextStatus = handler.thisPromise._status; + var nextValue = handler.thisPromise._value; + try { + if (nextStatus === STATUS_RESOLVED) { + if (typeof handler.onResolve === 'function') { + nextValue = handler.onResolve(nextValue); + } + } else if (typeof handler.onReject === 'function') { + nextValue = handler.onReject(nextValue); + nextStatus = STATUS_RESOLVED; + if (handler.thisPromise._unhandledRejection) { + this.removeUnhandeledRejection(handler.thisPromise); + } + } + } catch (ex) { + nextStatus = STATUS_REJECTED; + nextValue = ex; + } + handler.nextPromise._updateStatus(nextStatus, nextValue); + if (Date.now() >= timeoutAt) { + break; + } + } + if (this.handlers.length > 0) { + setTimeout(this.runHandlers.bind(this), 0); + return; + } + this.running = false; + }, + addUnhandledRejection: function addUnhandledRejection(promise) { + this.unhandledRejections.push({ + promise: promise, + time: Date.now() + }); + this.scheduleRejectionCheck(); + }, + removeUnhandeledRejection: function removeUnhandeledRejection(promise) { + promise._unhandledRejection = false; + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (this.unhandledRejections[i].promise === promise) { + this.unhandledRejections.splice(i); + i--; + } + } + }, + scheduleRejectionCheck: function scheduleRejectionCheck() { + if (this.pendingRejectionCheck) { + return; + } + this.pendingRejectionCheck = true; + setTimeout(function rejectionCheck() { + this.pendingRejectionCheck = false; + var now = Date.now(); + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) { + var unhandled = this.unhandledRejections[i].promise._value; + var msg = 'Unhandled rejection: ' + unhandled; + if (unhandled.stack) { + msg += '\n' + unhandled.stack; + } + try { + throw new Error(msg); + } catch (_) { + console.warn(msg); + } + this.unhandledRejections.splice(i); + i--; + } + } + if (this.unhandledRejections.length) { + this.scheduleRejectionCheck(); + } + }.bind(this), REJECTION_TIMEOUT); + } + }; + var Promise = function Promise(resolver) { + this._status = STATUS_PENDING; + this._handlers = []; + try { + resolver.call(this, this._resolve.bind(this), this._reject.bind(this)); + } catch (e) { + this._reject(e); + } + }; + Promise.all = function Promise_all(promises) { + var resolveAll, rejectAll; + var deferred = new Promise(function (resolve, reject) { + resolveAll = resolve; + rejectAll = reject; + }); + var unresolved = promises.length; + var results = []; + if (unresolved === 0) { + resolveAll(results); + return deferred; + } + function reject(reason) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results = []; + rejectAll(reason); + } + for (var i = 0, ii = promises.length; i < ii; ++i) { + var promise = promises[i]; + var resolve = function (i) { + return function (value) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results[i] = value; + unresolved--; + if (unresolved === 0) { + resolveAll(results); + } + }; + }(i); + if (Promise.isPromise(promise)) { + promise.then(resolve, reject); + } else { + resolve(promise); + } + } + return deferred; + }; + Promise.isPromise = function Promise_isPromise(value) { + return value && typeof value.then === 'function'; + }; + Promise.resolve = function Promise_resolve(value) { + return new Promise(function (resolve) { + resolve(value); + }); + }; + Promise.reject = function Promise_reject(reason) { + return new Promise(function (resolve, reject) { + reject(reason); + }); + }; + Promise.prototype = { + _status: null, + _value: null, + _handlers: null, + _unhandledRejection: null, + _updateStatus: function Promise__updateStatus(status, value) { + if (this._status === STATUS_RESOLVED || this._status === STATUS_REJECTED) { + return; + } + if (status === STATUS_RESOLVED && Promise.isPromise(value)) { + value.then(this._updateStatus.bind(this, STATUS_RESOLVED), this._updateStatus.bind(this, STATUS_REJECTED)); + return; + } + this._status = status; + this._value = value; + if (status === STATUS_REJECTED && this._handlers.length === 0) { + this._unhandledRejection = true; + HandlerManager.addUnhandledRejection(this); + } + HandlerManager.scheduleHandlers(this); + }, + _resolve: function Promise_resolve(value) { + this._updateStatus(STATUS_RESOLVED, value); + }, + _reject: function Promise_reject(reason) { + this._updateStatus(STATUS_REJECTED, reason); + }, + then: function Promise_then(onResolve, onReject) { + var nextPromise = new Promise(function (resolve, reject) { + this.resolve = resolve; + this.reject = reject; + }); + this._handlers.push({ + thisPromise: this, + onResolve: onResolve, + onReject: onReject, + nextPromise: nextPromise + }); + HandlerManager.scheduleHandlers(this); + return nextPromise; + }, + catch: function Promise_catch(onReject) { + return this.then(undefined, onReject); + } + }; + globalScope.Promise = Promise; + }()); + (function checkWeakMap() { + if (globalScope.WeakMap) { + return; + } + var id = 0; + function WeakMap() { + this.id = '$weakmap' + id++; + } + WeakMap.prototype = { + has: function (obj) { + return !!Object.getOwnPropertyDescriptor(obj, this.id); + }, + get: function (obj, defaultValue) { + return this.has(obj) ? obj[this.id] : defaultValue; + }, + set: function (obj, value) { + Object.defineProperty(obj, this.id, { + value: value, + enumerable: false, + configurable: true + }); + }, + delete: function (obj) { + delete obj[this.id]; + } + }; + globalScope.WeakMap = WeakMap; + }()); + (function checkURLConstructor() { + var hasWorkingUrl = false; + try { + if (typeof URL === 'function' && typeof URL.prototype === 'object' && 'origin' in URL.prototype) { + var u = new URL('b', 'http://a'); + u.pathname = 'c%20d'; + hasWorkingUrl = u.href === 'http://a/c%20d'; + } + } catch (e) { + } + if (hasWorkingUrl) { + return; + } + var relative = Object.create(null); + relative['ftp'] = 21; + relative['file'] = 0; + relative['gopher'] = 70; + relative['http'] = 80; + relative['https'] = 443; + relative['ws'] = 80; + relative['wss'] = 443; + var relativePathDotMapping = Object.create(null); + relativePathDotMapping['%2e'] = '.'; + relativePathDotMapping['.%2e'] = '..'; + relativePathDotMapping['%2e.'] = '..'; + relativePathDotMapping['%2e%2e'] = '..'; + function isRelativeScheme(scheme) { + return relative[scheme] !== undefined; + } + function invalid() { + clear.call(this); + this._isInvalid = true; + } + function IDNAToASCII(h) { + if (h === '') { + invalid.call(this); + } + return h.toLowerCase(); + } + function percentEscape(c) { + var unicode = c.charCodeAt(0); + if (unicode > 0x20 && unicode < 0x7F && [ + 0x22, + 0x23, + 0x3C, + 0x3E, + 0x3F, + 0x60 + ].indexOf(unicode) === -1) { + return c; + } + return encodeURIComponent(c); + } + function percentEscapeQuery(c) { + var unicode = c.charCodeAt(0); + if (unicode > 0x20 && unicode < 0x7F && [ + 0x22, + 0x23, + 0x3C, + 0x3E, + 0x60 + ].indexOf(unicode) === -1) { + return c; + } + return encodeURIComponent(c); + } + var EOF, ALPHA = /[a-zA-Z]/, ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/; + function parse(input, stateOverride, base) { + function err(message) { + errors.push(message); + } + var state = stateOverride || 'scheme start', cursor = 0, buffer = '', seenAt = false, seenBracket = false, errors = []; + loop: + while ((input[cursor - 1] !== EOF || cursor === 0) && !this._isInvalid) { + var c = input[cursor]; + switch (state) { + case 'scheme start': + if (c && ALPHA.test(c)) { + buffer += c.toLowerCase(); + state = 'scheme'; + } else if (!stateOverride) { + buffer = ''; + state = 'no scheme'; + continue; + } else { + err('Invalid scheme.'); + break loop; + } + break; + case 'scheme': + if (c && ALPHANUMERIC.test(c)) { + buffer += c.toLowerCase(); + } else if (c === ':') { + this._scheme = buffer; + buffer = ''; + if (stateOverride) { + break loop; + } + if (isRelativeScheme(this._scheme)) { + this._isRelative = true; + } + if (this._scheme === 'file') { + state = 'relative'; + } else if (this._isRelative && base && base._scheme === this._scheme) { + state = 'relative or authority'; + } else if (this._isRelative) { + state = 'authority first slash'; + } else { + state = 'scheme data'; + } + } else if (!stateOverride) { + buffer = ''; + cursor = 0; + state = 'no scheme'; + continue; + } else if (EOF === c) { + break loop; + } else { + err('Code point not allowed in scheme: ' + c); + break loop; + } + break; + case 'scheme data': + if (c === '?') { + this._query = '?'; + state = 'query'; + } else if (c === '#') { + this._fragment = '#'; + state = 'fragment'; + } else { + if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) { + this._schemeData += percentEscape(c); + } + } + break; + case 'no scheme': + if (!base || !isRelativeScheme(base._scheme)) { + err('Missing scheme.'); + invalid.call(this); + } else { + state = 'relative'; + continue; + } + break; + case 'relative or authority': + if (c === '/' && input[cursor + 1] === '/') { + state = 'authority ignore slashes'; + } else { + err('Expected /, got: ' + c); + state = 'relative'; + continue; + } + break; + case 'relative': + this._isRelative = true; + if ('file' !== this._scheme) { + this._scheme = base._scheme; + } + if (EOF === c) { + this._host = base._host; + this._port = base._port; + this._path = base._path.slice(); + this._query = base._query; + this._username = base._username; + this._password = base._password; + break loop; + } else if (c === '/' || c === '\\') { + if (c === '\\') { + err('\\ is an invalid code point.'); + } + state = 'relative slash'; + } else if (c === '?') { + this._host = base._host; + this._port = base._port; + this._path = base._path.slice(); + this._query = '?'; + this._username = base._username; + this._password = base._password; + state = 'query'; + } else if (c === '#') { + this._host = base._host; + this._port = base._port; + this._path = base._path.slice(); + this._query = base._query; + this._fragment = '#'; + this._username = base._username; + this._password = base._password; + state = 'fragment'; + } else { + var nextC = input[cursor + 1]; + var nextNextC = input[cursor + 2]; + if ('file' !== this._scheme || !ALPHA.test(c) || nextC !== ':' && nextC !== '|' || EOF !== nextNextC && '/' !== nextNextC && '\\' !== nextNextC && '?' !== nextNextC && '#' !== nextNextC) { + this._host = base._host; + this._port = base._port; + this._username = base._username; + this._password = base._password; + this._path = base._path.slice(); + this._path.pop(); + } + state = 'relative path'; + continue; + } + break; + case 'relative slash': + if (c === '/' || c === '\\') { + if (c === '\\') { + err('\\ is an invalid code point.'); + } + if (this._scheme === 'file') { + state = 'file host'; + } else { + state = 'authority ignore slashes'; + } + } else { + if ('file' !== this._scheme) { + this._host = base._host; + this._port = base._port; + this._username = base._username; + this._password = base._password; + } + state = 'relative path'; + continue; + } + break; + case 'authority first slash': + if (c === '/') { + state = 'authority second slash'; + } else { + err('Expected \'/\', got: ' + c); + state = 'authority ignore slashes'; + continue; + } + break; + case 'authority second slash': + state = 'authority ignore slashes'; + if ('/' !== c) { + err('Expected \'/\', got: ' + c); + continue; + } + break; + case 'authority ignore slashes': + if ('/' !== c && '\\' !== c) { + state = 'authority'; + continue; + } else { + err('Expected authority, got: ' + c); + } + break; + case 'authority': + if (c === '@') { + if (seenAt) { + err('@ already seen.'); + buffer += '%40'; + } + seenAt = true; + for (var i = 0; i < buffer.length; i++) { + var cp = buffer[i]; + if (cp === '\t' || cp === '\n' || cp === '\r') { + err('Invalid whitespace in authority.'); + continue; + } + if (cp === ':' && this._password === null) { + this._password = ''; + continue; + } + var tempC = percentEscape(cp); + if (null !== this._password) { + this._password += tempC; + } else { + this._username += tempC; + } + } + buffer = ''; + } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') { + cursor -= buffer.length; + buffer = ''; + state = 'host'; + continue; + } else { + buffer += c; + } + break; + case 'file host': + if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') { + if (buffer.length === 2 && ALPHA.test(buffer[0]) && (buffer[1] === ':' || buffer[1] === '|')) { + state = 'relative path'; + } else if (buffer.length === 0) { + state = 'relative path start'; + } else { + this._host = IDNAToASCII.call(this, buffer); + buffer = ''; + state = 'relative path start'; + } + continue; + } else if (c === '\t' || c === '\n' || c === '\r') { + err('Invalid whitespace in file host.'); + } else { + buffer += c; + } + break; + case 'host': + case 'hostname': + if (c === ':' && !seenBracket) { + this._host = IDNAToASCII.call(this, buffer); + buffer = ''; + state = 'port'; + if (stateOverride === 'hostname') { + break loop; + } + } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') { + this._host = IDNAToASCII.call(this, buffer); + buffer = ''; + state = 'relative path start'; + if (stateOverride) { + break loop; + } + continue; + } else if ('\t' !== c && '\n' !== c && '\r' !== c) { + if (c === '[') { + seenBracket = true; + } else if (c === ']') { + seenBracket = false; + } + buffer += c; + } else { + err('Invalid code point in host/hostname: ' + c); + } + break; + case 'port': + if (/[0-9]/.test(c)) { + buffer += c; + } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#' || stateOverride) { + if ('' !== buffer) { + var temp = parseInt(buffer, 10); + if (temp !== relative[this._scheme]) { + this._port = temp + ''; + } + buffer = ''; + } + if (stateOverride) { + break loop; + } + state = 'relative path start'; + continue; + } else if (c === '\t' || c === '\n' || c === '\r') { + err('Invalid code point in port: ' + c); + } else { + invalid.call(this); + } + break; + case 'relative path start': + if (c === '\\') { + err('\'\\\' not allowed in path.'); + } + state = 'relative path'; + if ('/' !== c && '\\' !== c) { + continue; + } + break; + case 'relative path': + if (c === EOF || c === '/' || c === '\\' || !stateOverride && (c === '?' || c === '#')) { + if (c === '\\') { + err('\\ not allowed in relative path.'); + } + var tmp; + if (tmp = relativePathDotMapping[buffer.toLowerCase()]) { + buffer = tmp; + } + if (buffer === '..') { + this._path.pop(); + if ('/' !== c && '\\' !== c) { + this._path.push(''); + } + } else if (buffer === '.' && '/' !== c && '\\' !== c) { + this._path.push(''); + } else if ('.' !== buffer) { + if (this._scheme === 'file' && this._path.length === 0 && buffer.length === 2 && ALPHA.test(buffer[0]) && buffer[1] === '|') { + buffer = buffer[0] + ':'; + } + this._path.push(buffer); + } + buffer = ''; + if (c === '?') { + this._query = '?'; + state = 'query'; + } else if (c === '#') { + this._fragment = '#'; + state = 'fragment'; + } + } else if ('\t' !== c && '\n' !== c && '\r' !== c) { + buffer += percentEscape(c); + } + break; + case 'query': + if (!stateOverride && c === '#') { + this._fragment = '#'; + state = 'fragment'; + } else if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) { + this._query += percentEscapeQuery(c); + } + break; + case 'fragment': + if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) { + this._fragment += c; + } + break; + } + cursor++; + } + } + function clear() { + this._scheme = ''; + this._schemeData = ''; + this._username = ''; + this._password = null; + this._host = ''; + this._port = ''; + this._path = []; + this._query = ''; + this._fragment = ''; + this._isInvalid = false; + this._isRelative = false; + } + function JURL(url, base) { + if (base !== undefined && !(base instanceof JURL)) { + base = new JURL(String(base)); + } + this._url = url; + clear.call(this); + var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, ''); + parse.call(this, input, null, base); + } + JURL.prototype = { + toString: function () { + return this.href; + }, + get href() { + if (this._isInvalid) { + return this._url; + } + var authority = ''; + if ('' !== this._username || null !== this._password) { + authority = this._username + (null !== this._password ? ':' + this._password : '') + '@'; + } + return this.protocol + (this._isRelative ? '//' + authority + this.host : '') + this.pathname + this._query + this._fragment; + }, + set href(href) { + clear.call(this); + parse.call(this, href); + }, + get protocol() { + return this._scheme + ':'; + }, + set protocol(protocol) { + if (this._isInvalid) { + return; + } + parse.call(this, protocol + ':', 'scheme start'); + }, + get host() { + return this._isInvalid ? '' : this._port ? this._host + ':' + this._port : this._host; + }, + set host(host) { + if (this._isInvalid || !this._isRelative) { + return; + } + parse.call(this, host, 'host'); + }, + get hostname() { + return this._host; + }, + set hostname(hostname) { + if (this._isInvalid || !this._isRelative) { + return; + } + parse.call(this, hostname, 'hostname'); + }, + get port() { + return this._port; + }, + set port(port) { + if (this._isInvalid || !this._isRelative) { + return; + } + parse.call(this, port, 'port'); + }, + get pathname() { + return this._isInvalid ? '' : this._isRelative ? '/' + this._path.join('/') : this._schemeData; + }, + set pathname(pathname) { + if (this._isInvalid || !this._isRelative) { + return; + } + this._path = []; + parse.call(this, pathname, 'relative path start'); + }, + get search() { + return this._isInvalid || !this._query || this._query === '?' ? '' : this._query; + }, + set search(search) { + if (this._isInvalid || !this._isRelative) { + return; + } + this._query = '?'; + if (search[0] === '?') { + search = search.slice(1); + } + parse.call(this, search, 'query'); + }, + get hash() { + return this._isInvalid || !this._fragment || this._fragment === '#' ? '' : this._fragment; + }, + set hash(hash) { + if (this._isInvalid) { + return; + } + this._fragment = '#'; + if (hash[0] === '#') { + hash = hash.slice(1); + } + parse.call(this, hash, 'fragment'); + }, + get origin() { + var host; + if (this._isInvalid || !this._scheme) { + return ''; + } + switch (this._scheme) { + case 'data': + case 'file': + case 'javascript': + case 'mailto': + return 'null'; + } + host = this.host; + if (!host) { + return ''; + } + return this._scheme + '://' + host; + } + }; + var OriginalURL = globalScope.URL; + if (OriginalURL) { + JURL.createObjectURL = function (blob) { + return OriginalURL.createObjectURL.apply(OriginalURL, arguments); + }; + JURL.revokeObjectURL = function (url) { + OriginalURL.revokeObjectURL(url); + }; + } + globalScope.URL = JURL; + }()); +} +/* WEBPACK VAR INJECTION */}.call(exports, __w_pdfjs_require__(9))) + +/***/ }), +/* 37 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + +var pdfjsVersion = '1.7.354'; +var pdfjsBuild = '0f7548ba'; +var pdfjsCoreWorker = __w_pdfjs_require__(8); +{ + __w_pdfjs_require__(19); +} +exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler; + +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..302b154 --- /dev/null +++ b/package.json @@ -0,0 +1,74 @@ +{ + "name": "PlantillasFormlyBackend", + "version": "1.0.0", + "description": "Creador de plantillas formly", + "main": "index.js", + "scripts": { + "start": "node index.js", + "lint": "eslint *.js lib/*.js src/models/*/*.js src/routes/*/*.js test/*.js src/bl/*/*.js", + "apidoc": "apidoc -i src/routes/ -o public/apidoc", + "setup": "FORCE=true node index.js && sequelize db:seed:all --config src/config/config.json --seeders-path src/seeders", + "startdev": "nodemon --exec 'node index.js'", + "parchar": "node parches/parchar.js", + "migrar": "sequelize db:migrate --config src/config/config.json --migrations-path src/migrations" + }, + "keywords": [ + "node", + "base", + "bienes" + ], + "apidoc": { + "name": "API REST - Documentacion", + "template": { + "forceLanguage": "es" + } + }, + "author": "AGETIC", + "license": "MIT", + "dependencies": { + "activedirectory": "^0.7.2", + "ad": "^0.3.2", + "axios": "^0.19.0", + "body-parser": "^1.15.0", + "child_process": "^1.0.2", + "coffee-script": "^1.10.0", + "colors": "^1.4.0", + "consign": "^0.1.2", + "cors": "^2.7.1", + "ejs": "^2.5.7", + "express": "^4.13.4", + "express-fileupload": "^1.1.6", + "helmet": "^3.4.0", + "html-pdf": "2.2.0", + "jwt-simple": "^0.5.0", + "lodash": "^4.17.5", + "lzma": "^2.3.2", + "md5-file": "^4.0.0", + "moment": "^2.17.1", + "morgan": "^1.7.0", + "node-jose": "^0.11.0", + "node-pdftk": "^1.3.0", + "node-rest-client": "3.1.0", + "nodemailer": "^2.6.4", + "nodemailer-smtp-transport": "^2.7.2", + "object-hash": "^1.1.4", + "openid-client": "^3.15.0", + "passport": "^0.3.2", + "passport-jwt": "^4.0.0", + "passport-ldapauth": "^0.5.0", + "pg": "^7.17.0", + "q": "^1.4.1", + "sequelize": "^5.21.3", + "sequelize-cli": "^5.5.1", + "sequelize-formly": "^1.0.19", + "sequelize-handlers": "^1.0.7", + "uuid": "^2.0.3", + "winston": "^2.2.0" + }, + "devDependencies": { + "chai": "^3.5.0", + "eslint": "^2.7.0", + "mocha": "^6.2.2", + "supertest": "^4.0.2" + } +} diff --git a/parches/config.parchar.json b/parches/config.parchar.json new file mode 100644 index 0000000..84f1647 --- /dev/null +++ b/parches/config.parchar.json @@ -0,0 +1,10 @@ +{ + "descripcion":"Archivo de configuracion para parchar librerias, modulos.", + "parches":[ + { + "ruta_origen":"handlers", + "ruta_destino":"node_modules/sequelize-handlers/src" + } + ] + +} diff --git a/parches/handlers/handler.js b/parches/handlers/handler.js new file mode 100644 index 0000000..a76e45d --- /dev/null +++ b/parches/handlers/handler.js @@ -0,0 +1,387 @@ +const _ = require('lodash'); +const { + HttpStatusError +} = require('./errors'); +const { + parse +} = require('./parser'); +const { + raw +} = require('./transforms'); +const Op = require('sequelize').Op; + +class ModelHandler { + constructor(model, defaults = { + limit: 50, + offset: 0 + }) { + this.model = model; + this.defaults = defaults; + this.custom = null; + this.name = this.model.getTableName(); + } + + create() { + const handle = (req, res, next) => { + this.model + .create(req.body) + .then(respond) + .catch(next); + + function respond(row) { + res.status(201); + res.send(res.transform(row)); + } + }; + + return [ + raw, + handle + ]; + } + + get() { + const handle = (req, res, next) => { + this + .findOne(req.params, req.options) + .then(respond) + .catch(next); + + function respond(row) { + if (!row) { + throw new HttpStatusError(404, 'Not Found'); + } + + res.send(res.transform(row)); + } + }; + + return [ + raw, + handle + ]; + } + + query() { + + const customQuery = (req) => { + return new Promise((resolve, reject) => { + // TODO: Corregir y adecuar al nuevo funcionamiento + // if (req.query.searchPro == 1 && req.query.fIni && req.query.fFin) { + // options.where.fecha = { + // $between: [new Date(req.query.fIni) || fAct, new Date(req.query.fFin) || fAct] + // }; + // } + + if (!req.query.filter || req.query.filter === '') return resolve(); + const condiciones = []; + const options = {}; + options.attributes = _.keys(this.model.rawAttributes); + + return this.model.describe().then(fields => { + for (const key in fields) { + const field = fields[key]; + const obj = {}; + + let aux; + let tipo = field.type; + let buscar = (options.attributes == null) ? true : options.attributes.indexOf(key) != -1; + console.log('Revisndo l interpretacion del searchPRO', req.query.searchPro == 1); + if (req.query.searchPro == 1 && buscar && req.query.tipoBus == 'campo') buscar = req.query.campoSel == key; + + if (req.query.searchPro == 1 && req.query.tipoBus == 'documento') { + console.log('SearchPro_Ddocumento'.bgWhite.red); + buscar = false; + if (key == 'plantilla_valor') { + obj[key] = { + "$ilike": `%${req.query.filter}%` + }; + // xfilter.push(obj); + } + } + if (req.query.searchPro == 1 && req.query.tipoBus == 'flujo') { + console.log('SearchPro_Ddocumento'.bgWhite.red); + + buscar = false; + if (key == 'grupo') { + obj[key] = req.query.filter; + // obj[i] = { $ilike:"%"+req.query.filter+"%" }; + // xfilter.push(obj); + } + } + + if (tipo.indexOf('CHARACTER VARYING') > -1) tipo = 'CHARACTER VARYING'; + switch (tipo) { + case 'INTEGER': + aux = parseInt(req.query.filter); + if (!isNaN(aux) && req.query.filter.indexOf("/") == -1) { + obj[key] = aux; + } + break; + case 'USER-DEFINED': + + aux = req.query.filter; + for (var j in field.special) { + if (field.special[j].toLowerCase().indexOf(aux.toLowerCase()) == 0) { + obj[key] = field.special[j]; + } + } + break; + case 'TIMESTAMP WITH TIME ZONE': + // Busqueda de fechas del tipo: 2016-10-20, 2016/10/20, 20-10-2016, 20/10/2016. + // TODO: No se puede buscar por el mes. + console.log('TIMESTAMP WITH TIME ZONE __________________________'.magenta.bgWhite); + console.log('Primer procesado de fecha __________________'.magenta.bgWhite, procesarFecha(req.query.filter)); + var consulta = procesarFecha(req.query.filter); + if (consulta != false) { + console.log('Fecha'.cyan, procesarFecha(req.query.filter)); + obj[key] = procesarFecha(req.query.filter); + // condiciones.push(obj); + } + break; + case 'CHARACTER VARYING': + obj[key] = { + "$iLike": `%${req.query.filter}%` + }; + break; + case 'TEXT': + obj[key] = { + "$iLike": `%${req.query.filter}%` + }; + break; + case 'ARRAY': + // obj[key] = {"$iLike":`%${req.query.filter}%`}; + break; + case 'BOOLEAN': + // obj[key] = {"$iLike":`%${req.query.filter}%`}; + break; + default: + console.log('DEFAULT__________________________'.magenta.bgWhite, tipo); + obj[key] = req.query.filter; + break; + } + + if (obj.hasOwnProperty(key)) { + condiciones.push(obj); + } + + + + } + }) + .then(() => { + console.log('Finalizando filtrado custom'.bgCyan.black); + this.custom = condiciones; + console.log('Checking custom condition'.bgCyan.black, this.custom); + return resolve(); + }); + }); + } + const handle = (req, res, next) => { + customQuery(req) + .then(() => { + let flag = false; + if (this.custom !== null) { + flag = true; + req.query.filter = this.custom; + this.custom = null; + } + + + this + .findAndCountAll(req.query, req.options, flag) + .then(respond) + .catch(next); + }); + + function respond({ + rows, + start, + end, + count + }) { + res.set('Content-Range', `${start}-${end}/${count}`); + + if (count > end) { + res.status(206); + } else { + res.status(200); + } + + const response = { + total: count, + resultado: rows + } + res.send(res.transform(response)); + } + }; + + return [ + raw, + handle + ]; + } + + remove() { + const handle = (req, res, next) => { + this + .findOne(req.params) + .then(destroy) + .then(respond) + .catch(next); + + function destroy(row) { + if (!row) { + throw new HttpStatusError(404, 'Not Found'); + } + + return row.destroy(); + } + + function respond() { + res.sendStatus(204); + } + }; + + return [ + handle + ]; + } + + update() { + const handle = (req, res, next) => { + console.log('[update] iniciando la modificacion ', req.params, req.body); + this + .findOne(req.params) + .then(updateAttributes) + .then(respond) + .catch(next); + + function updateAttributes(row) { + console.log('[update] row', row); + if (!row) { + throw new HttpStatusError(404, 'Not Found'); + } + + // return row.updateAttributes(req.body); + return row.update(req.body); + } + + function respond(row) { + res.send(res.transform(row)); + } + }; + + return [ + raw, + handle + ]; + } + + findOne(params, options) { + if (params.hasOwnProperty('id')) { + params[`id_${this.name}`] = params.id; + delete params.id; + } + if (options && options.hasOwnProperty('id')) { + delete options.id; + delete options.audit_usuario; + + } + options = _.merge(parse(params, this.model), options); + return this.model.findOne(options); + } + + findAndCountAll(params, options, custom) { + let parsed = parse(params, this.model, custom); + + options = _(parsed) + .defaults(this.defaults) + .merge(options) + .value(); + if (custom) options.where["$or"] = params.filter; + if (params.page) { + options.offset = (params.page === 0 ? 0 : params.page - 1) * options.limit; + } + + return this.model + .findAndCountAll(options) + .then(extract); + + function extract({ + count, + rows + }) { + const start = options.offset; + const end = Math.min(count, options.offset + options.limit); + + return { + rows, + start, + end, + count + }; + } + } +} + +/** + Funcion que procesa una cadena, verifica si tiene el formato de una fecha. + @param {pCadena} Cadena de texto con formato de fecha. + @return Retorna: + EXITO -> un objeto de consulta con formato sequelize. + FALLO -> false. + */ +function procesarFecha(pCadena) { + + var fecha = new Date(pCadena); + var anio = null, + inicio = null, + fin = null; + + // Identifica el operador usando en la cadena para separar los datos. + var operador = pCadena.indexOf('-') > -1 ? '-' : pCadena.indexOf('/') > -1 ? '/' : null; + + // Si existe un operador valido en la cadena. + if (operador != null) { + + // Si la cadena no es valida como fecha, se la invierte. + if (fecha == 'Invalid Date') { + fecha = new Date(((pCadena.split(operador)).reverse()).join("-")); + } + // Obtine el año. + anio = fecha.getFullYear(); + + // Si existe el año. + if (anio != null) { + var vector = pCadena.split(operador) + + // Si la longitud del vector es igual a 3. + if (vector.length == 3) { + var indice = vector.indexOf(anio.toString()); + + // Si el año existe dentro del vector de la cadena. + if (indice > -1) { + + // Armado de la fecha inicio y fecha fin. + if (indice == 0) { + inicio = vector[0] + "-" + vector[1] + "-" + vector[2]; + fin = vector[0] + "-" + vector[1] + "-" + (parseInt(vector[2]) + 1); + } else if (indice == 2) { + inicio = vector[2] + "-" + vector[1] + "-" + vector[0]; + fin = vector[2] + "-" + vector[1] + "-" + (parseInt(vector[0]) + 1); + } + + // Armado de la respuesta a retornar. + var respuesta = { + $gte: inicio, + $lt: fin + }; + return respuesta; + } else return false; // Fin condicional indice. + } else return false; // Fin condicional longitud vector. + } else return false; // Fin condicional existencia año. + } else return false; // Fin condicional existencia operador. +} + +module.exports = ModelHandler; \ No newline at end of file diff --git a/parches/handlers/transforms.js b/parches/handlers/transforms.js new file mode 100644 index 0000000..2353b65 --- /dev/null +++ b/parches/handlers/transforms.js @@ -0,0 +1,22 @@ +const _ = require('lodash'); + +module.exports = { + raw +}; + +function raw(req, res, next) { + if (!_.isFunction(res.transform)) { + res.transform = transform; + } + + next(); + + function transform(data) { + const resp = { + tipoMensaje: 'EXITO', + mensaje: 'Procesamiento exitoso', + datos: data || {} + } + return resp; + } +} \ No newline at end of file diff --git a/parches/parchar.js b/parches/parchar.js new file mode 100644 index 0000000..2f6ba71 --- /dev/null +++ b/parches/parchar.js @@ -0,0 +1,80 @@ +/** + Archivo que realiza el reemplazo de librerias y/o modulos. + +Es necesario tomar en cuenta lo siguiente: + +- Directorio: ./parches Almacena los recursos necesarios para el parche, en subdirectorios. +- Archivo: ./parches/parchar.js Se encarga de realizar el parche. +- Archivo: ./parches/config.parchar.json Contiene informacion sobre el origen del parche y el destino del mismo. + +PD.: El parche se realiza de carpeta a carpeta, es decir: +Si el parche va para ./node_modules/sequelize-handlers/handlers/create.js +El directorio origen que debe contener a "create.js" es: ./parches/handlers + +En el archivo de configuracion: +parches:[ + { + "ruta_origen":"handlers", + "ruta_destino":"node_modules/sequelize-handlers/handlers" + }, +] + */ + + +const fs = require('fs'); +const path = require('path'); + +const basename=path.basename(module.filename); +const rutaParches=`${__dirname}`; +const configuracion=require(`./config.parchar.json`); + +// Itera y verifica la existencia del directorio. +configuracion.parches.forEach((parche)=>{ + + // Verifica la existencia del directorio destino. + fs.exists(parche.ruta_destino,(resultadoLectura)=>{ + console.log("verificando la existencia de la ruta destino >>>> "+parche.ruta_destino, resultadoLectura); + + // Si éxiste el directorio. + if(resultadoLectura){ + + // Ruta del archivo origen. + var rutaOrigen=rutaParches+"/"+parche.ruta_origen; + + // Realiza la lectura del directorio origen, al cual le aplica un filtro. + fs.readdirSync(rutaOrigen).filter((archivo)=> + // Que sea un directorio && que no sea este mismo archivo && que no sea del tipo "json". + (archivo.indexOf('.')!==0) && (archivo!==basename) && (archivo.substr(archivo.lastIndexOf('.')+1,archivo.length)!='json') + ) + // Itera los archivos obtenidos de la ruta origen. + .forEach((archivo)=>{ + + // Realiza la lectura del archivo de origen. + fs.readFile(rutaOrigen+"/"+archivo,{flag:"r"},(errorLeer,dataLeer)=>{ + + // Si no existe error en la lectura. + if(!errorLeer){ + + // Realiza la escritura del archivo destino, con la data obtenida en la lectura. + fs.writeFile(parche.ruta_destino+"/"+archivo,dataLeer,{flag:'w'},(errorEscritura)=>{ + + // Si no existe error de escritura. + if(!errorEscritura) + console.log("Archivo "+archivo+" -- reemplazado correctamente "); + else + console.log("Archivo "+archivo+" -- Error en el remplazo.", errorEscritura); + }); + } + // Si existe error en la lectura. + else{ + console.log("Error en la lectura del archivo >> "+archivo); + } + }); + }); + } + // Si no existe el directorio destino. + else{ + console.log("La ruta destino no existe. <<< "+parche.ruta_destino+" >>>"); + } + }) +}) diff --git a/prod.json b/prod.json new file mode 100644 index 0000000..f16239d --- /dev/null +++ b/prod.json @@ -0,0 +1,12 @@ +{ + "apps" : [ + { + "name" : "plantillas-backend", + "script" : "./index.js", + "watch" : false, + "env" : { + "NODE_ENV": "production" + } + } + ] +} \ No newline at end of file diff --git a/public/images/logo.svg b/public/images/logo.svg new file mode 100644 index 0000000..941ee1c --- /dev/null +++ b/public/images/logo.svg @@ -0,0 +1,854 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/public/images/membrete.png b/public/images/membrete.png new file mode 100644 index 0000000..c9411b9 Binary files /dev/null and b/public/images/membrete.png differ diff --git a/public/qa/tests-global.js b/public/qa/tests-global.js new file mode 100644 index 0000000..ee1d7f7 --- /dev/null +++ b/public/qa/tests-global.js @@ -0,0 +1,15 @@ +suite('Global Tests', function(){ + test('Toda página debe tener un título válido', function(){ + assert(document.title && document.title.match(/\S/) && + document.title.toUpperCase() !== 'TODO'); + }); + test('Toda página debe tener un enlace a dpa', function(){ + assert($('a[href^="dpas"]').length); + }); + test('Todos los enlaces deben tener destino', function(){ + assert($('a[href="#"]').length === 0); + }); + test('No debe existir código css inline', function(){ + assert($("*[style *= ':']").length); + }); +}); diff --git a/public/vendor/chai.js b/public/vendor/chai.js new file mode 100644 index 0000000..1d30296 --- /dev/null +++ b/public/vendor/chai.js @@ -0,0 +1,6142 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.chai = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + * MIT Licensed + */ + +var used = [] + , exports = module.exports = {}; + +/*! + * Chai version + */ + +exports.version = '3.5.0'; + +/*! + * Assertion Error + */ + +exports.AssertionError = require('assertion-error'); + +/*! + * Utils for plugins (not exported) + */ + +var util = require('./chai/utils'); + +/** + * # .use(function) + * + * Provides a way to extend the internals of Chai + * + * @param {Function} + * @returns {this} for chaining + * @api public + */ + +exports.use = function (fn) { + if (!~used.indexOf(fn)) { + fn(this, util); + used.push(fn); + } + + return this; +}; + +/*! + * Utility Functions + */ + +exports.util = util; + +/*! + * Configuration + */ + +var config = require('./chai/config'); +exports.config = config; + +/*! + * Primary `Assertion` prototype + */ + +var assertion = require('./chai/assertion'); +exports.use(assertion); + +/*! + * Core Assertions + */ + +var core = require('./chai/core/assertions'); +exports.use(core); + +/*! + * Expect interface + */ + +var expect = require('./chai/interface/expect'); +exports.use(expect); + +/*! + * Should interface + */ + +var should = require('./chai/interface/should'); +exports.use(should); + +/*! + * Assert interface + */ + +var assert = require('./chai/interface/assert'); +exports.use(assert); + +},{"./chai/assertion":3,"./chai/config":4,"./chai/core/assertions":5,"./chai/interface/assert":6,"./chai/interface/expect":7,"./chai/interface/should":8,"./chai/utils":22,"assertion-error":30}],3:[function(require,module,exports){ +/*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + +var config = require('./config'); + +module.exports = function (_chai, util) { + /*! + * Module dependencies. + */ + + var AssertionError = _chai.AssertionError + , flag = util.flag; + + /*! + * Module export. + */ + + _chai.Assertion = Assertion; + + /*! + * Assertion Constructor + * + * Creates object for chaining. + * + * @api private + */ + + function Assertion (obj, msg, stack) { + flag(this, 'ssfi', stack || arguments.callee); + flag(this, 'object', obj); + flag(this, 'message', msg); + } + + Object.defineProperty(Assertion, 'includeStack', { + get: function() { + console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); + return config.includeStack; + }, + set: function(value) { + console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); + config.includeStack = value; + } + }); + + Object.defineProperty(Assertion, 'showDiff', { + get: function() { + console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); + return config.showDiff; + }, + set: function(value) { + console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); + config.showDiff = value; + } + }); + + Assertion.addProperty = function (name, fn) { + util.addProperty(this.prototype, name, fn); + }; + + Assertion.addMethod = function (name, fn) { + util.addMethod(this.prototype, name, fn); + }; + + Assertion.addChainableMethod = function (name, fn, chainingBehavior) { + util.addChainableMethod(this.prototype, name, fn, chainingBehavior); + }; + + Assertion.overwriteProperty = function (name, fn) { + util.overwriteProperty(this.prototype, name, fn); + }; + + Assertion.overwriteMethod = function (name, fn) { + util.overwriteMethod(this.prototype, name, fn); + }; + + Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) { + util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior); + }; + + /** + * ### .assert(expression, message, negateMessage, expected, actual, showDiff) + * + * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. + * + * @name assert + * @param {Philosophical} expression to be tested + * @param {String|Function} message or function that returns message to display if expression fails + * @param {String|Function} negatedMessage or function that returns negatedMessage to display if negated expression fails + * @param {Mixed} expected value (remember to check for negation) + * @param {Mixed} actual (optional) will default to `this.obj` + * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails + * @api private + */ + + Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) { + var ok = util.test(this, arguments); + if (true !== showDiff) showDiff = false; + if (true !== config.showDiff) showDiff = false; + + if (!ok) { + var msg = util.getMessage(this, arguments) + , actual = util.getActual(this, arguments); + throw new AssertionError(msg, { + actual: actual + , expected: expected + , showDiff: showDiff + }, (config.includeStack) ? this.assert : flag(this, 'ssfi')); + } + }; + + /*! + * ### ._obj + * + * Quick reference to stored `actual` value for plugin developers. + * + * @api private + */ + + Object.defineProperty(Assertion.prototype, '_obj', + { get: function () { + return flag(this, 'object'); + } + , set: function (val) { + flag(this, 'object', val); + } + }); +}; + +},{"./config":4}],4:[function(require,module,exports){ +module.exports = { + + /** + * ### config.includeStack + * + * User configurable property, influences whether stack trace + * is included in Assertion error message. Default of false + * suppresses stack trace in the error message. + * + * chai.config.includeStack = true; // enable stack on error + * + * @param {Boolean} + * @api public + */ + + includeStack: false, + + /** + * ### config.showDiff + * + * User configurable property, influences whether or not + * the `showDiff` flag should be included in the thrown + * AssertionErrors. `false` will always be `false`; `true` + * will be true when the assertion has requested a diff + * be shown. + * + * @param {Boolean} + * @api public + */ + + showDiff: true, + + /** + * ### config.truncateThreshold + * + * User configurable property, sets length threshold for actual and + * expected values in assertion errors. If this threshold is exceeded, for + * example for large data structures, the value is replaced with something + * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`. + * + * Set it to zero if you want to disable truncating altogether. + * + * This is especially userful when doing assertions on arrays: having this + * set to a reasonable large value makes the failure messages readily + * inspectable. + * + * chai.config.truncateThreshold = 0; // disable truncating + * + * @param {Number} + * @api public + */ + + truncateThreshold: 40 + +}; + +},{}],5:[function(require,module,exports){ +/*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + +module.exports = function (chai, _) { + var Assertion = chai.Assertion + , toString = Object.prototype.toString + , flag = _.flag; + + /** + * ### Language Chains + * + * The following are provided as chainable getters to + * improve the readability of your assertions. They + * do not provide testing capabilities unless they + * have been overwritten by a plugin. + * + * **Chains** + * + * - to + * - be + * - been + * - is + * - that + * - which + * - and + * - has + * - have + * - with + * - at + * - of + * - same + * + * @name language chains + * @namespace BDD + * @api public + */ + + [ 'to', 'be', 'been' + , 'is', 'and', 'has', 'have' + , 'with', 'that', 'which', 'at' + , 'of', 'same' ].forEach(function (chain) { + Assertion.addProperty(chain, function () { + return this; + }); + }); + + /** + * ### .not + * + * Negates any of assertions following in the chain. + * + * expect(foo).to.not.equal('bar'); + * expect(goodFn).to.not.throw(Error); + * expect({ foo: 'baz' }).to.have.property('foo') + * .and.not.equal('bar'); + * + * @name not + * @namespace BDD + * @api public + */ + + Assertion.addProperty('not', function () { + flag(this, 'negate', true); + }); + + /** + * ### .deep + * + * Sets the `deep` flag, later used by the `equal` and + * `property` assertions. + * + * expect(foo).to.deep.equal({ bar: 'baz' }); + * expect({ foo: { bar: { baz: 'quux' } } }) + * .to.have.deep.property('foo.bar.baz', 'quux'); + * + * `.deep.property` special characters can be escaped + * by adding two slashes before the `.` or `[]`. + * + * var deepCss = { '.link': { '[target]': 42 }}; + * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42); + * + * @name deep + * @namespace BDD + * @api public + */ + + Assertion.addProperty('deep', function () { + flag(this, 'deep', true); + }); + + /** + * ### .any + * + * Sets the `any` flag, (opposite of the `all` flag) + * later used in the `keys` assertion. + * + * expect(foo).to.have.any.keys('bar', 'baz'); + * + * @name any + * @namespace BDD + * @api public + */ + + Assertion.addProperty('any', function () { + flag(this, 'any', true); + flag(this, 'all', false) + }); + + + /** + * ### .all + * + * Sets the `all` flag (opposite of the `any` flag) + * later used by the `keys` assertion. + * + * expect(foo).to.have.all.keys('bar', 'baz'); + * + * @name all + * @namespace BDD + * @api public + */ + + Assertion.addProperty('all', function () { + flag(this, 'all', true); + flag(this, 'any', false); + }); + + /** + * ### .a(type) + * + * The `a` and `an` assertions are aliases that can be + * used either as language chains or to assert a value's + * type. + * + * // typeof + * expect('test').to.be.a('string'); + * expect({ foo: 'bar' }).to.be.an('object'); + * expect(null).to.be.a('null'); + * expect(undefined).to.be.an('undefined'); + * expect(new Error).to.be.an('error'); + * expect(new Promise).to.be.a('promise'); + * expect(new Float32Array()).to.be.a('float32array'); + * expect(Symbol()).to.be.a('symbol'); + * + * // es6 overrides + * expect({[Symbol.toStringTag]:()=>'foo'}).to.be.a('foo'); + * + * // language chain + * expect(foo).to.be.an.instanceof(Foo); + * + * @name a + * @alias an + * @param {String} type + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function an (type, msg) { + if (msg) flag(this, 'message', msg); + type = type.toLowerCase(); + var obj = flag(this, 'object') + , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a '; + + this.assert( + type === _.type(obj) + , 'expected #{this} to be ' + article + type + , 'expected #{this} not to be ' + article + type + ); + } + + Assertion.addChainableMethod('an', an); + Assertion.addChainableMethod('a', an); + + /** + * ### .include(value) + * + * The `include` and `contain` assertions can be used as either property + * based language chains or as methods to assert the inclusion of an object + * in an array or a substring in a string. When used as language chains, + * they toggle the `contains` flag for the `keys` assertion. + * + * expect([1,2,3]).to.include(2); + * expect('foobar').to.contain('foo'); + * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); + * + * @name include + * @alias contain + * @alias includes + * @alias contains + * @param {Object|String|Number} obj + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function includeChainingBehavior () { + flag(this, 'contains', true); + } + + function include (val, msg) { + _.expectTypes(this, ['array', 'object', 'string']); + + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + var expected = false; + + if (_.type(obj) === 'array' && _.type(val) === 'object') { + for (var i in obj) { + if (_.eql(obj[i], val)) { + expected = true; + break; + } + } + } else if (_.type(val) === 'object') { + if (!flag(this, 'negate')) { + for (var k in val) new Assertion(obj).property(k, val[k]); + return; + } + var subset = {}; + for (var k in val) subset[k] = obj[k]; + expected = _.eql(subset, val); + } else { + expected = (obj != undefined) && ~obj.indexOf(val); + } + this.assert( + expected + , 'expected #{this} to include ' + _.inspect(val) + , 'expected #{this} to not include ' + _.inspect(val)); + } + + Assertion.addChainableMethod('include', include, includeChainingBehavior); + Assertion.addChainableMethod('contain', include, includeChainingBehavior); + Assertion.addChainableMethod('contains', include, includeChainingBehavior); + Assertion.addChainableMethod('includes', include, includeChainingBehavior); + + /** + * ### .ok + * + * Asserts that the target is truthy. + * + * expect('everything').to.be.ok; + * expect(1).to.be.ok; + * expect(false).to.not.be.ok; + * expect(undefined).to.not.be.ok; + * expect(null).to.not.be.ok; + * + * @name ok + * @namespace BDD + * @api public + */ + + Assertion.addProperty('ok', function () { + this.assert( + flag(this, 'object') + , 'expected #{this} to be truthy' + , 'expected #{this} to be falsy'); + }); + + /** + * ### .true + * + * Asserts that the target is `true`. + * + * expect(true).to.be.true; + * expect(1).to.not.be.true; + * + * @name true + * @namespace BDD + * @api public + */ + + Assertion.addProperty('true', function () { + this.assert( + true === flag(this, 'object') + , 'expected #{this} to be true' + , 'expected #{this} to be false' + , this.negate ? false : true + ); + }); + + /** + * ### .false + * + * Asserts that the target is `false`. + * + * expect(false).to.be.false; + * expect(0).to.not.be.false; + * + * @name false + * @namespace BDD + * @api public + */ + + Assertion.addProperty('false', function () { + this.assert( + false === flag(this, 'object') + , 'expected #{this} to be false' + , 'expected #{this} to be true' + , this.negate ? true : false + ); + }); + + /** + * ### .null + * + * Asserts that the target is `null`. + * + * expect(null).to.be.null; + * expect(undefined).to.not.be.null; + * + * @name null + * @namespace BDD + * @api public + */ + + Assertion.addProperty('null', function () { + this.assert( + null === flag(this, 'object') + , 'expected #{this} to be null' + , 'expected #{this} not to be null' + ); + }); + + /** + * ### .undefined + * + * Asserts that the target is `undefined`. + * + * expect(undefined).to.be.undefined; + * expect(null).to.not.be.undefined; + * + * @name undefined + * @namespace BDD + * @api public + */ + + Assertion.addProperty('undefined', function () { + this.assert( + undefined === flag(this, 'object') + , 'expected #{this} to be undefined' + , 'expected #{this} not to be undefined' + ); + }); + + /** + * ### .NaN + * Asserts that the target is `NaN`. + * + * expect('foo').to.be.NaN; + * expect(4).not.to.be.NaN; + * + * @name NaN + * @namespace BDD + * @api public + */ + + Assertion.addProperty('NaN', function () { + this.assert( + isNaN(flag(this, 'object')) + , 'expected #{this} to be NaN' + , 'expected #{this} not to be NaN' + ); + }); + + /** + * ### .exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var foo = 'hi' + * , bar = null + * , baz; + * + * expect(foo).to.exist; + * expect(bar).to.not.exist; + * expect(baz).to.not.exist; + * + * @name exist + * @namespace BDD + * @api public + */ + + Assertion.addProperty('exist', function () { + this.assert( + null != flag(this, 'object') + , 'expected #{this} to exist' + , 'expected #{this} to not exist' + ); + }); + + + /** + * ### .empty + * + * Asserts that the target's length is `0`. For arrays and strings, it checks + * the `length` property. For objects, it gets the count of + * enumerable keys. + * + * expect([]).to.be.empty; + * expect('').to.be.empty; + * expect({}).to.be.empty; + * + * @name empty + * @namespace BDD + * @api public + */ + + Assertion.addProperty('empty', function () { + var obj = flag(this, 'object') + , expected = obj; + + if (Array.isArray(obj) || 'string' === typeof object) { + expected = obj.length; + } else if (typeof obj === 'object') { + expected = Object.keys(obj).length; + } + + this.assert( + !expected + , 'expected #{this} to be empty' + , 'expected #{this} not to be empty' + ); + }); + + /** + * ### .arguments + * + * Asserts that the target is an arguments object. + * + * function test () { + * expect(arguments).to.be.arguments; + * } + * + * @name arguments + * @alias Arguments + * @namespace BDD + * @api public + */ + + function checkArguments () { + var obj = flag(this, 'object') + , type = Object.prototype.toString.call(obj); + this.assert( + '[object Arguments]' === type + , 'expected #{this} to be arguments but got ' + type + , 'expected #{this} to not be arguments' + ); + } + + Assertion.addProperty('arguments', checkArguments); + Assertion.addProperty('Arguments', checkArguments); + + /** + * ### .equal(value) + * + * Asserts that the target is strictly equal (`===`) to `value`. + * Alternately, if the `deep` flag is set, asserts that + * the target is deeply equal to `value`. + * + * expect('hello').to.equal('hello'); + * expect(42).to.equal(42); + * expect(1).to.not.equal(true); + * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' }); + * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); + * + * @name equal + * @alias equals + * @alias eq + * @alias deep.equal + * @param {Mixed} value + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertEqual (val, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'deep')) { + return this.eql(val); + } else { + this.assert( + val === obj + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{exp}' + , val + , this._obj + , true + ); + } + } + + Assertion.addMethod('equal', assertEqual); + Assertion.addMethod('equals', assertEqual); + Assertion.addMethod('eq', assertEqual); + + /** + * ### .eql(value) + * + * Asserts that the target is deeply equal to `value`. + * + * expect({ foo: 'bar' }).to.eql({ foo: 'bar' }); + * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]); + * + * @name eql + * @alias eqls + * @param {Mixed} value + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertEql(obj, msg) { + if (msg) flag(this, 'message', msg); + this.assert( + _.eql(obj, flag(this, 'object')) + , 'expected #{this} to deeply equal #{exp}' + , 'expected #{this} to not deeply equal #{exp}' + , obj + , this._obj + , true + ); + } + + Assertion.addMethod('eql', assertEql); + Assertion.addMethod('eqls', assertEql); + + /** + * ### .above(value) + * + * Asserts that the target is greater than `value`. + * + * expect(10).to.be.above(5); + * + * Can also be used in conjunction with `length` to + * assert a minimum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.above(2); + * expect([ 1, 2, 3 ]).to.have.length.above(2); + * + * @name above + * @alias gt + * @alias greaterThan + * @param {Number} value + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertAbove (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len > n + , 'expected #{this} to have a length above #{exp} but got #{act}' + , 'expected #{this} to not have a length above #{exp}' + , n + , len + ); + } else { + this.assert( + obj > n + , 'expected #{this} to be above ' + n + , 'expected #{this} to be at most ' + n + ); + } + } + + Assertion.addMethod('above', assertAbove); + Assertion.addMethod('gt', assertAbove); + Assertion.addMethod('greaterThan', assertAbove); + + /** + * ### .least(value) + * + * Asserts that the target is greater than or equal to `value`. + * + * expect(10).to.be.at.least(10); + * + * Can also be used in conjunction with `length` to + * assert a minimum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.of.at.least(2); + * expect([ 1, 2, 3 ]).to.have.length.of.at.least(3); + * + * @name least + * @alias gte + * @param {Number} value + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertLeast (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len >= n + , 'expected #{this} to have a length at least #{exp} but got #{act}' + , 'expected #{this} to have a length below #{exp}' + , n + , len + ); + } else { + this.assert( + obj >= n + , 'expected #{this} to be at least ' + n + , 'expected #{this} to be below ' + n + ); + } + } + + Assertion.addMethod('least', assertLeast); + Assertion.addMethod('gte', assertLeast); + + /** + * ### .below(value) + * + * Asserts that the target is less than `value`. + * + * expect(5).to.be.below(10); + * + * Can also be used in conjunction with `length` to + * assert a maximum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.below(4); + * expect([ 1, 2, 3 ]).to.have.length.below(4); + * + * @name below + * @alias lt + * @alias lessThan + * @param {Number} value + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertBelow (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len < n + , 'expected #{this} to have a length below #{exp} but got #{act}' + , 'expected #{this} to not have a length below #{exp}' + , n + , len + ); + } else { + this.assert( + obj < n + , 'expected #{this} to be below ' + n + , 'expected #{this} to be at least ' + n + ); + } + } + + Assertion.addMethod('below', assertBelow); + Assertion.addMethod('lt', assertBelow); + Assertion.addMethod('lessThan', assertBelow); + + /** + * ### .most(value) + * + * Asserts that the target is less than or equal to `value`. + * + * expect(5).to.be.at.most(5); + * + * Can also be used in conjunction with `length` to + * assert a maximum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.of.at.most(4); + * expect([ 1, 2, 3 ]).to.have.length.of.at.most(3); + * + * @name most + * @alias lte + * @param {Number} value + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertMost (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len <= n + , 'expected #{this} to have a length at most #{exp} but got #{act}' + , 'expected #{this} to have a length above #{exp}' + , n + , len + ); + } else { + this.assert( + obj <= n + , 'expected #{this} to be at most ' + n + , 'expected #{this} to be above ' + n + ); + } + } + + Assertion.addMethod('most', assertMost); + Assertion.addMethod('lte', assertMost); + + /** + * ### .within(start, finish) + * + * Asserts that the target is within a range. + * + * expect(7).to.be.within(5,10); + * + * Can also be used in conjunction with `length` to + * assert a length range. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.within(2,4); + * expect([ 1, 2, 3 ]).to.have.length.within(2,4); + * + * @name within + * @param {Number} start lowerbound inclusive + * @param {Number} finish upperbound inclusive + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + Assertion.addMethod('within', function (start, finish, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , range = start + '..' + finish; + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len >= start && len <= finish + , 'expected #{this} to have a length within ' + range + , 'expected #{this} to not have a length within ' + range + ); + } else { + this.assert( + obj >= start && obj <= finish + , 'expected #{this} to be within ' + range + , 'expected #{this} to not be within ' + range + ); + } + }); + + /** + * ### .instanceof(constructor) + * + * Asserts that the target is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , Chai = new Tea('chai'); + * + * expect(Chai).to.be.an.instanceof(Tea); + * expect([ 1, 2, 3 ]).to.be.instanceof(Array); + * + * @name instanceof + * @param {Constructor} constructor + * @param {String} message _optional_ + * @alias instanceOf + * @namespace BDD + * @api public + */ + + function assertInstanceOf (constructor, msg) { + if (msg) flag(this, 'message', msg); + var name = _.getName(constructor); + this.assert( + flag(this, 'object') instanceof constructor + , 'expected #{this} to be an instance of ' + name + , 'expected #{this} to not be an instance of ' + name + ); + }; + + Assertion.addMethod('instanceof', assertInstanceOf); + Assertion.addMethod('instanceOf', assertInstanceOf); + + /** + * ### .property(name, [value]) + * + * Asserts that the target has a property `name`, optionally asserting that + * the value of that property is strictly equal to `value`. + * If the `deep` flag is set, you can use dot- and bracket-notation for deep + * references into objects and arrays. + * + * // simple referencing + * var obj = { foo: 'bar' }; + * expect(obj).to.have.property('foo'); + * expect(obj).to.have.property('foo', 'bar'); + * + * // deep referencing + * var deepObj = { + * green: { tea: 'matcha' } + * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ] + * }; + * + * expect(deepObj).to.have.deep.property('green.tea', 'matcha'); + * expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); + * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); + * + * You can also use an array as the starting point of a `deep.property` + * assertion, or traverse nested arrays. + * + * var arr = [ + * [ 'chai', 'matcha', 'konacha' ] + * , [ { tea: 'chai' } + * , { tea: 'matcha' } + * , { tea: 'konacha' } ] + * ]; + * + * expect(arr).to.have.deep.property('[0][1]', 'matcha'); + * expect(arr).to.have.deep.property('[1][2].tea', 'konacha'); + * + * Furthermore, `property` changes the subject of the assertion + * to be the value of that property from the original object. This + * permits for further chainable assertions on that property. + * + * expect(obj).to.have.property('foo') + * .that.is.a('string'); + * expect(deepObj).to.have.property('green') + * .that.is.an('object') + * .that.deep.equals({ tea: 'matcha' }); + * expect(deepObj).to.have.property('teas') + * .that.is.an('array') + * .with.deep.property('[2]') + * .that.deep.equals({ tea: 'konacha' }); + * + * Note that dots and bracket in `name` must be backslash-escaped when + * the `deep` flag is set, while they must NOT be escaped when the `deep` + * flag is not set. + * + * // simple referencing + * var css = { '.link[target]': 42 }; + * expect(css).to.have.property('.link[target]', 42); + * + * // deep referencing + * var deepCss = { '.link': { '[target]': 42 }}; + * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42); + * + * @name property + * @alias deep.property + * @param {String} name + * @param {Mixed} value (optional) + * @param {String} message _optional_ + * @returns value of property for chaining + * @namespace BDD + * @api public + */ + + Assertion.addMethod('property', function (name, val, msg) { + if (msg) flag(this, 'message', msg); + + var isDeep = !!flag(this, 'deep') + , descriptor = isDeep ? 'deep property ' : 'property ' + , negate = flag(this, 'negate') + , obj = flag(this, 'object') + , pathInfo = isDeep ? _.getPathInfo(name, obj) : null + , hasProperty = isDeep + ? pathInfo.exists + : _.hasProperty(name, obj) + , value = isDeep + ? pathInfo.value + : obj[name]; + + if (negate && arguments.length > 1) { + if (undefined === value) { + msg = (msg != null) ? msg + ': ' : ''; + throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name)); + } + } else { + this.assert( + hasProperty + , 'expected #{this} to have a ' + descriptor + _.inspect(name) + , 'expected #{this} to not have ' + descriptor + _.inspect(name)); + } + + if (arguments.length > 1) { + this.assert( + val === value + , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}' + , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}' + , val + , value + ); + } + + flag(this, 'object', value); + }); + + + /** + * ### .ownProperty(name) + * + * Asserts that the target has an own property `name`. + * + * expect('test').to.have.ownProperty('length'); + * + * @name ownProperty + * @alias haveOwnProperty + * @param {String} name + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertOwnProperty (name, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + this.assert( + obj.hasOwnProperty(name) + , 'expected #{this} to have own property ' + _.inspect(name) + , 'expected #{this} to not have own property ' + _.inspect(name) + ); + } + + Assertion.addMethod('ownProperty', assertOwnProperty); + Assertion.addMethod('haveOwnProperty', assertOwnProperty); + + /** + * ### .ownPropertyDescriptor(name[, descriptor[, message]]) + * + * Asserts that the target has an own property descriptor `name`, that optionally matches `descriptor`. + * + * expect('test').to.have.ownPropertyDescriptor('length'); + * expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 }); + * expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 }); + * expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false); + * expect('test').ownPropertyDescriptor('length').to.have.keys('value'); + * + * @name ownPropertyDescriptor + * @alias haveOwnPropertyDescriptor + * @param {String} name + * @param {Object} descriptor _optional_ + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertOwnPropertyDescriptor (name, descriptor, msg) { + if (typeof descriptor === 'string') { + msg = descriptor; + descriptor = null; + } + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name); + if (actualDescriptor && descriptor) { + this.assert( + _.eql(descriptor, actualDescriptor) + , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor) + , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor) + , descriptor + , actualDescriptor + , true + ); + } else { + this.assert( + actualDescriptor + , 'expected #{this} to have an own property descriptor for ' + _.inspect(name) + , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name) + ); + } + flag(this, 'object', actualDescriptor); + } + + Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor); + Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor); + + /** + * ### .length + * + * Sets the `doLength` flag later used as a chain precursor to a value + * comparison for the `length` property. + * + * expect('foo').to.have.length.above(2); + * expect([ 1, 2, 3 ]).to.have.length.above(2); + * expect('foo').to.have.length.below(4); + * expect([ 1, 2, 3 ]).to.have.length.below(4); + * expect('foo').to.have.length.within(2,4); + * expect([ 1, 2, 3 ]).to.have.length.within(2,4); + * + * *Deprecation notice:* Using `length` as an assertion will be deprecated + * in version 2.4.0 and removed in 3.0.0. Code using the old style of + * asserting for `length` property value using `length(value)` should be + * switched to use `lengthOf(value)` instead. + * + * @name length + * @namespace BDD + * @api public + */ + + /** + * ### .lengthOf(value[, message]) + * + * Asserts that the target's `length` property has + * the expected value. + * + * expect([ 1, 2, 3]).to.have.lengthOf(3); + * expect('foobar').to.have.lengthOf(6); + * + * @name lengthOf + * @param {Number} length + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertLengthChain () { + flag(this, 'doLength', true); + } + + function assertLength (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + + this.assert( + len == n + , 'expected #{this} to have a length of #{exp} but got #{act}' + , 'expected #{this} to not have a length of #{act}' + , n + , len + ); + } + + Assertion.addChainableMethod('length', assertLength, assertLengthChain); + Assertion.addMethod('lengthOf', assertLength); + + /** + * ### .match(regexp) + * + * Asserts that the target matches a regular expression. + * + * expect('foobar').to.match(/^foo/); + * + * @name match + * @alias matches + * @param {RegExp} RegularExpression + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + function assertMatch(re, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + this.assert( + re.exec(obj) + , 'expected #{this} to match ' + re + , 'expected #{this} not to match ' + re + ); + } + + Assertion.addMethod('match', assertMatch); + Assertion.addMethod('matches', assertMatch); + + /** + * ### .string(string) + * + * Asserts that the string target contains another string. + * + * expect('foobar').to.have.string('bar'); + * + * @name string + * @param {String} string + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + Assertion.addMethod('string', function (str, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + new Assertion(obj, msg).is.a('string'); + + this.assert( + ~obj.indexOf(str) + , 'expected #{this} to contain ' + _.inspect(str) + , 'expected #{this} to not contain ' + _.inspect(str) + ); + }); + + + /** + * ### .keys(key1, [key2], [...]) + * + * Asserts that the target contains any or all of the passed-in keys. + * Use in combination with `any`, `all`, `contains`, or `have` will affect + * what will pass. + * + * When used in conjunction with `any`, at least one key that is passed + * in must exist in the target object. This is regardless whether or not + * the `have` or `contain` qualifiers are used. Note, either `any` or `all` + * should be used in the assertion. If neither are used, the assertion is + * defaulted to `all`. + * + * When both `all` and `contain` are used, the target object must have at + * least all of the passed-in keys but may have more keys not listed. + * + * When both `all` and `have` are used, the target object must both contain + * all of the passed-in keys AND the number of keys in the target object must + * match the number of keys passed in (in other words, a target object must + * have all and only all of the passed-in keys). + * + * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz'); + * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo'); + * expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz'); + * expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']); + * expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6}); + * expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']); + * expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7}); + * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']); + * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys({'bar': 6}); + * + * + * @name keys + * @alias key + * @param {...String|Array|Object} keys + * @namespace BDD + * @api public + */ + + function assertKeys (keys) { + var obj = flag(this, 'object') + , str + , ok = true + , mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments'; + + switch (_.type(keys)) { + case "array": + if (arguments.length > 1) throw (new Error(mixedArgsMsg)); + break; + case "object": + if (arguments.length > 1) throw (new Error(mixedArgsMsg)); + keys = Object.keys(keys); + break; + default: + keys = Array.prototype.slice.call(arguments); + } + + if (!keys.length) throw new Error('keys required'); + + var actual = Object.keys(obj) + , expected = keys + , len = keys.length + , any = flag(this, 'any') + , all = flag(this, 'all'); + + if (!any && !all) { + all = true; + } + + // Has any + if (any) { + var intersection = expected.filter(function(key) { + return ~actual.indexOf(key); + }); + ok = intersection.length > 0; + } + + // Has all + if (all) { + ok = keys.every(function(key){ + return ~actual.indexOf(key); + }); + if (!flag(this, 'negate') && !flag(this, 'contains')) { + ok = ok && keys.length == actual.length; + } + } + + // Key string + if (len > 1) { + keys = keys.map(function(key){ + return _.inspect(key); + }); + var last = keys.pop(); + if (all) { + str = keys.join(', ') + ', and ' + last; + } + if (any) { + str = keys.join(', ') + ', or ' + last; + } + } else { + str = _.inspect(keys[0]); + } + + // Form + str = (len > 1 ? 'keys ' : 'key ') + str; + + // Have / include + str = (flag(this, 'contains') ? 'contain ' : 'have ') + str; + + // Assertion + this.assert( + ok + , 'expected #{this} to ' + str + , 'expected #{this} to not ' + str + , expected.slice(0).sort() + , actual.sort() + , true + ); + } + + Assertion.addMethod('keys', assertKeys); + Assertion.addMethod('key', assertKeys); + + /** + * ### .throw(constructor) + * + * Asserts that the function target will throw a specific error, or specific type of error + * (as determined using `instanceof`), optionally with a RegExp or string inclusion test + * for the error's message. + * + * var err = new ReferenceError('This is a bad function.'); + * var fn = function () { throw err; } + * expect(fn).to.throw(ReferenceError); + * expect(fn).to.throw(Error); + * expect(fn).to.throw(/bad function/); + * expect(fn).to.not.throw('good function'); + * expect(fn).to.throw(ReferenceError, /bad function/); + * expect(fn).to.throw(err); + * + * Please note that when a throw expectation is negated, it will check each + * parameter independently, starting with error constructor type. The appropriate way + * to check for the existence of a type of error but for a message that does not match + * is to use `and`. + * + * expect(fn).to.throw(ReferenceError) + * .and.not.throw(/good function/); + * + * @name throw + * @alias throws + * @alias Throw + * @param {ErrorConstructor} constructor + * @param {String|RegExp} expected error message + * @param {String} message _optional_ + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @returns error for chaining (null if no error) + * @namespace BDD + * @api public + */ + + function assertThrows (constructor, errMsg, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + new Assertion(obj, msg).is.a('function'); + + var thrown = false + , desiredError = null + , name = null + , thrownError = null; + + if (arguments.length === 0) { + errMsg = null; + constructor = null; + } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) { + errMsg = constructor; + constructor = null; + } else if (constructor && constructor instanceof Error) { + desiredError = constructor; + constructor = null; + errMsg = null; + } else if (typeof constructor === 'function') { + name = constructor.prototype.name; + if (!name || (name === 'Error' && constructor !== Error)) { + name = constructor.name || (new constructor()).name; + } + } else { + constructor = null; + } + + try { + obj(); + } catch (err) { + // first, check desired error + if (desiredError) { + this.assert( + err === desiredError + , 'expected #{this} to throw #{exp} but #{act} was thrown' + , 'expected #{this} to not throw #{exp}' + , (desiredError instanceof Error ? desiredError.toString() : desiredError) + , (err instanceof Error ? err.toString() : err) + ); + + flag(this, 'object', err); + return this; + } + + // next, check constructor + if (constructor) { + this.assert( + err instanceof constructor + , 'expected #{this} to throw #{exp} but #{act} was thrown' + , 'expected #{this} to not throw #{exp} but #{act} was thrown' + , name + , (err instanceof Error ? err.toString() : err) + ); + + if (!errMsg) { + flag(this, 'object', err); + return this; + } + } + + // next, check message + var message = 'error' === _.type(err) && "message" in err + ? err.message + : '' + err; + + if ((message != null) && errMsg && errMsg instanceof RegExp) { + this.assert( + errMsg.exec(message) + , 'expected #{this} to throw error matching #{exp} but got #{act}' + , 'expected #{this} to throw error not matching #{exp}' + , errMsg + , message + ); + + flag(this, 'object', err); + return this; + } else if ((message != null) && errMsg && 'string' === typeof errMsg) { + this.assert( + ~message.indexOf(errMsg) + , 'expected #{this} to throw error including #{exp} but got #{act}' + , 'expected #{this} to throw error not including #{act}' + , errMsg + , message + ); + + flag(this, 'object', err); + return this; + } else { + thrown = true; + thrownError = err; + } + } + + var actuallyGot = '' + , expectedThrown = name !== null + ? name + : desiredError + ? '#{exp}' //_.inspect(desiredError) + : 'an error'; + + if (thrown) { + actuallyGot = ' but #{act} was thrown' + } + + this.assert( + thrown === true + , 'expected #{this} to throw ' + expectedThrown + actuallyGot + , 'expected #{this} to not throw ' + expectedThrown + actuallyGot + , (desiredError instanceof Error ? desiredError.toString() : desiredError) + , (thrownError instanceof Error ? thrownError.toString() : thrownError) + ); + + flag(this, 'object', thrownError); + }; + + Assertion.addMethod('throw', assertThrows); + Assertion.addMethod('throws', assertThrows); + Assertion.addMethod('Throw', assertThrows); + + /** + * ### .respondTo(method) + * + * Asserts that the object or class target will respond to a method. + * + * Klass.prototype.bar = function(){}; + * expect(Klass).to.respondTo('bar'); + * expect(obj).to.respondTo('bar'); + * + * To check if a constructor will respond to a static function, + * set the `itself` flag. + * + * Klass.baz = function(){}; + * expect(Klass).itself.to.respondTo('baz'); + * + * @name respondTo + * @alias respondsTo + * @param {String} method + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function respondTo (method, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , itself = flag(this, 'itself') + , context = ('function' === _.type(obj) && !itself) + ? obj.prototype[method] + : obj[method]; + + this.assert( + 'function' === typeof context + , 'expected #{this} to respond to ' + _.inspect(method) + , 'expected #{this} to not respond to ' + _.inspect(method) + ); + } + + Assertion.addMethod('respondTo', respondTo); + Assertion.addMethod('respondsTo', respondTo); + + /** + * ### .itself + * + * Sets the `itself` flag, later used by the `respondTo` assertion. + * + * function Foo() {} + * Foo.bar = function() {} + * Foo.prototype.baz = function() {} + * + * expect(Foo).itself.to.respondTo('bar'); + * expect(Foo).itself.not.to.respondTo('baz'); + * + * @name itself + * @namespace BDD + * @api public + */ + + Assertion.addProperty('itself', function () { + flag(this, 'itself', true); + }); + + /** + * ### .satisfy(method) + * + * Asserts that the target passes a given truth test. + * + * expect(1).to.satisfy(function(num) { return num > 0; }); + * + * @name satisfy + * @alias satisfies + * @param {Function} matcher + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function satisfy (matcher, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + var result = matcher(obj); + this.assert( + result + , 'expected #{this} to satisfy ' + _.objDisplay(matcher) + , 'expected #{this} to not satisfy' + _.objDisplay(matcher) + , this.negate ? false : true + , result + ); + } + + Assertion.addMethod('satisfy', satisfy); + Assertion.addMethod('satisfies', satisfy); + + /** + * ### .closeTo(expected, delta) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * expect(1.5).to.be.closeTo(1, 0.5); + * + * @name closeTo + * @alias approximately + * @param {Number} expected + * @param {Number} delta + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function closeTo(expected, delta, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + + new Assertion(obj, msg).is.a('number'); + if (_.type(expected) !== 'number' || _.type(delta) !== 'number') { + throw new Error('the arguments to closeTo or approximately must be numbers'); + } + + this.assert( + Math.abs(obj - expected) <= delta + , 'expected #{this} to be close to ' + expected + ' +/- ' + delta + , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta + ); + } + + Assertion.addMethod('closeTo', closeTo); + Assertion.addMethod('approximately', closeTo); + + function isSubsetOf(subset, superset, cmp) { + return subset.every(function(elem) { + if (!cmp) return superset.indexOf(elem) !== -1; + + return superset.some(function(elem2) { + return cmp(elem, elem2); + }); + }) + } + + /** + * ### .members(set) + * + * Asserts that the target is a superset of `set`, + * or that the target and `set` have the same strictly-equal (===) members. + * Alternately, if the `deep` flag is set, set members are compared for deep + * equality. + * + * expect([1, 2, 3]).to.include.members([3, 2]); + * expect([1, 2, 3]).to.not.include.members([3, 2, 8]); + * + * expect([4, 2]).to.have.members([2, 4]); + * expect([5, 2]).to.not.have.members([5, 2, 1]); + * + * expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]); + * + * @name members + * @param {Array} set + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + Assertion.addMethod('members', function (subset, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + + new Assertion(obj).to.be.an('array'); + new Assertion(subset).to.be.an('array'); + + var cmp = flag(this, 'deep') ? _.eql : undefined; + + if (flag(this, 'contains')) { + return this.assert( + isSubsetOf(subset, obj, cmp) + , 'expected #{this} to be a superset of #{act}' + , 'expected #{this} to not be a superset of #{act}' + , obj + , subset + ); + } + + this.assert( + isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp) + , 'expected #{this} to have the same members as #{act}' + , 'expected #{this} to not have the same members as #{act}' + , obj + , subset + ); + }); + + /** + * ### .oneOf(list) + * + * Assert that a value appears somewhere in the top level of array `list`. + * + * expect('a').to.be.oneOf(['a', 'b', 'c']); + * expect(9).to.not.be.oneOf(['z']); + * expect([3]).to.not.be.oneOf([1, 2, [3]]); + * + * var three = [3]; + * // for object-types, contents are not compared + * expect(three).to.not.be.oneOf([1, 2, [3]]); + * // comparing references works + * expect(three).to.be.oneOf([1, 2, three]); + * + * @name oneOf + * @param {Array<*>} list + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function oneOf (list, msg) { + if (msg) flag(this, 'message', msg); + var expected = flag(this, 'object'); + new Assertion(list).to.be.an('array'); + + this.assert( + list.indexOf(expected) > -1 + , 'expected #{this} to be one of #{exp}' + , 'expected #{this} to not be one of #{exp}' + , list + , expected + ); + } + + Assertion.addMethod('oneOf', oneOf); + + + /** + * ### .change(function) + * + * Asserts that a function changes an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val += 3 }; + * var noChangeFn = function() { return 'foo' + 'bar'; } + * expect(fn).to.change(obj, 'val'); + * expect(noChangeFn).to.not.change(obj, 'val') + * + * @name change + * @alias changes + * @alias Change + * @param {String} object + * @param {String} property name + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertChanges (object, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object'); + new Assertion(object, msg).to.have.property(prop); + new Assertion(fn).is.a('function'); + + var initial = object[prop]; + fn(); + + this.assert( + initial !== object[prop] + , 'expected .' + prop + ' to change' + , 'expected .' + prop + ' to not change' + ); + } + + Assertion.addChainableMethod('change', assertChanges); + Assertion.addChainableMethod('changes', assertChanges); + + /** + * ### .increase(function) + * + * Asserts that a function increases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * expect(fn).to.increase(obj, 'val'); + * + * @name increase + * @alias increases + * @alias Increase + * @param {String} object + * @param {String} property name + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertIncreases (object, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object'); + new Assertion(object, msg).to.have.property(prop); + new Assertion(fn).is.a('function'); + + var initial = object[prop]; + fn(); + + this.assert( + object[prop] - initial > 0 + , 'expected .' + prop + ' to increase' + , 'expected .' + prop + ' to not increase' + ); + } + + Assertion.addChainableMethod('increase', assertIncreases); + Assertion.addChainableMethod('increases', assertIncreases); + + /** + * ### .decrease(function) + * + * Asserts that a function decreases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * expect(fn).to.decrease(obj, 'val'); + * + * @name decrease + * @alias decreases + * @alias Decrease + * @param {String} object + * @param {String} property name + * @param {String} message _optional_ + * @namespace BDD + * @api public + */ + + function assertDecreases (object, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object'); + new Assertion(object, msg).to.have.property(prop); + new Assertion(fn).is.a('function'); + + var initial = object[prop]; + fn(); + + this.assert( + object[prop] - initial < 0 + , 'expected .' + prop + ' to decrease' + , 'expected .' + prop + ' to not decrease' + ); + } + + Assertion.addChainableMethod('decrease', assertDecreases); + Assertion.addChainableMethod('decreases', assertDecreases); + + /** + * ### .extensible + * + * Asserts that the target is extensible (can have new properties added to + * it). + * + * var nonExtensibleObject = Object.preventExtensions({}); + * var sealedObject = Object.seal({}); + * var frozenObject = Object.freeze({}); + * + * expect({}).to.be.extensible; + * expect(nonExtensibleObject).to.not.be.extensible; + * expect(sealedObject).to.not.be.extensible; + * expect(frozenObject).to.not.be.extensible; + * + * @name extensible + * @namespace BDD + * @api public + */ + + Assertion.addProperty('extensible', function() { + var obj = flag(this, 'object'); + + // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError. + // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible + // The following provides ES6 behavior when a TypeError is thrown under ES5. + + var isExtensible; + + try { + isExtensible = Object.isExtensible(obj); + } catch (err) { + if (err instanceof TypeError) isExtensible = false; + else throw err; + } + + this.assert( + isExtensible + , 'expected #{this} to be extensible' + , 'expected #{this} to not be extensible' + ); + }); + + /** + * ### .sealed + * + * Asserts that the target is sealed (cannot have new properties added to it + * and its existing properties cannot be removed). + * + * var sealedObject = Object.seal({}); + * var frozenObject = Object.freeze({}); + * + * expect(sealedObject).to.be.sealed; + * expect(frozenObject).to.be.sealed; + * expect({}).to.not.be.sealed; + * + * @name sealed + * @namespace BDD + * @api public + */ + + Assertion.addProperty('sealed', function() { + var obj = flag(this, 'object'); + + // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError. + // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed + // The following provides ES6 behavior when a TypeError is thrown under ES5. + + var isSealed; + + try { + isSealed = Object.isSealed(obj); + } catch (err) { + if (err instanceof TypeError) isSealed = true; + else throw err; + } + + this.assert( + isSealed + , 'expected #{this} to be sealed' + , 'expected #{this} to not be sealed' + ); + }); + + /** + * ### .frozen + * + * Asserts that the target is frozen (cannot have new properties added to it + * and its existing properties cannot be modified). + * + * var frozenObject = Object.freeze({}); + * + * expect(frozenObject).to.be.frozen; + * expect({}).to.not.be.frozen; + * + * @name frozen + * @namespace BDD + * @api public + */ + + Assertion.addProperty('frozen', function() { + var obj = flag(this, 'object'); + + // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError. + // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen + // The following provides ES6 behavior when a TypeError is thrown under ES5. + + var isFrozen; + + try { + isFrozen = Object.isFrozen(obj); + } catch (err) { + if (err instanceof TypeError) isFrozen = true; + else throw err; + } + + this.assert( + isFrozen + , 'expected #{this} to be frozen' + , 'expected #{this} to not be frozen' + ); + }); +}; + +},{}],6:[function(require,module,exports){ +/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + + +module.exports = function (chai, util) { + + /*! + * Chai dependencies. + */ + + var Assertion = chai.Assertion + , flag = util.flag; + + /*! + * Module export. + */ + + /** + * ### assert(expression, message) + * + * Write your own test expressions. + * + * assert('foo' !== 'bar', 'foo is not bar'); + * assert(Array.isArray([]), 'empty arrays are arrays'); + * + * @param {Mixed} expression to test for truthiness + * @param {String} message to display on error + * @name assert + * @namespace Assert + * @api public + */ + + var assert = chai.assert = function (express, errmsg) { + var test = new Assertion(null, null, chai.assert); + test.assert( + express + , errmsg + , '[ negation message unavailable ]' + ); + }; + + /** + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. Node.js `assert` module-compatible. + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @namespace Assert + * @api public + */ + + assert.fail = function (actual, expected, message, operator) { + message = message || 'assert.fail()'; + throw new chai.AssertionError(message, { + actual: actual + , expected: expected + , operator: operator + }, assert.fail); + }; + + /** + * ### .isOk(object, [message]) + * + * Asserts that `object` is truthy. + * + * assert.isOk('everything', 'everything is ok'); + * assert.isOk(false, 'this will fail'); + * + * @name isOk + * @alias ok + * @param {Mixed} object to test + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isOk = function (val, msg) { + new Assertion(val, msg).is.ok; + }; + + /** + * ### .isNotOk(object, [message]) + * + * Asserts that `object` is falsy. + * + * assert.isNotOk('everything', 'this will fail'); + * assert.isNotOk(false, 'this will pass'); + * + * @name isNotOk + * @alias notOk + * @param {Mixed} object to test + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotOk = function (val, msg) { + new Assertion(val, msg).is.not.ok; + }; + + /** + * ### .equal(actual, expected, [message]) + * + * Asserts non-strict equality (`==`) of `actual` and `expected`. + * + * assert.equal(3, '3', '== coerces values to strings'); + * + * @name equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.equal = function (act, exp, msg) { + var test = new Assertion(act, msg, assert.equal); + + test.assert( + exp == flag(test, 'object') + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{act}' + , exp + , act + ); + }; + + /** + * ### .notEqual(actual, expected, [message]) + * + * Asserts non-strict inequality (`!=`) of `actual` and `expected`. + * + * assert.notEqual(3, 4, 'these numbers are not equal'); + * + * @name notEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notEqual = function (act, exp, msg) { + var test = new Assertion(act, msg, assert.notEqual); + + test.assert( + exp != flag(test, 'object') + , 'expected #{this} to not equal #{exp}' + , 'expected #{this} to equal #{act}' + , exp + , act + ); + }; + + /** + * ### .strictEqual(actual, expected, [message]) + * + * Asserts strict equality (`===`) of `actual` and `expected`. + * + * assert.strictEqual(true, true, 'these booleans are strictly equal'); + * + * @name strictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.strictEqual = function (act, exp, msg) { + new Assertion(act, msg).to.equal(exp); + }; + + /** + * ### .notStrictEqual(actual, expected, [message]) + * + * Asserts strict inequality (`!==`) of `actual` and `expected`. + * + * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); + * + * @name notStrictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notStrictEqual = function (act, exp, msg) { + new Assertion(act, msg).to.not.equal(exp); + }; + + /** + * ### .deepEqual(actual, expected, [message]) + * + * Asserts that `actual` is deeply equal to `expected`. + * + * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); + * + * @name deepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.deepEqual = function (act, exp, msg) { + new Assertion(act, msg).to.eql(exp); + }; + + /** + * ### .notDeepEqual(actual, expected, [message]) + * + * Assert that `actual` is not deeply equal to `expected`. + * + * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); + * + * @name notDeepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notDeepEqual = function (act, exp, msg) { + new Assertion(act, msg).to.not.eql(exp); + }; + + /** + * ### .isAbove(valueToCheck, valueToBeAbove, [message]) + * + * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove` + * + * assert.isAbove(5, 2, '5 is strictly greater than 2'); + * + * @name isAbove + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAbove + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isAbove = function (val, abv, msg) { + new Assertion(val, msg).to.be.above(abv); + }; + + /** + * ### .isAtLeast(valueToCheck, valueToBeAtLeast, [message]) + * + * Asserts `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast` + * + * assert.isAtLeast(5, 2, '5 is greater or equal to 2'); + * assert.isAtLeast(3, 3, '3 is greater or equal to 3'); + * + * @name isAtLeast + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAtLeast + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isAtLeast = function (val, atlst, msg) { + new Assertion(val, msg).to.be.least(atlst); + }; + + /** + * ### .isBelow(valueToCheck, valueToBeBelow, [message]) + * + * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow` + * + * assert.isBelow(3, 6, '3 is strictly less than 6'); + * + * @name isBelow + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeBelow + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isBelow = function (val, blw, msg) { + new Assertion(val, msg).to.be.below(blw); + }; + + /** + * ### .isAtMost(valueToCheck, valueToBeAtMost, [message]) + * + * Asserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost` + * + * assert.isAtMost(3, 6, '3 is less than or equal to 6'); + * assert.isAtMost(4, 4, '4 is less than or equal to 4'); + * + * @name isAtMost + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAtMost + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isAtMost = function (val, atmst, msg) { + new Assertion(val, msg).to.be.most(atmst); + }; + + /** + * ### .isTrue(value, [message]) + * + * Asserts that `value` is true. + * + * var teaServed = true; + * assert.isTrue(teaServed, 'the tea has been served'); + * + * @name isTrue + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isTrue = function (val, msg) { + new Assertion(val, msg).is['true']; + }; + + /** + * ### .isNotTrue(value, [message]) + * + * Asserts that `value` is not true. + * + * var tea = 'tasty chai'; + * assert.isNotTrue(tea, 'great, time for tea!'); + * + * @name isNotTrue + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotTrue = function (val, msg) { + new Assertion(val, msg).to.not.equal(true); + }; + + /** + * ### .isFalse(value, [message]) + * + * Asserts that `value` is false. + * + * var teaServed = false; + * assert.isFalse(teaServed, 'no tea yet? hmm...'); + * + * @name isFalse + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isFalse = function (val, msg) { + new Assertion(val, msg).is['false']; + }; + + /** + * ### .isNotFalse(value, [message]) + * + * Asserts that `value` is not false. + * + * var tea = 'tasty chai'; + * assert.isNotFalse(tea, 'great, time for tea!'); + * + * @name isNotFalse + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotFalse = function (val, msg) { + new Assertion(val, msg).to.not.equal(false); + }; + + /** + * ### .isNull(value, [message]) + * + * Asserts that `value` is null. + * + * assert.isNull(err, 'there was no error'); + * + * @name isNull + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNull = function (val, msg) { + new Assertion(val, msg).to.equal(null); + }; + + /** + * ### .isNotNull(value, [message]) + * + * Asserts that `value` is not null. + * + * var tea = 'tasty chai'; + * assert.isNotNull(tea, 'great, time for tea!'); + * + * @name isNotNull + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotNull = function (val, msg) { + new Assertion(val, msg).to.not.equal(null); + }; + + /** + * ### .isNaN + * Asserts that value is NaN + * + * assert.isNaN('foo', 'foo is NaN'); + * + * @name isNaN + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNaN = function (val, msg) { + new Assertion(val, msg).to.be.NaN; + }; + + /** + * ### .isNotNaN + * Asserts that value is not NaN + * + * assert.isNotNaN(4, '4 is not NaN'); + * + * @name isNotNaN + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + assert.isNotNaN = function (val, msg) { + new Assertion(val, msg).not.to.be.NaN; + }; + + /** + * ### .isUndefined(value, [message]) + * + * Asserts that `value` is `undefined`. + * + * var tea; + * assert.isUndefined(tea, 'no tea defined'); + * + * @name isUndefined + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isUndefined = function (val, msg) { + new Assertion(val, msg).to.equal(undefined); + }; + + /** + * ### .isDefined(value, [message]) + * + * Asserts that `value` is not `undefined`. + * + * var tea = 'cup of chai'; + * assert.isDefined(tea, 'tea has been defined'); + * + * @name isDefined + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isDefined = function (val, msg) { + new Assertion(val, msg).to.not.equal(undefined); + }; + + /** + * ### .isFunction(value, [message]) + * + * Asserts that `value` is a function. + * + * function serveTea() { return 'cup of tea'; }; + * assert.isFunction(serveTea, 'great, we can have tea now'); + * + * @name isFunction + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isFunction = function (val, msg) { + new Assertion(val, msg).to.be.a('function'); + }; + + /** + * ### .isNotFunction(value, [message]) + * + * Asserts that `value` is _not_ a function. + * + * var serveTea = [ 'heat', 'pour', 'sip' ]; + * assert.isNotFunction(serveTea, 'great, we have listed the steps'); + * + * @name isNotFunction + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotFunction = function (val, msg) { + new Assertion(val, msg).to.not.be.a('function'); + }; + + /** + * ### .isObject(value, [message]) + * + * Asserts that `value` is an object of type 'Object' (as revealed by `Object.prototype.toString`). + * _The assertion does not match subclassed objects._ + * + * var selection = { name: 'Chai', serve: 'with spices' }; + * assert.isObject(selection, 'tea selection is an object'); + * + * @name isObject + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isObject = function (val, msg) { + new Assertion(val, msg).to.be.a('object'); + }; + + /** + * ### .isNotObject(value, [message]) + * + * Asserts that `value` is _not_ an object of type 'Object' (as revealed by `Object.prototype.toString`). + * + * var selection = 'chai' + * assert.isNotObject(selection, 'tea selection is not an object'); + * assert.isNotObject(null, 'null is not an object'); + * + * @name isNotObject + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotObject = function (val, msg) { + new Assertion(val, msg).to.not.be.a('object'); + }; + + /** + * ### .isArray(value, [message]) + * + * Asserts that `value` is an array. + * + * var menu = [ 'green', 'chai', 'oolong' ]; + * assert.isArray(menu, 'what kind of tea do we want?'); + * + * @name isArray + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isArray = function (val, msg) { + new Assertion(val, msg).to.be.an('array'); + }; + + /** + * ### .isNotArray(value, [message]) + * + * Asserts that `value` is _not_ an array. + * + * var menu = 'green|chai|oolong'; + * assert.isNotArray(menu, 'what kind of tea do we want?'); + * + * @name isNotArray + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotArray = function (val, msg) { + new Assertion(val, msg).to.not.be.an('array'); + }; + + /** + * ### .isString(value, [message]) + * + * Asserts that `value` is a string. + * + * var teaOrder = 'chai'; + * assert.isString(teaOrder, 'order placed'); + * + * @name isString + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isString = function (val, msg) { + new Assertion(val, msg).to.be.a('string'); + }; + + /** + * ### .isNotString(value, [message]) + * + * Asserts that `value` is _not_ a string. + * + * var teaOrder = 4; + * assert.isNotString(teaOrder, 'order placed'); + * + * @name isNotString + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotString = function (val, msg) { + new Assertion(val, msg).to.not.be.a('string'); + }; + + /** + * ### .isNumber(value, [message]) + * + * Asserts that `value` is a number. + * + * var cups = 2; + * assert.isNumber(cups, 'how many cups'); + * + * @name isNumber + * @param {Number} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNumber = function (val, msg) { + new Assertion(val, msg).to.be.a('number'); + }; + + /** + * ### .isNotNumber(value, [message]) + * + * Asserts that `value` is _not_ a number. + * + * var cups = '2 cups please'; + * assert.isNotNumber(cups, 'how many cups'); + * + * @name isNotNumber + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotNumber = function (val, msg) { + new Assertion(val, msg).to.not.be.a('number'); + }; + + /** + * ### .isBoolean(value, [message]) + * + * Asserts that `value` is a boolean. + * + * var teaReady = true + * , teaServed = false; + * + * assert.isBoolean(teaReady, 'is the tea ready'); + * assert.isBoolean(teaServed, 'has tea been served'); + * + * @name isBoolean + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isBoolean = function (val, msg) { + new Assertion(val, msg).to.be.a('boolean'); + }; + + /** + * ### .isNotBoolean(value, [message]) + * + * Asserts that `value` is _not_ a boolean. + * + * var teaReady = 'yep' + * , teaServed = 'nope'; + * + * assert.isNotBoolean(teaReady, 'is the tea ready'); + * assert.isNotBoolean(teaServed, 'has tea been served'); + * + * @name isNotBoolean + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isNotBoolean = function (val, msg) { + new Assertion(val, msg).to.not.be.a('boolean'); + }; + + /** + * ### .typeOf(value, name, [message]) + * + * Asserts that `value`'s type is `name`, as determined by + * `Object.prototype.toString`. + * + * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object'); + * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array'); + * assert.typeOf('tea', 'string', 'we have a string'); + * assert.typeOf(/tea/, 'regexp', 'we have a regular expression'); + * assert.typeOf(null, 'null', 'we have a null'); + * assert.typeOf(undefined, 'undefined', 'we have an undefined'); + * + * @name typeOf + * @param {Mixed} value + * @param {String} name + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.typeOf = function (val, type, msg) { + new Assertion(val, msg).to.be.a(type); + }; + + /** + * ### .notTypeOf(value, name, [message]) + * + * Asserts that `value`'s type is _not_ `name`, as determined by + * `Object.prototype.toString`. + * + * assert.notTypeOf('tea', 'number', 'strings are not numbers'); + * + * @name notTypeOf + * @param {Mixed} value + * @param {String} typeof name + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notTypeOf = function (val, type, msg) { + new Assertion(val, msg).to.not.be.a(type); + }; + + /** + * ### .instanceOf(object, constructor, [message]) + * + * Asserts that `value` is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new Tea('chai'); + * + * assert.instanceOf(chai, Tea, 'chai is an instance of tea'); + * + * @name instanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.instanceOf = function (val, type, msg) { + new Assertion(val, msg).to.be.instanceOf(type); + }; + + /** + * ### .notInstanceOf(object, constructor, [message]) + * + * Asserts `value` is not an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new String('chai'); + * + * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea'); + * + * @name notInstanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notInstanceOf = function (val, type, msg) { + new Assertion(val, msg).to.not.be.instanceOf(type); + }; + + /** + * ### .include(haystack, needle, [message]) + * + * Asserts that `haystack` includes `needle`. Works + * for strings and arrays. + * + * assert.include('foobar', 'bar', 'foobar contains string "bar"'); + * assert.include([ 1, 2, 3 ], 3, 'array contains value'); + * + * @name include + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.include = function (exp, inc, msg) { + new Assertion(exp, msg, assert.include).include(inc); + }; + + /** + * ### .notInclude(haystack, needle, [message]) + * + * Asserts that `haystack` does not include `needle`. Works + * for strings and arrays. + * + * assert.notInclude('foobar', 'baz', 'string not include substring'); + * assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value'); + * + * @name notInclude + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notInclude = function (exp, inc, msg) { + new Assertion(exp, msg, assert.notInclude).not.include(inc); + }; + + /** + * ### .match(value, regexp, [message]) + * + * Asserts that `value` matches the regular expression `regexp`. + * + * assert.match('foobar', /^foo/, 'regexp matches'); + * + * @name match + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.match = function (exp, re, msg) { + new Assertion(exp, msg).to.match(re); + }; + + /** + * ### .notMatch(value, regexp, [message]) + * + * Asserts that `value` does not match the regular expression `regexp`. + * + * assert.notMatch('foobar', /^foo/, 'regexp does not match'); + * + * @name notMatch + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notMatch = function (exp, re, msg) { + new Assertion(exp, msg).to.not.match(re); + }; + + /** + * ### .property(object, property, [message]) + * + * Asserts that `object` has a property named by `property`. + * + * assert.property({ tea: { green: 'matcha' }}, 'tea'); + * + * @name property + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.property = function (obj, prop, msg) { + new Assertion(obj, msg).to.have.property(prop); + }; + + /** + * ### .notProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`. + * + * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee'); + * + * @name notProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.not.have.property(prop); + }; + + /** + * ### .deepProperty(object, property, [message]) + * + * Asserts that `object` has a property named by `property`, which can be a + * string using dot- and bracket-notation for deep reference. + * + * assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green'); + * + * @name deepProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.deepProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.have.deep.property(prop); + }; + + /** + * ### .notDeepProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`, which + * can be a string using dot- and bracket-notation for deep reference. + * + * assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong'); + * + * @name notDeepProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notDeepProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.not.have.deep.property(prop); + }; + + /** + * ### .propertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. + * + * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good'); + * + * @name propertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.propertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.have.property(prop, val); + }; + + /** + * ### .propertyNotVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property`, but with a value + * different from that given by `value`. + * + * assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad'); + * + * @name propertyNotVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.propertyNotVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.not.have.property(prop, val); + }; + + /** + * ### .deepPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. `property` can use dot- and bracket-notation for deep + * reference. + * + * assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha'); + * + * @name deepPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.deepPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.have.deep.property(prop, val); + }; + + /** + * ### .deepPropertyNotVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property`, but with a value + * different from that given by `value`. `property` can use dot- and + * bracket-notation for deep reference. + * + * assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha'); + * + * @name deepPropertyNotVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.deepPropertyNotVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.not.have.deep.property(prop, val); + }; + + /** + * ### .lengthOf(object, length, [message]) + * + * Asserts that `object` has a `length` property with the expected value. + * + * assert.lengthOf([1,2,3], 3, 'array has length of 3'); + * assert.lengthOf('foobar', 6, 'string has length of 6'); + * + * @name lengthOf + * @param {Mixed} object + * @param {Number} length + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.lengthOf = function (exp, len, msg) { + new Assertion(exp, msg).to.have.length(len); + }; + + /** + * ### .throws(function, [constructor/string/regexp], [string/regexp], [message]) + * + * Asserts that `function` will throw an error that is an instance of + * `constructor`, or alternately that it will throw an error with message + * matching `regexp`. + * + * assert.throws(fn, 'function throws a reference error'); + * assert.throws(fn, /function throws a reference error/); + * assert.throws(fn, ReferenceError); + * assert.throws(fn, ReferenceError, 'function throws a reference error'); + * assert.throws(fn, ReferenceError, /function throws a reference error/); + * + * @name throws + * @alias throw + * @alias Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Assert + * @api public + */ + + assert.throws = function (fn, errt, errs, msg) { + if ('string' === typeof errt || errt instanceof RegExp) { + errs = errt; + errt = null; + } + + var assertErr = new Assertion(fn, msg).to.throw(errt, errs); + return flag(assertErr, 'object'); + }; + + /** + * ### .doesNotThrow(function, [constructor/regexp], [message]) + * + * Asserts that `function` will _not_ throw an error that is an instance of + * `constructor`, or alternately that it will not throw an error with message + * matching `regexp`. + * + * assert.doesNotThrow(fn, Error, 'function does not throw'); + * + * @name doesNotThrow + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Assert + * @api public + */ + + assert.doesNotThrow = function (fn, type, msg) { + if ('string' === typeof type) { + msg = type; + type = null; + } + + new Assertion(fn, msg).to.not.Throw(type); + }; + + /** + * ### .operator(val1, operator, val2, [message]) + * + * Compares two values using `operator`. + * + * assert.operator(1, '<', 2, 'everything is ok'); + * assert.operator(1, '>', 2, 'this will fail'); + * + * @name operator + * @param {Mixed} val1 + * @param {String} operator + * @param {Mixed} val2 + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.operator = function (val, operator, val2, msg) { + var ok; + switch(operator) { + case '==': + ok = val == val2; + break; + case '===': + ok = val === val2; + break; + case '>': + ok = val > val2; + break; + case '>=': + ok = val >= val2; + break; + case '<': + ok = val < val2; + break; + case '<=': + ok = val <= val2; + break; + case '!=': + ok = val != val2; + break; + case '!==': + ok = val !== val2; + break; + default: + throw new Error('Invalid operator "' + operator + '"'); + } + var test = new Assertion(ok, msg); + test.assert( + true === flag(test, 'object') + , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2) + , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) ); + }; + + /** + * ### .closeTo(actual, expected, delta, [message]) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * assert.closeTo(1.5, 1, 0.5, 'numbers are close'); + * + * @name closeTo + * @param {Number} actual + * @param {Number} expected + * @param {Number} delta + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.closeTo = function (act, exp, delta, msg) { + new Assertion(act, msg).to.be.closeTo(exp, delta); + }; + + /** + * ### .approximately(actual, expected, delta, [message]) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * assert.approximately(1.5, 1, 0.5, 'numbers are close'); + * + * @name approximately + * @param {Number} actual + * @param {Number} expected + * @param {Number} delta + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.approximately = function (act, exp, delta, msg) { + new Assertion(act, msg).to.be.approximately(exp, delta); + }; + + /** + * ### .sameMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` have the same members. + * Order is not taken into account. + * + * assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members'); + * + * @name sameMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.sameMembers = function (set1, set2, msg) { + new Assertion(set1, msg).to.have.same.members(set2); + } + + /** + * ### .sameDeepMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` have the same members - using a deep equality checking. + * Order is not taken into account. + * + * assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members'); + * + * @name sameDeepMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.sameDeepMembers = function (set1, set2, msg) { + new Assertion(set1, msg).to.have.same.deep.members(set2); + } + + /** + * ### .includeMembers(superset, subset, [message]) + * + * Asserts that `subset` is included in `superset`. + * Order is not taken into account. + * + * assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members'); + * + * @name includeMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.includeMembers = function (superset, subset, msg) { + new Assertion(superset, msg).to.include.members(subset); + } + + /** + * ### .includeDeepMembers(superset, subset, [message]) + * + * Asserts that `subset` is included in `superset` - using deep equality checking. + * Order is not taken into account. + * Duplicates are ignored. + * + * assert.includeDeepMembers([ {a: 1}, {b: 2}, {c: 3} ], [ {b: 2}, {a: 1}, {b: 2} ], 'include deep members'); + * + * @name includeDeepMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.includeDeepMembers = function (superset, subset, msg) { + new Assertion(superset, msg).to.include.deep.members(subset); + } + + /** + * ### .oneOf(inList, list, [message]) + * + * Asserts that non-object, non-array value `inList` appears in the flat array `list`. + * + * assert.oneOf(1, [ 2, 1 ], 'Not found in list'); + * + * @name oneOf + * @param {*} inList + * @param {Array<*>} list + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.oneOf = function (inList, list, msg) { + new Assertion(inList, msg).to.be.oneOf(list); + } + + /** + * ### .changes(function, object, property) + * + * Asserts that a function changes the value of a property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 22 }; + * assert.changes(fn, obj, 'val'); + * + * @name changes + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.changes = function (fn, obj, prop) { + new Assertion(fn).to.change(obj, prop); + } + + /** + * ### .doesNotChange(function, object, property) + * + * Asserts that a function does not changes the value of a property + * + * var obj = { val: 10 }; + * var fn = function() { console.log('foo'); }; + * assert.doesNotChange(fn, obj, 'val'); + * + * @name doesNotChange + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.doesNotChange = function (fn, obj, prop) { + new Assertion(fn).to.not.change(obj, prop); + } + + /** + * ### .increases(function, object, property) + * + * Asserts that a function increases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 13 }; + * assert.increases(fn, obj, 'val'); + * + * @name increases + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.increases = function (fn, obj, prop) { + new Assertion(fn).to.increase(obj, prop); + } + + /** + * ### .doesNotIncrease(function, object, property) + * + * Asserts that a function does not increase object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 8 }; + * assert.doesNotIncrease(fn, obj, 'val'); + * + * @name doesNotIncrease + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.doesNotIncrease = function (fn, obj, prop) { + new Assertion(fn).to.not.increase(obj, prop); + } + + /** + * ### .decreases(function, object, property) + * + * Asserts that a function decreases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * assert.decreases(fn, obj, 'val'); + * + * @name decreases + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.decreases = function (fn, obj, prop) { + new Assertion(fn).to.decrease(obj, prop); + } + + /** + * ### .doesNotDecrease(function, object, property) + * + * Asserts that a function does not decreases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * assert.doesNotDecrease(fn, obj, 'val'); + * + * @name doesNotDecrease + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.doesNotDecrease = function (fn, obj, prop) { + new Assertion(fn).to.not.decrease(obj, prop); + } + + /*! + * ### .ifError(object) + * + * Asserts if value is not a false value, and throws if it is a true value. + * This is added to allow for chai to be a drop-in replacement for Node's + * assert class. + * + * var err = new Error('I am a custom error'); + * assert.ifError(err); // Rethrows err! + * + * @name ifError + * @param {Object} object + * @namespace Assert + * @api public + */ + + assert.ifError = function (val) { + if (val) { + throw(val); + } + }; + + /** + * ### .isExtensible(object) + * + * Asserts that `object` is extensible (can have new properties added to it). + * + * assert.isExtensible({}); + * + * @name isExtensible + * @alias extensible + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.isExtensible = function (obj, msg) { + new Assertion(obj, msg).to.be.extensible; + }; + + /** + * ### .isNotExtensible(object) + * + * Asserts that `object` is _not_ extensible. + * + * var nonExtensibleObject = Object.preventExtensions({}); + * var sealedObject = Object.seal({}); + * var frozenObject = Object.freese({}); + * + * assert.isNotExtensible(nonExtensibleObject); + * assert.isNotExtensible(sealedObject); + * assert.isNotExtensible(frozenObject); + * + * @name isNotExtensible + * @alias notExtensible + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.isNotExtensible = function (obj, msg) { + new Assertion(obj, msg).to.not.be.extensible; + }; + + /** + * ### .isSealed(object) + * + * Asserts that `object` is sealed (cannot have new properties added to it + * and its existing properties cannot be removed). + * + * var sealedObject = Object.seal({}); + * var frozenObject = Object.seal({}); + * + * assert.isSealed(sealedObject); + * assert.isSealed(frozenObject); + * + * @name isSealed + * @alias sealed + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.isSealed = function (obj, msg) { + new Assertion(obj, msg).to.be.sealed; + }; + + /** + * ### .isNotSealed(object) + * + * Asserts that `object` is _not_ sealed. + * + * assert.isNotSealed({}); + * + * @name isNotSealed + * @alias notSealed + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.isNotSealed = function (obj, msg) { + new Assertion(obj, msg).to.not.be.sealed; + }; + + /** + * ### .isFrozen(object) + * + * Asserts that `object` is frozen (cannot have new properties added to it + * and its existing properties cannot be modified). + * + * var frozenObject = Object.freeze({}); + * assert.frozen(frozenObject); + * + * @name isFrozen + * @alias frozen + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.isFrozen = function (obj, msg) { + new Assertion(obj, msg).to.be.frozen; + }; + + /** + * ### .isNotFrozen(object) + * + * Asserts that `object` is _not_ frozen. + * + * assert.isNotFrozen({}); + * + * @name isNotFrozen + * @alias notFrozen + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.isNotFrozen = function (obj, msg) { + new Assertion(obj, msg).to.not.be.frozen; + }; + + /*! + * Aliases. + */ + + (function alias(name, as){ + assert[as] = assert[name]; + return alias; + }) + ('isOk', 'ok') + ('isNotOk', 'notOk') + ('throws', 'throw') + ('throws', 'Throw') + ('isExtensible', 'extensible') + ('isNotExtensible', 'notExtensible') + ('isSealed', 'sealed') + ('isNotSealed', 'notSealed') + ('isFrozen', 'frozen') + ('isNotFrozen', 'notFrozen'); +}; + +},{}],7:[function(require,module,exports){ +/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + +module.exports = function (chai, util) { + chai.expect = function (val, message) { + return new chai.Assertion(val, message); + }; + + /** + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @namespace Expect + * @api public + */ + + chai.expect.fail = function (actual, expected, message, operator) { + message = message || 'expect.fail()'; + throw new chai.AssertionError(message, { + actual: actual + , expected: expected + , operator: operator + }, chai.expect.fail); + }; +}; + +},{}],8:[function(require,module,exports){ +/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + +module.exports = function (chai, util) { + var Assertion = chai.Assertion; + + function loadShould () { + // explicitly define this method as function as to have it's name to include as `ssfi` + function shouldGetter() { + if (this instanceof String || this instanceof Number || this instanceof Boolean ) { + return new Assertion(this.valueOf(), null, shouldGetter); + } + return new Assertion(this, null, shouldGetter); + } + function shouldSetter(value) { + // See https://github.com/chaijs/chai/issues/86: this makes + // `whatever.should = someValue` actually set `someValue`, which is + // especially useful for `global.should = require('chai').should()`. + // + // Note that we have to use [[DefineProperty]] instead of [[Put]] + // since otherwise we would trigger this very setter! + Object.defineProperty(this, 'should', { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } + // modify Object.prototype to have `should` + Object.defineProperty(Object.prototype, 'should', { + set: shouldSetter + , get: shouldGetter + , configurable: true + }); + + var should = {}; + + /** + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @namespace Should + * @api public + */ + + should.fail = function (actual, expected, message, operator) { + message = message || 'should.fail()'; + throw new chai.AssertionError(message, { + actual: actual + , expected: expected + , operator: operator + }, should.fail); + }; + + /** + * ### .equal(actual, expected, [message]) + * + * Asserts non-strict equality (`==`) of `actual` and `expected`. + * + * should.equal(3, '3', '== coerces values to strings'); + * + * @name equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Should + * @api public + */ + + should.equal = function (val1, val2, msg) { + new Assertion(val1, msg).to.equal(val2); + }; + + /** + * ### .throw(function, [constructor/string/regexp], [string/regexp], [message]) + * + * Asserts that `function` will throw an error that is an instance of + * `constructor`, or alternately that it will throw an error with message + * matching `regexp`. + * + * should.throw(fn, 'function throws a reference error'); + * should.throw(fn, /function throws a reference error/); + * should.throw(fn, ReferenceError); + * should.throw(fn, ReferenceError, 'function throws a reference error'); + * should.throw(fn, ReferenceError, /function throws a reference error/); + * + * @name throw + * @alias Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Should + * @api public + */ + + should.Throw = function (fn, errt, errs, msg) { + new Assertion(fn, msg).to.Throw(errt, errs); + }; + + /** + * ### .exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var foo = 'hi'; + * + * should.exist(foo, 'foo exists'); + * + * @name exist + * @namespace Should + * @api public + */ + + should.exist = function (val, msg) { + new Assertion(val, msg).to.exist; + } + + // negation + should.not = {} + + /** + * ### .not.equal(actual, expected, [message]) + * + * Asserts non-strict inequality (`!=`) of `actual` and `expected`. + * + * should.not.equal(3, 4, 'these numbers are not equal'); + * + * @name not.equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Should + * @api public + */ + + should.not.equal = function (val1, val2, msg) { + new Assertion(val1, msg).to.not.equal(val2); + }; + + /** + * ### .throw(function, [constructor/regexp], [message]) + * + * Asserts that `function` will _not_ throw an error that is an instance of + * `constructor`, or alternately that it will not throw an error with message + * matching `regexp`. + * + * should.not.throw(fn, Error, 'function does not throw'); + * + * @name not.throw + * @alias not.Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Should + * @api public + */ + + should.not.Throw = function (fn, errt, errs, msg) { + new Assertion(fn, msg).to.not.Throw(errt, errs); + }; + + /** + * ### .not.exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var bar = null; + * + * should.not.exist(bar, 'bar does not exist'); + * + * @name not.exist + * @namespace Should + * @api public + */ + + should.not.exist = function (val, msg) { + new Assertion(val, msg).to.not.exist; + } + + should['throw'] = should['Throw']; + should.not['throw'] = should.not['Throw']; + + return should; + }; + + chai.should = loadShould; + chai.Should = loadShould; +}; + +},{}],9:[function(require,module,exports){ +/*! + * Chai - addChainingMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependencies + */ + +var transferFlags = require('./transferFlags'); +var flag = require('./flag'); +var config = require('../config'); + +/*! + * Module variables + */ + +// Check whether `__proto__` is supported +var hasProtoSupport = '__proto__' in Object; + +// Without `__proto__` support, this module will need to add properties to a function. +// However, some Function.prototype methods cannot be overwritten, +// and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69). +var excludeNames = /^(?:length|name|arguments|caller)$/; + +// Cache `Function` properties +var call = Function.prototype.call, + apply = Function.prototype.apply; + +/** + * ### addChainableMethod (ctx, name, method, chainingBehavior) + * + * Adds a method to an object, such that the method can also be chained. + * + * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior); + * + * The result can then be used as both a method assertion, executing both `method` and + * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`. + * + * expect(fooStr).to.be.foo('bar'); + * expect(fooStr).to.be.foo.equal('foo'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for `name`, when called + * @param {Function} chainingBehavior function to be called every time the property is accessed + * @namespace Utils + * @name addChainableMethod + * @api public + */ + +module.exports = function (ctx, name, method, chainingBehavior) { + if (typeof chainingBehavior !== 'function') { + chainingBehavior = function () { }; + } + + var chainableBehavior = { + method: method + , chainingBehavior: chainingBehavior + }; + + // save the methods so we can overwrite them later, if we need to. + if (!ctx.__methods) { + ctx.__methods = {}; + } + ctx.__methods[name] = chainableBehavior; + + Object.defineProperty(ctx, name, + { get: function () { + chainableBehavior.chainingBehavior.call(this); + + var assert = function assert() { + var old_ssfi = flag(this, 'ssfi'); + if (old_ssfi && config.includeStack === false) + flag(this, 'ssfi', assert); + var result = chainableBehavior.method.apply(this, arguments); + return result === undefined ? this : result; + }; + + // Use `__proto__` if available + if (hasProtoSupport) { + // Inherit all properties from the object by replacing the `Function` prototype + var prototype = assert.__proto__ = Object.create(this); + // Restore the `call` and `apply` methods from `Function` + prototype.call = call; + prototype.apply = apply; + } + // Otherwise, redefine all properties (slow!) + else { + var asserterNames = Object.getOwnPropertyNames(ctx); + asserterNames.forEach(function (asserterName) { + if (!excludeNames.test(asserterName)) { + var pd = Object.getOwnPropertyDescriptor(ctx, asserterName); + Object.defineProperty(assert, asserterName, pd); + } + }); + } + + transferFlags(this, assert); + return assert; + } + , configurable: true + }); +}; + +},{"../config":4,"./flag":13,"./transferFlags":29}],10:[function(require,module,exports){ +/*! + * Chai - addMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +var config = require('../config'); + +/** + * ### .addMethod (ctx, name, method) + * + * Adds a method to the prototype of an object. + * + * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(fooStr).to.be.foo('bar'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for name + * @namespace Utils + * @name addMethod + * @api public + */ +var flag = require('./flag'); + +module.exports = function (ctx, name, method) { + ctx[name] = function () { + var old_ssfi = flag(this, 'ssfi'); + if (old_ssfi && config.includeStack === false) + flag(this, 'ssfi', ctx[name]); + var result = method.apply(this, arguments); + return result === undefined ? this : result; + }; +}; + +},{"../config":4,"./flag":13}],11:[function(require,module,exports){ +/*! + * Chai - addProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +var config = require('../config'); +var flag = require('./flag'); + +/** + * ### addProperty (ctx, name, getter) + * + * Adds a property to the prototype of an object. + * + * utils.addProperty(chai.Assertion.prototype, 'foo', function () { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.instanceof(Foo); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.foo; + * + * @param {Object} ctx object to which the property is added + * @param {String} name of property to add + * @param {Function} getter function to be used for name + * @namespace Utils + * @name addProperty + * @api public + */ + +module.exports = function (ctx, name, getter) { + Object.defineProperty(ctx, name, + { get: function addProperty() { + var old_ssfi = flag(this, 'ssfi'); + if (old_ssfi && config.includeStack === false) + flag(this, 'ssfi', addProperty); + + var result = getter.call(this); + return result === undefined ? this : result; + } + , configurable: true + }); +}; + +},{"../config":4,"./flag":13}],12:[function(require,module,exports){ +/*! + * Chai - expectTypes utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### expectTypes(obj, types) + * + * Ensures that the object being tested against is of a valid type. + * + * utils.expectTypes(this, ['array', 'object', 'string']); + * + * @param {Mixed} obj constructed Assertion + * @param {Array} type A list of allowed types for this assertion + * @namespace Utils + * @name expectTypes + * @api public + */ + +var AssertionError = require('assertion-error'); +var flag = require('./flag'); +var type = require('type-detect'); + +module.exports = function (obj, types) { + var obj = flag(obj, 'object'); + types = types.map(function (t) { return t.toLowerCase(); }); + types.sort(); + + // Transforms ['lorem', 'ipsum'] into 'a lirum, or an ipsum' + var str = types.map(function (t, index) { + var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a'; + var or = types.length > 1 && index === types.length - 1 ? 'or ' : ''; + return or + art + ' ' + t; + }).join(', '); + + if (!types.some(function (expected) { return type(obj) === expected; })) { + throw new AssertionError( + 'object tested must be ' + str + ', but ' + type(obj) + ' given' + ); + } +}; + +},{"./flag":13,"assertion-error":30,"type-detect":35}],13:[function(require,module,exports){ +/*! + * Chai - flag utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### flag(object, key, [value]) + * + * Get or set a flag value on an object. If a + * value is provided it will be set, else it will + * return the currently set value or `undefined` if + * the value is not set. + * + * utils.flag(this, 'foo', 'bar'); // setter + * utils.flag(this, 'foo'); // getter, returns `bar` + * + * @param {Object} object constructed Assertion + * @param {String} key + * @param {Mixed} value (optional) + * @namespace Utils + * @name flag + * @api private + */ + +module.exports = function (obj, key, value) { + var flags = obj.__flags || (obj.__flags = Object.create(null)); + if (arguments.length === 3) { + flags[key] = value; + } else { + return flags[key]; + } +}; + +},{}],14:[function(require,module,exports){ +/*! + * Chai - getActual utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * # getActual(object, [actual]) + * + * Returns the `actual` value for an Assertion + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name getActual + */ + +module.exports = function (obj, args) { + return args.length > 4 ? args[4] : obj._obj; +}; + +},{}],15:[function(require,module,exports){ +/*! + * Chai - getEnumerableProperties utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### .getEnumerableProperties(object) + * + * This allows the retrieval of enumerable property names of an object, + * inherited or not. + * + * @param {Object} object + * @returns {Array} + * @namespace Utils + * @name getEnumerableProperties + * @api public + */ + +module.exports = function getEnumerableProperties(object) { + var result = []; + for (var name in object) { + result.push(name); + } + return result; +}; + +},{}],16:[function(require,module,exports){ +/*! + * Chai - message composition utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependancies + */ + +var flag = require('./flag') + , getActual = require('./getActual') + , inspect = require('./inspect') + , objDisplay = require('./objDisplay'); + +/** + * ### .getMessage(object, message, negateMessage) + * + * Construct the error message based on flags + * and template tags. Template tags will return + * a stringified inspection of the object referenced. + * + * Message template tags: + * - `#{this}` current asserted object + * - `#{act}` actual value + * - `#{exp}` expected value + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name getMessage + * @api public + */ + +module.exports = function (obj, args) { + var negate = flag(obj, 'negate') + , val = flag(obj, 'object') + , expected = args[3] + , actual = getActual(obj, args) + , msg = negate ? args[2] : args[1] + , flagMsg = flag(obj, 'message'); + + if(typeof msg === "function") msg = msg(); + msg = msg || ''; + msg = msg + .replace(/#\{this\}/g, function () { return objDisplay(val); }) + .replace(/#\{act\}/g, function () { return objDisplay(actual); }) + .replace(/#\{exp\}/g, function () { return objDisplay(expected); }); + + return flagMsg ? flagMsg + ': ' + msg : msg; +}; + +},{"./flag":13,"./getActual":14,"./inspect":23,"./objDisplay":24}],17:[function(require,module,exports){ +/*! + * Chai - getName utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * # getName(func) + * + * Gets the name of a function, in a cross-browser way. + * + * @param {Function} a function (usually a constructor) + * @namespace Utils + * @name getName + */ + +module.exports = function (func) { + if (func.name) return func.name; + + var match = /^\s?function ([^(]*)\(/.exec(func); + return match && match[1] ? match[1] : ""; +}; + +},{}],18:[function(require,module,exports){ +/*! + * Chai - getPathInfo utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +var hasProperty = require('./hasProperty'); + +/** + * ### .getPathInfo(path, object) + * + * This allows the retrieval of property info in an + * object given a string path. + * + * The path info consists of an object with the + * following properties: + * + * * parent - The parent object of the property referenced by `path` + * * name - The name of the final property, a number if it was an array indexer + * * value - The value of the property, if it exists, otherwise `undefined` + * * exists - Whether the property exists or not + * + * @param {String} path + * @param {Object} object + * @returns {Object} info + * @namespace Utils + * @name getPathInfo + * @api public + */ + +module.exports = function getPathInfo(path, obj) { + var parsed = parsePath(path), + last = parsed[parsed.length - 1]; + + var info = { + parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj, + name: last.p || last.i, + value: _getPathValue(parsed, obj) + }; + info.exists = hasProperty(info.name, info.parent); + + return info; +}; + + +/*! + * ## parsePath(path) + * + * Helper function used to parse string object + * paths. Use in conjunction with `_getPathValue`. + * + * var parsed = parsePath('myobject.property.subprop'); + * + * ### Paths: + * + * * Can be as near infinitely deep and nested + * * Arrays are also valid using the formal `myobject.document[3].property`. + * * Literal dots and brackets (not delimiter) must be backslash-escaped. + * + * @param {String} path + * @returns {Object} parsed + * @api private + */ + +function parsePath (path) { + var str = path.replace(/([^\\])\[/g, '$1.[') + , parts = str.match(/(\\\.|[^.]+?)+/g); + return parts.map(function (value) { + var re = /^\[(\d+)\]$/ + , mArr = re.exec(value); + if (mArr) return { i: parseFloat(mArr[1]) }; + else return { p: value.replace(/\\([.\[\]])/g, '$1') }; + }); +} + + +/*! + * ## _getPathValue(parsed, obj) + * + * Helper companion function for `.parsePath` that returns + * the value located at the parsed address. + * + * var value = getPathValue(parsed, obj); + * + * @param {Object} parsed definition from `parsePath`. + * @param {Object} object to search against + * @param {Number} object to search against + * @returns {Object|Undefined} value + * @api private + */ + +function _getPathValue (parsed, obj, index) { + var tmp = obj + , res; + + index = (index === undefined ? parsed.length : index); + + for (var i = 0, l = index; i < l; i++) { + var part = parsed[i]; + if (tmp) { + if ('undefined' !== typeof part.p) + tmp = tmp[part.p]; + else if ('undefined' !== typeof part.i) + tmp = tmp[part.i]; + if (i == (l - 1)) res = tmp; + } else { + res = undefined; + } + } + return res; +} + +},{"./hasProperty":21}],19:[function(require,module,exports){ +/*! + * Chai - getPathValue utility + * Copyright(c) 2012-2014 Jake Luer + * @see https://github.com/logicalparadox/filtr + * MIT Licensed + */ + +var getPathInfo = require('./getPathInfo'); + +/** + * ### .getPathValue(path, object) + * + * This allows the retrieval of values in an + * object given a string path. + * + * var obj = { + * prop1: { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * , prop2: { + * arr: [ { nested: 'Universe' } ] + * , str: 'Hello again!' + * } + * } + * + * The following would be the results. + * + * getPathValue('prop1.str', obj); // Hello + * getPathValue('prop1.att[2]', obj); // b + * getPathValue('prop2.arr[0].nested', obj); // Universe + * + * @param {String} path + * @param {Object} object + * @returns {Object} value or `undefined` + * @namespace Utils + * @name getPathValue + * @api public + */ +module.exports = function(path, obj) { + var info = getPathInfo(path, obj); + return info.value; +}; + +},{"./getPathInfo":18}],20:[function(require,module,exports){ +/*! + * Chai - getProperties utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### .getProperties(object) + * + * This allows the retrieval of property names of an object, enumerable or not, + * inherited or not. + * + * @param {Object} object + * @returns {Array} + * @namespace Utils + * @name getProperties + * @api public + */ + +module.exports = function getProperties(object) { + var result = Object.getOwnPropertyNames(object); + + function addProperty(property) { + if (result.indexOf(property) === -1) { + result.push(property); + } + } + + var proto = Object.getPrototypeOf(object); + while (proto !== null) { + Object.getOwnPropertyNames(proto).forEach(addProperty); + proto = Object.getPrototypeOf(proto); + } + + return result; +}; + +},{}],21:[function(require,module,exports){ +/*! + * Chai - hasProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +var type = require('type-detect'); + +/** + * ### .hasProperty(object, name) + * + * This allows checking whether an object has + * named property or numeric array index. + * + * Basically does the same thing as the `in` + * operator but works properly with natives + * and null/undefined values. + * + * var obj = { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * + * The following would be the results. + * + * hasProperty('str', obj); // true + * hasProperty('constructor', obj); // true + * hasProperty('bar', obj); // false + * + * hasProperty('length', obj.str); // true + * hasProperty(1, obj.str); // true + * hasProperty(5, obj.str); // false + * + * hasProperty('length', obj.arr); // true + * hasProperty(2, obj.arr); // true + * hasProperty(3, obj.arr); // false + * + * @param {Objuect} object + * @param {String|Number} name + * @returns {Boolean} whether it exists + * @namespace Utils + * @name getPathInfo + * @api public + */ + +var literals = { + 'number': Number + , 'string': String +}; + +module.exports = function hasProperty(name, obj) { + var ot = type(obj); + + // Bad Object, obviously no props at all + if(ot === 'null' || ot === 'undefined') + return false; + + // The `in` operator does not work with certain literals + // box these before the check + if(literals[ot] && typeof obj !== 'object') + obj = new literals[ot](obj); + + return name in obj; +}; + +},{"type-detect":35}],22:[function(require,module,exports){ +/*! + * chai + * Copyright(c) 2011 Jake Luer + * MIT Licensed + */ + +/*! + * Main exports + */ + +var exports = module.exports = {}; + +/*! + * test utility + */ + +exports.test = require('./test'); + +/*! + * type utility + */ + +exports.type = require('type-detect'); + +/*! + * expectTypes utility + */ +exports.expectTypes = require('./expectTypes'); + +/*! + * message utility + */ + +exports.getMessage = require('./getMessage'); + +/*! + * actual utility + */ + +exports.getActual = require('./getActual'); + +/*! + * Inspect util + */ + +exports.inspect = require('./inspect'); + +/*! + * Object Display util + */ + +exports.objDisplay = require('./objDisplay'); + +/*! + * Flag utility + */ + +exports.flag = require('./flag'); + +/*! + * Flag transferring utility + */ + +exports.transferFlags = require('./transferFlags'); + +/*! + * Deep equal utility + */ + +exports.eql = require('deep-eql'); + +/*! + * Deep path value + */ + +exports.getPathValue = require('./getPathValue'); + +/*! + * Deep path info + */ + +exports.getPathInfo = require('./getPathInfo'); + +/*! + * Check if a property exists + */ + +exports.hasProperty = require('./hasProperty'); + +/*! + * Function name + */ + +exports.getName = require('./getName'); + +/*! + * add Property + */ + +exports.addProperty = require('./addProperty'); + +/*! + * add Method + */ + +exports.addMethod = require('./addMethod'); + +/*! + * overwrite Property + */ + +exports.overwriteProperty = require('./overwriteProperty'); + +/*! + * overwrite Method + */ + +exports.overwriteMethod = require('./overwriteMethod'); + +/*! + * Add a chainable method + */ + +exports.addChainableMethod = require('./addChainableMethod'); + +/*! + * Overwrite chainable method + */ + +exports.overwriteChainableMethod = require('./overwriteChainableMethod'); + +},{"./addChainableMethod":9,"./addMethod":10,"./addProperty":11,"./expectTypes":12,"./flag":13,"./getActual":14,"./getMessage":16,"./getName":17,"./getPathInfo":18,"./getPathValue":19,"./hasProperty":21,"./inspect":23,"./objDisplay":24,"./overwriteChainableMethod":25,"./overwriteMethod":26,"./overwriteProperty":27,"./test":28,"./transferFlags":29,"deep-eql":31,"type-detect":35}],23:[function(require,module,exports){ +// This is (almost) directly from Node.js utils +// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js + +var getName = require('./getName'); +var getProperties = require('./getProperties'); +var getEnumerableProperties = require('./getEnumerableProperties'); + +module.exports = inspect; + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Boolean} showHidden Flag that shows hidden (not enumerable) + * properties of objects. + * @param {Number} depth Depth in which to descend in object. Default is 2. + * @param {Boolean} colors Flag to turn on ANSI escape codes to color the + * output. Default is false (no coloring). + * @namespace Utils + * @name inspect + */ +function inspect(obj, showHidden, depth, colors) { + var ctx = { + showHidden: showHidden, + seen: [], + stylize: function (str) { return str; } + }; + return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth)); +} + +// Returns true if object is a DOM element. +var isDOMElement = function (object) { + if (typeof HTMLElement === 'object') { + return object instanceof HTMLElement; + } else { + return object && + typeof object === 'object' && + object.nodeType === 1 && + typeof object.nodeName === 'string'; + } +}; + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (value && typeof value.inspect === 'function' && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes); + if (typeof ret !== 'string') { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // If this is a DOM element, try to get the outer HTML. + if (isDOMElement(value)) { + if ('outerHTML' in value) { + return value.outerHTML; + // This value does not have an outerHTML attribute, + // it could still be an XML element + } else { + // Attempt to serialize it + try { + if (document.xmlVersion) { + var xmlSerializer = new XMLSerializer(); + return xmlSerializer.serializeToString(value); + } else { + // Firefox 11- do not support outerHTML + // It does, however, support innerHTML + // Use the following to render the element + var ns = "http://www.w3.org/1999/xhtml"; + var container = document.createElementNS(ns, '_'); + + container.appendChild(value.cloneNode(false)); + html = container.innerHTML + .replace('><', '>' + value.innerHTML + '<'); + container.innerHTML = ''; + return html; + } + } catch (err) { + // This could be a non-native DOM implementation, + // continue with the normal flow: + // printing the element as if it is an object. + } + } + } + + // Look up the keys of the object. + var visibleKeys = getEnumerableProperties(value); + var keys = ctx.showHidden ? getProperties(value) : visibleKeys; + + // Some type of object without properties can be shortcutted. + // In IE, errors have a single `stack` property, or if they are vanilla `Error`, + // a `stack` plus `description` property; ignore those for consistency. + if (keys.length === 0 || (isError(value) && ( + (keys.length === 1 && keys[0] === 'stack') || + (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack') + ))) { + if (typeof value === 'function') { + var name = getName(value); + var nameSuffix = name ? ': ' + name : ''; + return ctx.stylize('[Function' + nameSuffix + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toUTCString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (typeof value === 'function') { + var name = getName(value); + var nameSuffix = name ? ': ' + name : ''; + base = ' [Function' + nameSuffix + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + return formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + switch (typeof value) { + case 'undefined': + return ctx.stylize('undefined', 'undefined'); + + case 'string': + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + + case 'number': + if (value === 0 && (1/value) === -Infinity) { + return ctx.stylize('-0', 'number'); + } + return ctx.stylize('' + value, 'number'); + + case 'boolean': + return ctx.stylize('' + value, 'boolean'); + } + // For some reason typeof null is "object", so special case here. + if (value === null) { + return ctx.stylize('null', 'null'); + } +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (Object.prototype.hasOwnProperty.call(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str; + if (value.__lookupGetter__) { + if (value.__lookupGetter__(key)) { + if (value.__lookupSetter__(key)) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (value.__lookupSetter__(key)) { + str = ctx.stylize('[Setter]', 'special'); + } + } + } + if (visibleKeys.indexOf(key) < 0) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(value[key]) < 0) { + if (recurseTimes === null) { + str = formatValue(ctx, value[key], null); + } else { + str = formatValue(ctx, value[key], recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (typeof name === 'undefined') { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + +function isArray(ar) { + return Array.isArray(ar) || + (typeof ar === 'object' && objectToString(ar) === '[object Array]'); +} + +function isRegExp(re) { + return typeof re === 'object' && objectToString(re) === '[object RegExp]'; +} + +function isDate(d) { + return typeof d === 'object' && objectToString(d) === '[object Date]'; +} + +function isError(e) { + return typeof e === 'object' && objectToString(e) === '[object Error]'; +} + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +},{"./getEnumerableProperties":15,"./getName":17,"./getProperties":20}],24:[function(require,module,exports){ +/*! + * Chai - flag utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependancies + */ + +var inspect = require('./inspect'); +var config = require('../config'); + +/** + * ### .objDisplay (object) + * + * Determines if an object or an array matches + * criteria to be inspected in-line for error + * messages or should be truncated. + * + * @param {Mixed} javascript object to inspect + * @name objDisplay + * @namespace Utils + * @api public + */ + +module.exports = function (obj) { + var str = inspect(obj) + , type = Object.prototype.toString.call(obj); + + if (config.truncateThreshold && str.length >= config.truncateThreshold) { + if (type === '[object Function]') { + return !obj.name || obj.name === '' + ? '[Function]' + : '[Function: ' + obj.name + ']'; + } else if (type === '[object Array]') { + return '[ Array(' + obj.length + ') ]'; + } else if (type === '[object Object]') { + var keys = Object.keys(obj) + , kstr = keys.length > 2 + ? keys.splice(0, 2).join(', ') + ', ...' + : keys.join(', '); + return '{ Object (' + kstr + ') }'; + } else { + return str; + } + } else { + return str; + } +}; + +},{"../config":4,"./inspect":23}],25:[function(require,module,exports){ +/*! + * Chai - overwriteChainableMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### overwriteChainableMethod (ctx, name, method, chainingBehavior) + * + * Overwites an already existing chainable method + * and provides access to the previous function or + * property. Must return functions to be used for + * name. + * + * utils.overwriteChainableMethod(chai.Assertion.prototype, 'length', + * function (_super) { + * } + * , function (_super) { + * } + * ); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteChainableMethod('foo', fn, fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.have.length(3); + * expect(myFoo).to.have.length.above(3); + * + * @param {Object} ctx object whose method / property is to be overwritten + * @param {String} name of method / property to overwrite + * @param {Function} method function that returns a function to be used for name + * @param {Function} chainingBehavior function that returns a function to be used for property + * @namespace Utils + * @name overwriteChainableMethod + * @api public + */ + +module.exports = function (ctx, name, method, chainingBehavior) { + var chainableBehavior = ctx.__methods[name]; + + var _chainingBehavior = chainableBehavior.chainingBehavior; + chainableBehavior.chainingBehavior = function () { + var result = chainingBehavior(_chainingBehavior).call(this); + return result === undefined ? this : result; + }; + + var _method = chainableBehavior.method; + chainableBehavior.method = function () { + var result = method(_method).apply(this, arguments); + return result === undefined ? this : result; + }; +}; + +},{}],26:[function(require,module,exports){ +/*! + * Chai - overwriteMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### overwriteMethod (ctx, name, fn) + * + * Overwites an already existing method and provides + * access to previous function. Must return function + * to be used for name. + * + * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { + * return function (str) { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.value).to.equal(str); + * } else { + * _super.apply(this, arguments); + * } + * } + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.equal('bar'); + * + * @param {Object} ctx object whose method is to be overwritten + * @param {String} name of method to overwrite + * @param {Function} method function that returns a function to be used for name + * @namespace Utils + * @name overwriteMethod + * @api public + */ + +module.exports = function (ctx, name, method) { + var _method = ctx[name] + , _super = function () { return this; }; + + if (_method && 'function' === typeof _method) + _super = _method; + + ctx[name] = function () { + var result = method(_super).apply(this, arguments); + return result === undefined ? this : result; + } +}; + +},{}],27:[function(require,module,exports){ +/*! + * Chai - overwriteProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### overwriteProperty (ctx, name, fn) + * + * Overwites an already existing property getter and provides + * access to previous value. Must return function to use as getter. + * + * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) { + * return function () { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.name).to.equal('bar'); + * } else { + * _super.call(this); + * } + * } + * }); + * + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.ok; + * + * @param {Object} ctx object whose property is to be overwritten + * @param {String} name of property to overwrite + * @param {Function} getter function that returns a getter function to be used for name + * @namespace Utils + * @name overwriteProperty + * @api public + */ + +module.exports = function (ctx, name, getter) { + var _get = Object.getOwnPropertyDescriptor(ctx, name) + , _super = function () {}; + + if (_get && 'function' === typeof _get.get) + _super = _get.get + + Object.defineProperty(ctx, name, + { get: function () { + var result = getter(_super).call(this); + return result === undefined ? this : result; + } + , configurable: true + }); +}; + +},{}],28:[function(require,module,exports){ +/*! + * Chai - test utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependancies + */ + +var flag = require('./flag'); + +/** + * # test(object, expression) + * + * Test and object for expression. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name test + */ + +module.exports = function (obj, args) { + var negate = flag(obj, 'negate') + , expr = args[0]; + return negate ? !expr : expr; +}; + +},{"./flag":13}],29:[function(require,module,exports){ +/*! + * Chai - transferFlags utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### transferFlags(assertion, object, includeAll = true) + * + * Transfer all the flags for `assertion` to `object`. If + * `includeAll` is set to `false`, then the base Chai + * assertion flags (namely `object`, `ssfi`, and `message`) + * will not be transferred. + * + * + * var newAssertion = new Assertion(); + * utils.transferFlags(assertion, newAssertion); + * + * var anotherAsseriton = new Assertion(myObj); + * utils.transferFlags(assertion, anotherAssertion, false); + * + * @param {Assertion} assertion the assertion to transfer the flags from + * @param {Object} object the object to transfer the flags to; usually a new assertion + * @param {Boolean} includeAll + * @namespace Utils + * @name transferFlags + * @api private + */ + +module.exports = function (assertion, object, includeAll) { + var flags = assertion.__flags || (assertion.__flags = Object.create(null)); + + if (!object.__flags) { + object.__flags = Object.create(null); + } + + includeAll = arguments.length === 3 ? includeAll : true; + + for (var flag in flags) { + if (includeAll || + (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) { + object.__flags[flag] = flags[flag]; + } + } +}; + +},{}],30:[function(require,module,exports){ +/*! + * assertion-error + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */ + +/*! + * Return a function that will copy properties from + * one object to another excluding any originally + * listed. Returned function will create a new `{}`. + * + * @param {String} excluded properties ... + * @return {Function} + */ + +function exclude () { + var excludes = [].slice.call(arguments); + + function excludeProps (res, obj) { + Object.keys(obj).forEach(function (key) { + if (!~excludes.indexOf(key)) res[key] = obj[key]; + }); + } + + return function extendExclude () { + var args = [].slice.call(arguments) + , i = 0 + , res = {}; + + for (; i < args.length; i++) { + excludeProps(res, args[i]); + } + + return res; + }; +}; + +/*! + * Primary Exports + */ + +module.exports = AssertionError; + +/** + * ### AssertionError + * + * An extension of the JavaScript `Error` constructor for + * assertion and validation scenarios. + * + * @param {String} message + * @param {Object} properties to include (optional) + * @param {callee} start stack function (optional) + */ + +function AssertionError (message, _props, ssf) { + var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON') + , props = extend(_props || {}); + + // default values + this.message = message || 'Unspecified AssertionError'; + this.showDiff = false; + + // copy from properties + for (var key in props) { + this[key] = props[key]; + } + + // capture stack trace + ssf = ssf || arguments.callee; + if (ssf && Error.captureStackTrace) { + Error.captureStackTrace(this, ssf); + } else { + this.stack = new Error().stack; + } +} + +/*! + * Inherit from Error.prototype + */ + +AssertionError.prototype = Object.create(Error.prototype); + +/*! + * Statically set name + */ + +AssertionError.prototype.name = 'AssertionError'; + +/*! + * Ensure correct constructor + */ + +AssertionError.prototype.constructor = AssertionError; + +/** + * Allow errors to be converted to JSON for static transfer. + * + * @param {Boolean} include stack (default: `true`) + * @return {Object} object that can be `JSON.stringify` + */ + +AssertionError.prototype.toJSON = function (stack) { + var extend = exclude('constructor', 'toJSON', 'stack') + , props = extend({ name: this.name }, this); + + // include stack if exists and not turned off + if (false !== stack && this.stack) { + props.stack = this.stack; + } + + return props; +}; + +},{}],31:[function(require,module,exports){ +module.exports = require('./lib/eql'); + +},{"./lib/eql":32}],32:[function(require,module,exports){ +/*! + * deep-eql + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependencies + */ + +var type = require('type-detect'); + +/*! + * Buffer.isBuffer browser shim + */ + +var Buffer; +try { Buffer = require('buffer').Buffer; } +catch(ex) { + Buffer = {}; + Buffer.isBuffer = function() { return false; } +} + +/*! + * Primary Export + */ + +module.exports = deepEqual; + +/** + * Assert super-strict (egal) equality between + * two objects of any type. + * + * @param {Mixed} a + * @param {Mixed} b + * @param {Array} memoised (optional) + * @return {Boolean} equal match + */ + +function deepEqual(a, b, m) { + if (sameValue(a, b)) { + return true; + } else if ('date' === type(a)) { + return dateEqual(a, b); + } else if ('regexp' === type(a)) { + return regexpEqual(a, b); + } else if (Buffer.isBuffer(a)) { + return bufferEqual(a, b); + } else if ('arguments' === type(a)) { + return argumentsEqual(a, b, m); + } else if (!typeEqual(a, b)) { + return false; + } else if (('object' !== type(a) && 'object' !== type(b)) + && ('array' !== type(a) && 'array' !== type(b))) { + return sameValue(a, b); + } else { + return objectEqual(a, b, m); + } +} + +/*! + * Strict (egal) equality test. Ensures that NaN always + * equals NaN and `-0` does not equal `+0`. + * + * @param {Mixed} a + * @param {Mixed} b + * @return {Boolean} equal match + */ + +function sameValue(a, b) { + if (a === b) return a !== 0 || 1 / a === 1 / b; + return a !== a && b !== b; +} + +/*! + * Compare the types of two given objects and + * return if they are equal. Note that an Array + * has a type of `array` (not `object`) and arguments + * have a type of `arguments` (not `array`/`object`). + * + * @param {Mixed} a + * @param {Mixed} b + * @return {Boolean} result + */ + +function typeEqual(a, b) { + return type(a) === type(b); +} + +/*! + * Compare two Date objects by asserting that + * the time values are equal using `saveValue`. + * + * @param {Date} a + * @param {Date} b + * @return {Boolean} result + */ + +function dateEqual(a, b) { + if ('date' !== type(b)) return false; + return sameValue(a.getTime(), b.getTime()); +} + +/*! + * Compare two regular expressions by converting them + * to string and checking for `sameValue`. + * + * @param {RegExp} a + * @param {RegExp} b + * @return {Boolean} result + */ + +function regexpEqual(a, b) { + if ('regexp' !== type(b)) return false; + return sameValue(a.toString(), b.toString()); +} + +/*! + * Assert deep equality of two `arguments` objects. + * Unfortunately, these must be sliced to arrays + * prior to test to ensure no bad behavior. + * + * @param {Arguments} a + * @param {Arguments} b + * @param {Array} memoize (optional) + * @return {Boolean} result + */ + +function argumentsEqual(a, b, m) { + if ('arguments' !== type(b)) return false; + a = [].slice.call(a); + b = [].slice.call(b); + return deepEqual(a, b, m); +} + +/*! + * Get enumerable properties of a given object. + * + * @param {Object} a + * @return {Array} property names + */ + +function enumerable(a) { + var res = []; + for (var key in a) res.push(key); + return res; +} + +/*! + * Simple equality for flat iterable objects + * such as Arrays or Node.js buffers. + * + * @param {Iterable} a + * @param {Iterable} b + * @return {Boolean} result + */ + +function iterableEqual(a, b) { + if (a.length !== b.length) return false; + + var i = 0; + var match = true; + + for (; i < a.length; i++) { + if (a[i] !== b[i]) { + match = false; + break; + } + } + + return match; +} + +/*! + * Extension to `iterableEqual` specifically + * for Node.js Buffers. + * + * @param {Buffer} a + * @param {Mixed} b + * @return {Boolean} result + */ + +function bufferEqual(a, b) { + if (!Buffer.isBuffer(b)) return false; + return iterableEqual(a, b); +} + +/*! + * Block for `objectEqual` ensuring non-existing + * values don't get in. + * + * @param {Mixed} object + * @return {Boolean} result + */ + +function isValue(a) { + return a !== null && a !== undefined; +} + +/*! + * Recursively check the equality of two objects. + * Once basic sameness has been established it will + * defer to `deepEqual` for each enumerable key + * in the object. + * + * @param {Mixed} a + * @param {Mixed} b + * @return {Boolean} result + */ + +function objectEqual(a, b, m) { + if (!isValue(a) || !isValue(b)) { + return false; + } + + if (a.prototype !== b.prototype) { + return false; + } + + var i; + if (m) { + for (i = 0; i < m.length; i++) { + if ((m[i][0] === a && m[i][1] === b) + || (m[i][0] === b && m[i][1] === a)) { + return true; + } + } + } else { + m = []; + } + + try { + var ka = enumerable(a); + var kb = enumerable(b); + } catch (ex) { + return false; + } + + ka.sort(); + kb.sort(); + + if (!iterableEqual(ka, kb)) { + return false; + } + + m.push([ a, b ]); + + var key; + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key], m)) { + return false; + } + } + + return true; +} + +},{"buffer":undefined,"type-detect":33}],33:[function(require,module,exports){ +module.exports = require('./lib/type'); + +},{"./lib/type":34}],34:[function(require,module,exports){ +/*! + * type-detect + * Copyright(c) 2013 jake luer + * MIT Licensed + */ + +/*! + * Primary Exports + */ + +var exports = module.exports = getType; + +/*! + * Detectable javascript natives + */ + +var natives = { + '[object Array]': 'array' + , '[object RegExp]': 'regexp' + , '[object Function]': 'function' + , '[object Arguments]': 'arguments' + , '[object Date]': 'date' +}; + +/** + * ### typeOf (obj) + * + * Use several different techniques to determine + * the type of object being tested. + * + * + * @param {Mixed} object + * @return {String} object type + * @api public + */ + +function getType (obj) { + var str = Object.prototype.toString.call(obj); + if (natives[str]) return natives[str]; + if (obj === null) return 'null'; + if (obj === undefined) return 'undefined'; + if (obj === Object(obj)) return 'object'; + return typeof obj; +} + +exports.Library = Library; + +/** + * ### Library + * + * Create a repository for custom type detection. + * + * ```js + * var lib = new type.Library; + * ``` + * + */ + +function Library () { + this.tests = {}; +} + +/** + * #### .of (obj) + * + * Expose replacement `typeof` detection to the library. + * + * ```js + * if ('string' === lib.of('hello world')) { + * // ... + * } + * ``` + * + * @param {Mixed} object to test + * @return {String} type + */ + +Library.prototype.of = getType; + +/** + * #### .define (type, test) + * + * Add a test to for the `.test()` assertion. + * + * Can be defined as a regular expression: + * + * ```js + * lib.define('int', /^[0-9]+$/); + * ``` + * + * ... or as a function: + * + * ```js + * lib.define('bln', function (obj) { + * if ('boolean' === lib.of(obj)) return true; + * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ]; + * if ('string' === lib.of(obj)) obj = obj.toLowerCase(); + * return !! ~blns.indexOf(obj); + * }); + * ``` + * + * @param {String} type + * @param {RegExp|Function} test + * @api public + */ + +Library.prototype.define = function (type, test) { + if (arguments.length === 1) return this.tests[type]; + this.tests[type] = test; + return this; +}; + +/** + * #### .test (obj, test) + * + * Assert that an object is of type. Will first + * check natives, and if that does not pass it will + * use the user defined custom tests. + * + * ```js + * assert(lib.test('1', 'int')); + * assert(lib.test('yes', 'bln')); + * ``` + * + * @param {Mixed} object + * @param {String} type + * @return {Boolean} result + * @api public + */ + +Library.prototype.test = function (obj, type) { + if (type === getType(obj)) return true; + var test = this.tests[type]; + + if (test && 'regexp' === getType(test)) { + return test.test(obj); + } else if (test && 'function' === getType(test)) { + return test(obj); + } else { + throw new ReferenceError('Type test "' + type + '" not defined or invalid.'); + } +}; + +},{}],35:[function(require,module,exports){ +arguments[4][33][0].apply(exports,arguments) +},{"./lib/type":36,"dup":33}],36:[function(require,module,exports){ +/*! + * type-detect + * Copyright(c) 2013 jake luer + * MIT Licensed + */ + +/*! + * Primary Exports + */ + +var exports = module.exports = getType; + +/** + * ### typeOf (obj) + * + * Use several different techniques to determine + * the type of object being tested. + * + * + * @param {Mixed} object + * @return {String} object type + * @api public + */ +var objectTypeRegexp = /^\[object (.*)\]$/; + +function getType(obj) { + var type = Object.prototype.toString.call(obj).match(objectTypeRegexp)[1].toLowerCase(); + // Let "new String('')" return 'object' + if (typeof Promise === 'function' && obj instanceof Promise) return 'promise'; + // PhantomJS has type "DOMWindow" for null + if (obj === null) return 'null'; + // PhantomJS has type "DOMWindow" for undefined + if (obj === undefined) return 'undefined'; + return type; +} + +exports.Library = Library; + +/** + * ### Library + * + * Create a repository for custom type detection. + * + * ```js + * var lib = new type.Library; + * ``` + * + */ + +function Library() { + if (!(this instanceof Library)) return new Library(); + this.tests = {}; +} + +/** + * #### .of (obj) + * + * Expose replacement `typeof` detection to the library. + * + * ```js + * if ('string' === lib.of('hello world')) { + * // ... + * } + * ``` + * + * @param {Mixed} object to test + * @return {String} type + */ + +Library.prototype.of = getType; + +/** + * #### .define (type, test) + * + * Add a test to for the `.test()` assertion. + * + * Can be defined as a regular expression: + * + * ```js + * lib.define('int', /^[0-9]+$/); + * ``` + * + * ... or as a function: + * + * ```js + * lib.define('bln', function (obj) { + * if ('boolean' === lib.of(obj)) return true; + * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ]; + * if ('string' === lib.of(obj)) obj = obj.toLowerCase(); + * return !! ~blns.indexOf(obj); + * }); + * ``` + * + * @param {String} type + * @param {RegExp|Function} test + * @api public + */ + +Library.prototype.define = function(type, test) { + if (arguments.length === 1) return this.tests[type]; + this.tests[type] = test; + return this; +}; + +/** + * #### .test (obj, test) + * + * Assert that an object is of type. Will first + * check natives, and if that does not pass it will + * use the user defined custom tests. + * + * ```js + * assert(lib.test('1', 'int')); + * assert(lib.test('yes', 'bln')); + * ``` + * + * @param {Mixed} object + * @param {String} type + * @return {Boolean} result + * @api public + */ + +Library.prototype.test = function(obj, type) { + if (type === getType(obj)) return true; + var test = this.tests[type]; + + if (test && 'regexp' === getType(test)) { + return test.test(obj); + } else if (test && 'function' === getType(test)) { + return test(obj); + } else { + throw new ReferenceError('Type test "' + type + '" not defined or invalid.'); + } +}; + +},{}]},{},[1])(1) +}); \ No newline at end of file diff --git a/public/vendor/mocha.css b/public/vendor/mocha.css new file mode 100644 index 0000000..3b82ae9 --- /dev/null +++ b/public/vendor/mocha.css @@ -0,0 +1,305 @@ +@charset "utf-8"; + +body { + margin:0; +} + +#mocha { + font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; + margin: 60px 50px; +} + +#mocha ul, +#mocha li { + margin: 0; + padding: 0; +} + +#mocha ul { + list-style: none; +} + +#mocha h1, +#mocha h2 { + margin: 0; +} + +#mocha h1 { + margin-top: 15px; + font-size: 1em; + font-weight: 200; +} + +#mocha h1 a { + text-decoration: none; + color: inherit; +} + +#mocha h1 a:hover { + text-decoration: underline; +} + +#mocha .suite .suite h1 { + margin-top: 0; + font-size: .8em; +} + +#mocha .hidden { + display: none; +} + +#mocha h2 { + font-size: 12px; + font-weight: normal; + cursor: pointer; +} + +#mocha .suite { + margin-left: 15px; +} + +#mocha .test { + margin-left: 15px; + overflow: hidden; +} + +#mocha .test.pending:hover h2::after { + content: '(pending)'; + font-family: arial, sans-serif; +} + +#mocha .test.pass.medium .duration { + background: #c09853; +} + +#mocha .test.pass.slow .duration { + background: #b94a48; +} + +#mocha .test.pass::before { + content: '✓'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #00d6b2; +} + +#mocha .test.pass .duration { + font-size: 9px; + margin-left: 5px; + padding: 2px 5px; + color: #fff; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} + +#mocha .test.pass.fast .duration { + display: none; +} + +#mocha .test.pending { + color: #0b97c4; +} + +#mocha .test.pending::before { + content: '◦'; + color: #0b97c4; +} + +#mocha .test.fail { + color: #c00; +} + +#mocha .test.fail pre { + color: black; +} + +#mocha .test.fail::before { + content: '✖'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #c00; +} + +#mocha .test pre.error { + color: #c00; + max-height: 300px; + overflow: auto; +} + +#mocha .test .html-error { + overflow: auto; + color: black; + line-height: 1.5; + display: block; + float: left; + clear: left; + font: 12px/1.5 monaco, monospace; + margin: 5px; + padding: 15px; + border: 1px solid #eee; + max-width: 85%; /*(1)*/ + max-width: calc(100% - 42px); /*(2)*/ + max-height: 300px; + word-wrap: break-word; + border-bottom-color: #ddd; + -webkit-border-radius: 3px; + -webkit-box-shadow: 0 1px 3px #eee; + -moz-border-radius: 3px; + -moz-box-shadow: 0 1px 3px #eee; + border-radius: 3px; +} + +#mocha .test .html-error pre.error { + border: none; + -webkit-border-radius: none; + -webkit-box-shadow: none; + -moz-border-radius: none; + -moz-box-shadow: none; + padding: 0; + margin: 0; + margin-top: 18px; + max-height: none; +} + +/** + * (1): approximate for browsers not supporting calc + * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border) + * ^^ seriously + */ +#mocha .test pre { + display: block; + float: left; + clear: left; + font: 12px/1.5 monaco, monospace; + margin: 5px; + padding: 15px; + border: 1px solid #eee; + max-width: 85%; /*(1)*/ + max-width: calc(100% - 42px); /*(2)*/ + word-wrap: break-word; + border-bottom-color: #ddd; + -webkit-border-radius: 3px; + -webkit-box-shadow: 0 1px 3px #eee; + -moz-border-radius: 3px; + -moz-box-shadow: 0 1px 3px #eee; + border-radius: 3px; +} + +#mocha .test h2 { + position: relative; +} + +#mocha .test a.replay { + position: absolute; + top: 3px; + right: 0; + text-decoration: none; + vertical-align: middle; + display: block; + width: 15px; + height: 15px; + line-height: 15px; + text-align: center; + background: #eee; + font-size: 15px; + -moz-border-radius: 15px; + border-radius: 15px; + -webkit-transition: opacity 200ms; + -moz-transition: opacity 200ms; + transition: opacity 200ms; + opacity: 0.3; + color: #888; +} + +#mocha .test:hover a.replay { + opacity: 1; +} + +#mocha-report.pass .test.fail { + display: none; +} + +#mocha-report.fail .test.pass { + display: none; +} + +#mocha-report.pending .test.pass, +#mocha-report.pending .test.fail { + display: none; +} +#mocha-report.pending .test.pass.pending { + display: block; +} + +#mocha-error { + color: #c00; + font-size: 1.5em; + font-weight: 100; + letter-spacing: 1px; +} + +#mocha-stats { + position: fixed; + top: 15px; + right: 10px; + font-size: 12px; + margin: 0; + color: #888; + z-index: 1; +} + +#mocha-stats .progress { + float: right; + padding-top: 0; +} + +#mocha-stats em { + color: black; +} + +#mocha-stats a { + text-decoration: none; + color: inherit; +} + +#mocha-stats a:hover { + border-bottom: 1px solid #eee; +} + +#mocha-stats li { + display: inline-block; + margin: 0 5px; + list-style: none; + padding-top: 11px; +} + +#mocha-stats canvas { + width: 40px; + height: 40px; +} + +#mocha code .comment { color: #ddd; } +#mocha code .init { color: #2f6fad; } +#mocha code .string { color: #5890ad; } +#mocha code .keyword { color: #8a6343; } +#mocha code .number { color: #2f6fad; } + +@media screen and (max-device-width: 480px) { + #mocha { + margin: 60px 0px; + } + + #mocha #stats { + position: absolute; + } +} diff --git a/public/vendor/mocha.js b/public/vendor/mocha.js new file mode 100644 index 0000000..1956197 --- /dev/null +++ b/public/vendor/mocha.js @@ -0,0 +1,12710 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) { + suites.shift(); + } + var suite = Suite.create(suites[0], title); + suite.file = file; + suites.unshift(suite); + return suite; + }; + + /** + * Exclusive test-case. + */ + + context.suite.only = function(title, fn) { + var suite = context.suite(title, fn); + mocha.grep(suite.fullTitle()); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.test = function(title, fn) { + var test = new Test(title, fn); + test.file = file; + suites[0].addTest(test); + return test; + }; + + /** + * Exclusive test-case. + */ + + context.test.only = function(title, fn) { + var test = context.test(title, fn); + var reString = '^' + escapeRe(test.fullTitle()) + '$'; + mocha.grep(new RegExp(reString)); + }; + + context.test.skip = common.test.skip; + context.test.retries = common.test.retries; + }); +}; + +},{"../suite":37,"../test":38,"./common":9,"escape-string-regexp":68}],13:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var Suite = require('../suite'); +var Test = require('../test'); +var escapeRe = require('escape-string-regexp'); + +/** + * TDD-style interface: + * + * suite('Array', function() { + * suite('#indexOf()', function() { + * suiteSetup(function() { + * + * }); + * + * test('should return -1 when not present', function() { + * + * }); + * + * test('should return the index when present', function() { + * + * }); + * + * suiteTeardown(function() { + * + * }); + * }); + * }); + * + * @param {Suite} suite Root suite. + */ +module.exports = function(suite) { + var suites = [suite]; + + suite.on('pre-require', function(context, file, mocha) { + var common = require('./common')(suites, context); + + context.setup = common.beforeEach; + context.teardown = common.afterEach; + context.suiteSetup = common.before; + context.suiteTeardown = common.after; + context.run = mocha.options.delay && common.runWithSuite(suite); + + /** + * Describe a "suite" with the given `title` and callback `fn` containing + * nested suites and/or tests. + */ + context.suite = function(title, fn) { + var suite = Suite.create(suites[0], title); + suite.file = file; + suites.unshift(suite); + fn.call(suite); + suites.shift(); + return suite; + }; + + /** + * Pending suite. + */ + context.suite.skip = function(title, fn) { + var suite = Suite.create(suites[0], title); + suite.pending = true; + suites.unshift(suite); + fn.call(suite); + suites.shift(); + }; + + /** + * Exclusive test-case. + */ + context.suite.only = function(title, fn) { + var suite = context.suite(title, fn); + mocha.grep(suite.fullTitle()); + }; + + /** + * Describe a specification or test-case with the given `title` and + * callback `fn` acting as a thunk. + */ + context.test = function(title, fn) { + var suite = suites[0]; + if (suite.pending) { + fn = null; + } + var test = new Test(title, fn); + test.file = file; + suite.addTest(test); + return test; + }; + + /** + * Exclusive test-case. + */ + + context.test.only = function(title, fn) { + var test = context.test(title, fn); + var reString = '^' + escapeRe(test.fullTitle()) + '$'; + mocha.grep(new RegExp(reString)); + }; + + context.test.skip = common.test.skip; + context.test.retries = common.test.retries; + }); +}; + +},{"../suite":37,"../test":38,"./common":9,"escape-string-regexp":68}],14:[function(require,module,exports){ +(function (process,global,__dirname){ +/*! + * mocha + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var escapeRe = require('escape-string-regexp'); +var path = require('path'); +var reporters = require('./reporters'); +var utils = require('./utils'); + +/** + * Expose `Mocha`. + */ + +exports = module.exports = Mocha; + +/** + * To require local UIs and reporters when running in node. + */ + +if (!process.browser) { + var cwd = process.cwd(); + module.paths.push(cwd, path.join(cwd, 'node_modules')); +} + +/** + * Expose internals. + */ + +exports.utils = utils; +exports.interfaces = require('./interfaces'); +exports.reporters = reporters; +exports.Runnable = require('./runnable'); +exports.Context = require('./context'); +exports.Runner = require('./runner'); +exports.Suite = require('./suite'); +exports.Hook = require('./hook'); +exports.Test = require('./test'); + +/** + * Return image `name` path. + * + * @api private + * @param {string} name + * @return {string} + */ +function image(name) { + return path.join(__dirname, '../images', name + '.png'); +} + +/** + * Set up mocha with `options`. + * + * Options: + * + * - `ui` name "bdd", "tdd", "exports" etc + * - `reporter` reporter instance, defaults to `mocha.reporters.spec` + * - `globals` array of accepted globals + * - `timeout` timeout in milliseconds + * - `retries` number of times to retry failed tests + * - `bail` bail on the first test failure + * - `slow` milliseconds to wait before considering a test slow + * - `ignoreLeaks` ignore global leaks + * - `fullTrace` display the full stack-trace on failing + * - `grep` string or regexp to filter tests with + * + * @param {Object} options + * @api public + */ +function Mocha(options) { + options = options || {}; + this.files = []; + this.options = options; + if (options.grep) { + this.grep(new RegExp(options.grep)); + } + if (options.fgrep) { + this.grep(options.fgrep); + } + this.suite = new exports.Suite('', new exports.Context()); + this.ui(options.ui); + this.bail(options.bail); + this.reporter(options.reporter, options.reporterOptions); + if (typeof options.timeout !== 'undefined' && options.timeout !== null) { + this.timeout(options.timeout); + } + if (typeof options.retries !== 'undefined' && options.retries !== null) { + this.retries(options.retries); + } + this.useColors(options.useColors); + if (options.enableTimeouts !== null) { + this.enableTimeouts(options.enableTimeouts); + } + if (options.slow) { + this.slow(options.slow); + } + + this.suite.on('pre-require', function(context) { + exports.afterEach = context.afterEach || context.teardown; + exports.after = context.after || context.suiteTeardown; + exports.beforeEach = context.beforeEach || context.setup; + exports.before = context.before || context.suiteSetup; + exports.describe = context.describe || context.suite; + exports.it = context.it || context.test; + exports.setup = context.setup || context.beforeEach; + exports.suiteSetup = context.suiteSetup || context.before; + exports.suiteTeardown = context.suiteTeardown || context.after; + exports.suite = context.suite || context.describe; + exports.teardown = context.teardown || context.afterEach; + exports.test = context.test || context.it; + exports.run = context.run; + }); +} + +/** + * Enable or disable bailing on the first failure. + * + * @api public + * @param {boolean} [bail] + */ +Mocha.prototype.bail = function(bail) { + if (!arguments.length) { + bail = true; + } + this.suite.bail(bail); + return this; +}; + +/** + * Add test `file`. + * + * @api public + * @param {string} file + */ +Mocha.prototype.addFile = function(file) { + this.files.push(file); + return this; +}; + +/** + * Set reporter to `reporter`, defaults to "spec". + * + * @param {String|Function} reporter name or constructor + * @param {Object} reporterOptions optional options + * @api public + * @param {string|Function} reporter name or constructor + * @param {Object} reporterOptions optional options + */ +Mocha.prototype.reporter = function(reporter, reporterOptions) { + if (typeof reporter === 'function') { + this._reporter = reporter; + } else { + reporter = reporter || 'spec'; + var _reporter; + // Try to load a built-in reporter. + if (reporters[reporter]) { + _reporter = reporters[reporter]; + } + // Try to load reporters from process.cwd() and node_modules + if (!_reporter) { + try { + _reporter = require(reporter); + } catch (err) { + err.message.indexOf('Cannot find module') !== -1 + ? console.warn('"' + reporter + '" reporter not found') + : console.warn('"' + reporter + '" reporter blew up with error:\n' + err.stack); + } + } + if (!_reporter && reporter === 'teamcity') { + console.warn('The Teamcity reporter was moved to a package named ' + + 'mocha-teamcity-reporter ' + + '(https://npmjs.org/package/mocha-teamcity-reporter).'); + } + if (!_reporter) { + throw new Error('invalid reporter "' + reporter + '"'); + } + this._reporter = _reporter; + } + this.options.reporterOptions = reporterOptions; + return this; +}; + +/** + * Set test UI `name`, defaults to "bdd". + * + * @api public + * @param {string} bdd + */ +Mocha.prototype.ui = function(name) { + name = name || 'bdd'; + this._ui = exports.interfaces[name]; + if (!this._ui) { + try { + this._ui = require(name); + } catch (err) { + throw new Error('invalid interface "' + name + '"'); + } + } + this._ui = this._ui(this.suite); + return this; +}; + +/** + * Load registered files. + * + * @api private + */ +Mocha.prototype.loadFiles = function(fn) { + var self = this; + var suite = this.suite; + this.files.forEach(function(file) { + file = path.resolve(file); + suite.emit('pre-require', global, file, self); + suite.emit('require', require(file), file, self); + suite.emit('post-require', global, file, self); + }); + fn && fn(); +}; + +/** + * Enable growl support. + * + * @api private + */ +Mocha.prototype._growl = function(runner, reporter) { + var notify = require('growl'); + + runner.on('end', function() { + var stats = reporter.stats; + if (stats.failures) { + var msg = stats.failures + ' of ' + runner.total + ' tests failed'; + notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); + } else { + notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { + name: 'mocha', + title: 'Passed', + image: image('ok') + }); + } + }); +}; + +/** + * Add regexp to grep, if `re` is a string it is escaped. + * + * @param {RegExp|String} re + * @return {Mocha} + * @api public + * @param {RegExp|string} re + * @return {Mocha} + */ +Mocha.prototype.grep = function(re) { + this.options.grep = typeof re === 'string' ? new RegExp(escapeRe(re)) : re; + return this; +}; + +/** + * Invert `.grep()` matches. + * + * @return {Mocha} + * @api public + */ +Mocha.prototype.invert = function() { + this.options.invert = true; + return this; +}; + +/** + * Ignore global leaks. + * + * @param {Boolean} ignore + * @return {Mocha} + * @api public + * @param {boolean} ignore + * @return {Mocha} + */ +Mocha.prototype.ignoreLeaks = function(ignore) { + this.options.ignoreLeaks = Boolean(ignore); + return this; +}; + +/** + * Enable global leak checking. + * + * @return {Mocha} + * @api public + */ +Mocha.prototype.checkLeaks = function() { + this.options.ignoreLeaks = false; + return this; +}; + +/** + * Display long stack-trace on failing + * + * @return {Mocha} + * @api public + */ +Mocha.prototype.fullTrace = function() { + this.options.fullStackTrace = true; + return this; +}; + +/** + * Enable growl support. + * + * @return {Mocha} + * @api public + */ +Mocha.prototype.growl = function() { + this.options.growl = true; + return this; +}; + +/** + * Ignore `globals` array or string. + * + * @param {Array|String} globals + * @return {Mocha} + * @api public + * @param {Array|string} globals + * @return {Mocha} + */ +Mocha.prototype.globals = function(globals) { + this.options.globals = (this.options.globals || []).concat(globals); + return this; +}; + +/** + * Emit color output. + * + * @param {Boolean} colors + * @return {Mocha} + * @api public + * @param {boolean} colors + * @return {Mocha} + */ +Mocha.prototype.useColors = function(colors) { + if (colors !== undefined) { + this.options.useColors = colors; + } + return this; +}; + +/** + * Use inline diffs rather than +/-. + * + * @param {Boolean} inlineDiffs + * @return {Mocha} + * @api public + * @param {boolean} inlineDiffs + * @return {Mocha} + */ +Mocha.prototype.useInlineDiffs = function(inlineDiffs) { + this.options.useInlineDiffs = inlineDiffs !== undefined && inlineDiffs; + return this; +}; + +/** + * Set the timeout in milliseconds. + * + * @param {Number} timeout + * @return {Mocha} + * @api public + * @param {number} timeout + * @return {Mocha} + */ +Mocha.prototype.timeout = function(timeout) { + this.suite.timeout(timeout); + return this; +}; + +/** + * Set the number of times to retry failed tests. + * + * @param {Number} retry times + * @return {Mocha} + * @api public + */ +Mocha.prototype.retries = function(n) { + this.suite.retries(n); + return this; +}; + +/** + * Set slowness threshold in milliseconds. + * + * @param {Number} slow + * @return {Mocha} + * @api public + * @param {number} slow + * @return {Mocha} + */ +Mocha.prototype.slow = function(slow) { + this.suite.slow(slow); + return this; +}; + +/** + * Enable timeouts. + * + * @param {Boolean} enabled + * @return {Mocha} + * @api public + * @param {boolean} enabled + * @return {Mocha} + */ +Mocha.prototype.enableTimeouts = function(enabled) { + this.suite.enableTimeouts(arguments.length && enabled !== undefined ? enabled : true); + return this; +}; + +/** + * Makes all tests async (accepting a callback) + * + * @return {Mocha} + * @api public + */ +Mocha.prototype.asyncOnly = function() { + this.options.asyncOnly = true; + return this; +}; + +/** + * Disable syntax highlighting (in browser). + * + * @api public + */ +Mocha.prototype.noHighlighting = function() { + this.options.noHighlighting = true; + return this; +}; + +/** + * Enable uncaught errors to propagate (in browser). + * + * @return {Mocha} + * @api public + */ +Mocha.prototype.allowUncaught = function() { + this.options.allowUncaught = true; + return this; +}; + +/** + * Delay root suite execution. + * @returns {Mocha} + */ +Mocha.prototype.delay = function delay() { + this.options.delay = true; + return this; +}; + +/** + * Run tests and invoke `fn()` when complete. + * + * @api public + * @param {Function} fn + * @return {Runner} + */ +Mocha.prototype.run = function(fn) { + if (this.files.length) { + this.loadFiles(); + } + var suite = this.suite; + var options = this.options; + options.files = this.files; + var runner = new exports.Runner(suite, options.delay); + var reporter = new this._reporter(runner, options); + runner.ignoreLeaks = options.ignoreLeaks !== false; + runner.fullStackTrace = options.fullStackTrace; + runner.asyncOnly = options.asyncOnly; + runner.allowUncaught = options.allowUncaught; + if (options.grep) { + runner.grep(options.grep, options.invert); + } + if (options.globals) { + runner.globals(options.globals); + } + if (options.growl) { + this._growl(runner, reporter); + } + if (options.useColors !== undefined) { + exports.reporters.Base.useColors = options.useColors; + } + exports.reporters.Base.inlineDiffs = options.useInlineDiffs; + + function done(failures) { + if (reporter.done) { + reporter.done(failures, fn); + } else { + fn && fn(failures); + } + } + + return runner.run(done); +}; + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},"/lib") +},{"./context":6,"./hook":7,"./interfaces":11,"./reporters":22,"./runnable":35,"./runner":36,"./suite":37,"./test":38,"./utils":39,"_process":51,"escape-string-regexp":68,"growl":69,"path":41}],15:[function(require,module,exports){ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @api public + * @param {string|number} val + * @param {Object} options + * @return {string|number} + */ +module.exports = function(val, options) { + options = options || {}; + if (typeof val === 'string') { + return parse(val); + } + // https://github.com/mochajs/mocha/pull/1035 + return options['long'] ? longFormat(val) : shortFormat(val); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @api private + * @param {string} str + * @return {number} + */ +function parse(str) { + var match = (/^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i).exec(str); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 's': + return n * s; + case 'ms': + return n; + default: + // No default case + } +} + +/** + * Short format for `ms`. + * + * @api private + * @param {number} ms + * @return {string} + */ +function shortFormat(ms) { + if (ms >= d) { + return Math.round(ms / d) + 'd'; + } + if (ms >= h) { + return Math.round(ms / h) + 'h'; + } + if (ms >= m) { + return Math.round(ms / m) + 'm'; + } + if (ms >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @api private + * @param {number} ms + * @return {string} + */ +function longFormat(ms) { + return plural(ms, d, 'day') + || plural(ms, h, 'hour') + || plural(ms, m, 'minute') + || plural(ms, s, 'second') + || ms + ' ms'; +} + +/** + * Pluralization helper. + * + * @api private + * @param {number} ms + * @param {number} n + * @param {string} name + */ +function plural(ms, n, name) { + if (ms < n) { + return; + } + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name; + } + return Math.ceil(ms / n) + ' ' + name + 's'; +} + +},{}],16:[function(require,module,exports){ + +/** + * Expose `Pending`. + */ + +module.exports = Pending; + +/** + * Initialize a new `Pending` error with the given message. + * + * @param {string} message + */ +function Pending(message) { + this.message = message; +} + +},{}],17:[function(require,module,exports){ +(function (process,global){ +/** + * Module dependencies. + */ + +var tty = require('tty'); +var diff = require('diff'); +var ms = require('../ms'); +var utils = require('../utils'); +var supportsColor = process.browser ? null : require('supports-color'); + +/** + * Expose `Base`. + */ + +exports = module.exports = Base; + +/** + * Save timer references to avoid Sinon interfering. + * See: https://github.com/mochajs/mocha/issues/237 + */ + +/* eslint-disable no-unused-vars, no-native-reassign */ +var Date = global.Date; +var setTimeout = global.setTimeout; +var setInterval = global.setInterval; +var clearTimeout = global.clearTimeout; +var clearInterval = global.clearInterval; +/* eslint-enable no-unused-vars, no-native-reassign */ + +/** + * Check if both stdio streams are associated with a tty. + */ + +var isatty = tty.isatty(1) && tty.isatty(2); + +/** + * Enable coloring by default, except in the browser interface. + */ + +exports.useColors = !process.browser && (supportsColor || (process.env.MOCHA_COLORS !== undefined)); + +/** + * Inline diffs instead of +/- + */ + +exports.inlineDiffs = false; + +/** + * Default color map. + */ + +exports.colors = { + pass: 90, + fail: 31, + 'bright pass': 92, + 'bright fail': 91, + 'bright yellow': 93, + pending: 36, + suite: 0, + 'error title': 0, + 'error message': 31, + 'error stack': 90, + checkmark: 32, + fast: 90, + medium: 33, + slow: 31, + green: 32, + light: 90, + 'diff gutter': 90, + 'diff added': 32, + 'diff removed': 31 +}; + +/** + * Default symbol map. + */ + +exports.symbols = { + ok: '✓', + err: '✖', + dot: '․' +}; + +// With node.js on Windows: use symbols available in terminal default fonts +if (process.platform === 'win32') { + exports.symbols.ok = '\u221A'; + exports.symbols.err = '\u00D7'; + exports.symbols.dot = '.'; +} + +/** + * Color `str` with the given `type`, + * allowing colors to be disabled, + * as well as user-defined color + * schemes. + * + * @param {string} type + * @param {string} str + * @return {string} + * @api private + */ +var color = exports.color = function(type, str) { + if (!exports.useColors) { + return String(str); + } + return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; +}; + +/** + * Expose term window size, with some defaults for when stderr is not a tty. + */ + +exports.window = { + width: 75 +}; + +if (isatty) { + exports.window.width = process.stdout.getWindowSize + ? process.stdout.getWindowSize(1)[0] + : tty.getWindowSize()[1]; +} + +/** + * Expose some basic cursor interactions that are common among reporters. + */ + +exports.cursor = { + hide: function() { + isatty && process.stdout.write('\u001b[?25l'); + }, + + show: function() { + isatty && process.stdout.write('\u001b[?25h'); + }, + + deleteLine: function() { + isatty && process.stdout.write('\u001b[2K'); + }, + + beginningOfLine: function() { + isatty && process.stdout.write('\u001b[0G'); + }, + + CR: function() { + if (isatty) { + exports.cursor.deleteLine(); + exports.cursor.beginningOfLine(); + } else { + process.stdout.write('\r'); + } + } +}; + +/** + * Outut the given `failures` as a list. + * + * @param {Array} failures + * @api public + */ + +exports.list = function(failures) { + console.log(); + failures.forEach(function(test, i) { + // format + var fmt = color('error title', ' %s) %s:\n') + + color('error message', ' %s') + + color('error stack', '\n%s\n'); + + // msg + var msg; + var err = test.err; + var message; + if (err.message) { + message = err.message; + } else if (typeof err.inspect === 'function') { + message = err.inspect() + ''; + } else { + message = ''; + } + var stack = err.stack || message; + var index = stack.indexOf(message); + var actual = err.actual; + var expected = err.expected; + var escape = true; + + if (index === -1) { + msg = message; + } else { + index += message.length; + msg = stack.slice(0, index); + // remove msg from stack + stack = stack.slice(index + 1); + } + + // uncaught + if (err.uncaught) { + msg = 'Uncaught ' + msg; + } + // explicitly show diff + if (err.showDiff !== false && sameType(actual, expected) && expected !== undefined) { + escape = false; + if (!(utils.isString(actual) && utils.isString(expected))) { + err.actual = actual = utils.stringify(actual); + err.expected = expected = utils.stringify(expected); + } + + fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n'); + var match = message.match(/^([^:]+): expected/); + msg = '\n ' + color('error message', match ? match[1] : msg); + + if (exports.inlineDiffs) { + msg += inlineDiff(err, escape); + } else { + msg += unifiedDiff(err, escape); + } + } + + // indent stack trace + stack = stack.replace(/^/gm, ' '); + + console.log(fmt, (i + 1), test.fullTitle(), msg, stack); + }); +}; + +/** + * Initialize a new `Base` reporter. + * + * All other reporters generally + * inherit from this reporter, providing + * stats such as test duration, number + * of tests passed / failed etc. + * + * @param {Runner} runner + * @api public + */ + +function Base(runner) { + var stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }; + var failures = this.failures = []; + + if (!runner) { + return; + } + this.runner = runner; + + runner.stats = stats; + + runner.on('start', function() { + stats.start = new Date(); + }); + + runner.on('suite', function(suite) { + stats.suites = stats.suites || 0; + suite.root || stats.suites++; + }); + + runner.on('test end', function() { + stats.tests = stats.tests || 0; + stats.tests++; + }); + + runner.on('pass', function(test) { + stats.passes = stats.passes || 0; + + if (test.duration > test.slow()) { + test.speed = 'slow'; + } else if (test.duration > test.slow() / 2) { + test.speed = 'medium'; + } else { + test.speed = 'fast'; + } + + stats.passes++; + }); + + runner.on('fail', function(test, err) { + stats.failures = stats.failures || 0; + stats.failures++; + test.err = err; + failures.push(test); + }); + + runner.on('end', function() { + stats.end = new Date(); + stats.duration = new Date() - stats.start; + }); + + runner.on('pending', function() { + stats.pending++; + }); +} + +/** + * Output common epilogue used by many of + * the bundled reporters. + * + * @api public + */ +Base.prototype.epilogue = function() { + var stats = this.stats; + var fmt; + + console.log(); + + // passes + fmt = color('bright pass', ' ') + + color('green', ' %d passing') + + color('light', ' (%s)'); + + console.log(fmt, + stats.passes || 0, + ms(stats.duration)); + + // pending + if (stats.pending) { + fmt = color('pending', ' ') + + color('pending', ' %d pending'); + + console.log(fmt, stats.pending); + } + + // failures + if (stats.failures) { + fmt = color('fail', ' %d failing'); + + console.log(fmt, stats.failures); + + Base.list(this.failures); + console.log(); + } + + console.log(); +}; + +/** + * Pad the given `str` to `len`. + * + * @api private + * @param {string} str + * @param {string} len + * @return {string} + */ +function pad(str, len) { + str = String(str); + return Array(len - str.length + 1).join(' ') + str; +} + +/** + * Returns an inline diff between 2 strings with coloured ANSI output + * + * @api private + * @param {Error} err with actual/expected + * @param {boolean} escape + * @return {string} Diff + */ +function inlineDiff(err, escape) { + var msg = errorDiff(err, 'WordsWithSpace', escape); + + // linenos + var lines = msg.split('\n'); + if (lines.length > 4) { + var width = String(lines.length).length; + msg = lines.map(function(str, i) { + return pad(++i, width) + ' |' + ' ' + str; + }).join('\n'); + } + + // legend + msg = '\n' + + color('diff removed', 'actual') + + ' ' + + color('diff added', 'expected') + + '\n\n' + + msg + + '\n'; + + // indent + msg = msg.replace(/^/gm, ' '); + return msg; +} + +/** + * Returns a unified diff between two strings. + * + * @api private + * @param {Error} err with actual/expected + * @param {boolean} escape + * @return {string} The diff. + */ +function unifiedDiff(err, escape) { + var indent = ' '; + function cleanUp(line) { + if (escape) { + line = escapeInvisibles(line); + } + if (line[0] === '+') { + return indent + colorLines('diff added', line); + } + if (line[0] === '-') { + return indent + colorLines('diff removed', line); + } + if (line.match(/\@\@/)) { + return null; + } + if (line.match(/\\ No newline/)) { + return null; + } + return indent + line; + } + function notBlank(line) { + return typeof line !== 'undefined' && line !== null; + } + var msg = diff.createPatch('string', err.actual, err.expected); + var lines = msg.split('\n').splice(4); + return '\n ' + + colorLines('diff added', '+ expected') + ' ' + + colorLines('diff removed', '- actual') + + '\n\n' + + lines.map(cleanUp).filter(notBlank).join('\n'); +} + +/** + * Return a character diff for `err`. + * + * @api private + * @param {Error} err + * @param {string} type + * @param {boolean} escape + * @return {string} + */ +function errorDiff(err, type, escape) { + var actual = escape ? escapeInvisibles(err.actual) : err.actual; + var expected = escape ? escapeInvisibles(err.expected) : err.expected; + return diff['diff' + type](actual, expected).map(function(str) { + if (str.added) { + return colorLines('diff added', str.value); + } + if (str.removed) { + return colorLines('diff removed', str.value); + } + return str.value; + }).join(''); +} + +/** + * Returns a string with all invisible characters in plain text + * + * @api private + * @param {string} line + * @return {string} + */ +function escapeInvisibles(line) { + return line.replace(/\t/g, '') + .replace(/\r/g, '') + .replace(/\n/g, '\n'); +} + +/** + * Color lines for `str`, using the color `name`. + * + * @api private + * @param {string} name + * @param {string} str + * @return {string} + */ +function colorLines(name, str) { + return str.split('\n').map(function(str) { + return color(name, str); + }).join('\n'); +} + +/** + * Object#toString reference. + */ +var objToString = Object.prototype.toString; + +/** + * Check that a / b have the same type. + * + * @api private + * @param {Object} a + * @param {Object} b + * @return {boolean} + */ +function sameType(a, b) { + return objToString.call(a) === objToString.call(b); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../ms":15,"../utils":39,"_process":51,"diff":67,"supports-color":41,"tty":5}],18:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var utils = require('../utils'); + +/** + * Expose `Doc`. + */ + +exports = module.exports = Doc; + +/** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ +function Doc(runner) { + Base.call(this, runner); + + var indents = 2; + + function indent() { + return Array(indents).join(' '); + } + + runner.on('suite', function(suite) { + if (suite.root) { + return; + } + ++indents; + console.log('%s
', indent()); + ++indents; + console.log('%s

%s

', indent(), utils.escape(suite.title)); + console.log('%s
', indent()); + }); + + runner.on('suite end', function(suite) { + if (suite.root) { + return; + } + console.log('%s
', indent()); + --indents; + console.log('%s
', indent()); + --indents; + }); + + runner.on('pass', function(test) { + console.log('%s
%s
', indent(), utils.escape(test.title)); + var code = utils.escape(utils.clean(test.body)); + console.log('%s
%s
', indent(), code); + }); + + runner.on('fail', function(test, err) { + console.log('%s
%s
', indent(), utils.escape(test.title)); + var code = utils.escape(utils.clean(test.fn.body)); + console.log('%s
%s
', indent(), code); + console.log('%s
%s
', indent(), utils.escape(err)); + }); +} + +},{"../utils":39,"./base":17}],19:[function(require,module,exports){ +(function (process){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var inherits = require('../utils').inherits; +var color = Base.color; + +/** + * Expose `Dot`. + */ + +exports = module.exports = Dot; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @api public + * @param {Runner} runner + */ +function Dot(runner) { + Base.call(this, runner); + + var self = this; + var width = Base.window.width * .75 | 0; + var n = -1; + + runner.on('start', function() { + process.stdout.write('\n'); + }); + + runner.on('pending', function() { + if (++n % width === 0) { + process.stdout.write('\n '); + } + process.stdout.write(color('pending', Base.symbols.dot)); + }); + + runner.on('pass', function(test) { + if (++n % width === 0) { + process.stdout.write('\n '); + } + if (test.speed === 'slow') { + process.stdout.write(color('bright yellow', Base.symbols.dot)); + } else { + process.stdout.write(color(test.speed, Base.symbols.dot)); + } + }); + + runner.on('fail', function() { + if (++n % width === 0) { + process.stdout.write('\n '); + } + process.stdout.write(color('fail', Base.symbols.dot)); + }); + + runner.on('end', function() { + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ +inherits(Dot, Base); + +}).call(this,require('_process')) +},{"../utils":39,"./base":17,"_process":51}],20:[function(require,module,exports){ +(function (process,__dirname){ +/** + * Module dependencies. + */ + +var JSONCov = require('./json-cov'); +var readFileSync = require('fs').readFileSync; +var join = require('path').join; + +/** + * Expose `HTMLCov`. + */ + +exports = module.exports = HTMLCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @api public + * @param {Runner} runner + */ +function HTMLCov(runner) { + var jade = require('jade'); + var file = join(__dirname, '/templates/coverage.jade'); + var str = readFileSync(file, 'utf8'); + var fn = jade.compile(str, { filename: file }); + var self = this; + + JSONCov.call(this, runner, false); + + runner.on('end', function() { + process.stdout.write(fn({ + cov: self.cov, + coverageClass: coverageClass + })); + }); +} + +/** + * Return coverage class for a given coverage percentage. + * + * @api private + * @param {number} coveragePctg + * @return {string} + */ +function coverageClass(coveragePctg) { + if (coveragePctg >= 75) { + return 'high'; + } + if (coveragePctg >= 50) { + return 'medium'; + } + if (coveragePctg >= 25) { + return 'low'; + } + return 'terrible'; +} + +}).call(this,require('_process'),"/lib/reporters") +},{"./json-cov":23,"_process":51,"fs":41,"jade":41,"path":41}],21:[function(require,module,exports){ +(function (global){ +/* eslint-env browser */ + +/** + * Module dependencies. + */ + +var Base = require('./base'); +var utils = require('../utils'); +var Progress = require('../browser/progress'); +var escapeRe = require('escape-string-regexp'); +var escape = utils.escape; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +/* eslint-disable no-unused-vars, no-native-reassign */ +var Date = global.Date; +var setTimeout = global.setTimeout; +var setInterval = global.setInterval; +var clearTimeout = global.clearTimeout; +var clearInterval = global.clearInterval; +/* eslint-enable no-unused-vars, no-native-reassign */ + +/** + * Expose `HTML`. + */ + +exports = module.exports = HTML; + +/** + * Stats template. + */ + +var statsTemplate = ''; + +/** + * Initialize a new `HTML` reporter. + * + * @api public + * @param {Runner} runner + */ +function HTML(runner) { + Base.call(this, runner); + + var self = this; + var stats = this.stats; + var stat = fragment(statsTemplate); + var items = stat.getElementsByTagName('li'); + var passes = items[1].getElementsByTagName('em')[0]; + var passesLink = items[1].getElementsByTagName('a')[0]; + var failures = items[2].getElementsByTagName('em')[0]; + var failuresLink = items[2].getElementsByTagName('a')[0]; + var duration = items[3].getElementsByTagName('em')[0]; + var canvas = stat.getElementsByTagName('canvas')[0]; + var report = fragment('
    '); + var stack = [report]; + var progress; + var ctx; + var root = document.getElementById('mocha'); + + if (canvas.getContext) { + var ratio = window.devicePixelRatio || 1; + canvas.style.width = canvas.width; + canvas.style.height = canvas.height; + canvas.width *= ratio; + canvas.height *= ratio; + ctx = canvas.getContext('2d'); + ctx.scale(ratio, ratio); + progress = new Progress(); + } + + if (!root) { + return error('#mocha div missing, add it to your document'); + } + + // pass toggle + on(passesLink, 'click', function() { + unhide(); + var name = (/pass/).test(report.className) ? '' : ' pass'; + report.className = report.className.replace(/fail|pass/g, '') + name; + if (report.className.trim()) { + hideSuitesWithout('test pass'); + } + }); + + // failure toggle + on(failuresLink, 'click', function() { + unhide(); + var name = (/fail/).test(report.className) ? '' : ' fail'; + report.className = report.className.replace(/fail|pass/g, '') + name; + if (report.className.trim()) { + hideSuitesWithout('test fail'); + } + }); + + root.appendChild(stat); + root.appendChild(report); + + if (progress) { + progress.size(40); + } + + runner.on('suite', function(suite) { + if (suite.root) { + return; + } + + // suite + var url = self.suiteURL(suite); + var el = fragment('
  • %s

  • ', url, escape(suite.title)); + + // container + stack[0].appendChild(el); + stack.unshift(document.createElement('ul')); + el.appendChild(stack[0]); + }); + + runner.on('suite end', function(suite) { + if (suite.root) { + return; + } + stack.shift(); + }); + + runner.on('fail', function(test) { + // For type = 'test' its possible that the test failed due to multiple + // done() calls. So report the issue here. + if (test.type === 'hook' + || test.type === 'test') { + runner.emit('test end', test); + } + }); + + runner.on('test end', function(test) { + // TODO: add to stats + var percent = stats.tests / this.total * 100 | 0; + if (progress) { + progress.update(percent).draw(ctx); + } + + // update stats + var ms = new Date() - stats.start; + text(passes, stats.passes); + text(failures, stats.failures); + text(duration, (ms / 1000).toFixed(2)); + + // test + var el; + if (test.state === 'passed') { + var url = self.testURL(test); + el = fragment('
  • %e%ems

  • ', test.speed, test.title, test.duration, url); + } else if (test.pending) { + el = fragment('
  • %e

  • ', test.title); + } else { + el = fragment('
  • %e

  • ', test.title, self.testURL(test)); + var stackString; // Note: Includes leading newline + var message = test.err.toString(); + + // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we + // check for the result of the stringifying. + if (message === '[object Error]') { + message = test.err.message; + } + + if (test.err.stack) { + var indexOfMessage = test.err.stack.indexOf(test.err.message); + if (indexOfMessage === -1) { + stackString = test.err.stack; + } else { + stackString = test.err.stack.substr(test.err.message.length + indexOfMessage); + } + } else if (test.err.sourceURL && test.err.line !== undefined) { + // Safari doesn't give you a stack. Let's at least provide a source line. + stackString = '\n(' + test.err.sourceURL + ':' + test.err.line + ')'; + } + + stackString = stackString || ''; + + if (test.err.htmlMessage && stackString) { + el.appendChild(fragment('
    %s\n
    %e
    ', test.err.htmlMessage, stackString)); + } else if (test.err.htmlMessage) { + el.appendChild(fragment('
    %s
    ', test.err.htmlMessage)); + } else { + el.appendChild(fragment('
    %e%e
    ', message, stackString)); + } + } + + // toggle code + // TODO: defer + if (!test.pending) { + var h2 = el.getElementsByTagName('h2')[0]; + + on(h2, 'click', function() { + pre.style.display = pre.style.display === 'none' ? 'block' : 'none'; + }); + + var pre = fragment('
    %e
    ', utils.clean(test.body)); + el.appendChild(pre); + pre.style.display = 'none'; + } + + // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack. + if (stack[0]) { + stack[0].appendChild(el); + } + }); +} + +/** + * Makes a URL, preserving querystring ("search") parameters. + * + * @param {string} s + * @return {string} A new URL. + */ +function makeUrl(s) { + var search = window.location.search; + + // Remove previous grep query parameter if present + if (search) { + search = search.replace(/[?&]grep=[^&\s]*/g, '').replace(/^&/, '?'); + } + + return window.location.pathname + (search ? search + '&' : '?') + 'grep=' + encodeURIComponent(escapeRe(s)); +} + +/** + * Provide suite URL. + * + * @param {Object} [suite] + */ +HTML.prototype.suiteURL = function(suite) { + return makeUrl(suite.fullTitle()); +}; + +/** + * Provide test URL. + * + * @param {Object} [test] + */ +HTML.prototype.testURL = function(test) { + return makeUrl(test.fullTitle()); +}; + +/** + * Display error `msg`. + * + * @param {string} msg + */ +function error(msg) { + document.body.appendChild(fragment('
    %s
    ', msg)); +} + +/** + * Return a DOM fragment from `html`. + * + * @param {string} html + */ +function fragment(html) { + var args = arguments; + var div = document.createElement('div'); + var i = 1; + + div.innerHTML = html.replace(/%([se])/g, function(_, type) { + switch (type) { + case 's': return String(args[i++]); + case 'e': return escape(args[i++]); + // no default + } + }); + + return div.firstChild; +} + +/** + * Check for suites that do not have elements + * with `classname`, and hide them. + * + * @param {text} classname + */ +function hideSuitesWithout(classname) { + var suites = document.getElementsByClassName('suite'); + for (var i = 0; i < suites.length; i++) { + var els = suites[i].getElementsByClassName(classname); + if (!els.length) { + suites[i].className += ' hidden'; + } + } +} + +/** + * Unhide .hidden suites. + */ +function unhide() { + var els = document.getElementsByClassName('suite hidden'); + for (var i = 0; i < els.length; ++i) { + els[i].className = els[i].className.replace('suite hidden', 'suite'); + } +} + +/** + * Set an element's text contents. + * + * @param {HTMLElement} el + * @param {string} contents + */ +function text(el, contents) { + if (el.textContent) { + el.textContent = contents; + } else { + el.innerText = contents; + } +} + +/** + * Listen on `event` with callback `fn`. + */ +function on(el, event, fn) { + if (el.addEventListener) { + el.addEventListener(event, fn, false); + } else { + el.attachEvent('on' + event, fn); + } +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../browser/progress":4,"../utils":39,"./base":17,"escape-string-regexp":68}],22:[function(require,module,exports){ +// Alias exports to a their normalized format Mocha#reporter to prevent a need +// for dynamic (try/catch) requires, which Browserify doesn't handle. +exports.Base = exports.base = require('./base'); +exports.Dot = exports.dot = require('./dot'); +exports.Doc = exports.doc = require('./doc'); +exports.TAP = exports.tap = require('./tap'); +exports.JSON = exports.json = require('./json'); +exports.HTML = exports.html = require('./html'); +exports.List = exports.list = require('./list'); +exports.Min = exports.min = require('./min'); +exports.Spec = exports.spec = require('./spec'); +exports.Nyan = exports.nyan = require('./nyan'); +exports.XUnit = exports.xunit = require('./xunit'); +exports.Markdown = exports.markdown = require('./markdown'); +exports.Progress = exports.progress = require('./progress'); +exports.Landing = exports.landing = require('./landing'); +exports.JSONCov = exports['json-cov'] = require('./json-cov'); +exports.HTMLCov = exports['html-cov'] = require('./html-cov'); +exports.JSONStream = exports['json-stream'] = require('./json-stream'); + +},{"./base":17,"./doc":18,"./dot":19,"./html":21,"./html-cov":20,"./json":25,"./json-cov":23,"./json-stream":24,"./landing":26,"./list":27,"./markdown":28,"./min":29,"./nyan":30,"./progress":31,"./spec":32,"./tap":33,"./xunit":34}],23:[function(require,module,exports){ +(function (process,global){ +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `JSONCov`. + */ + +exports = module.exports = JSONCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @api public + * @param {Runner} runner + * @param {boolean} output + */ +function JSONCov(runner, output) { + Base.call(this, runner); + + output = arguments.length === 1 || output; + var self = this; + var tests = []; + var failures = []; + var passes = []; + + runner.on('test end', function(test) { + tests.push(test); + }); + + runner.on('pass', function(test) { + passes.push(test); + }); + + runner.on('fail', function(test) { + failures.push(test); + }); + + runner.on('end', function() { + var cov = global._$jscoverage || {}; + var result = self.cov = map(cov); + result.stats = self.stats; + result.tests = tests.map(clean); + result.failures = failures.map(clean); + result.passes = passes.map(clean); + if (!output) { + return; + } + process.stdout.write(JSON.stringify(result, null, 2)); + }); +} + +/** + * Map jscoverage data to a JSON structure + * suitable for reporting. + * + * @api private + * @param {Object} cov + * @return {Object} + */ + +function map(cov) { + var ret = { + instrumentation: 'node-jscoverage', + sloc: 0, + hits: 0, + misses: 0, + coverage: 0, + files: [] + }; + + for (var filename in cov) { + if (Object.prototype.hasOwnProperty.call(cov, filename)) { + var data = coverage(filename, cov[filename]); + ret.files.push(data); + ret.hits += data.hits; + ret.misses += data.misses; + ret.sloc += data.sloc; + } + } + + ret.files.sort(function(a, b) { + return a.filename.localeCompare(b.filename); + }); + + if (ret.sloc > 0) { + ret.coverage = (ret.hits / ret.sloc) * 100; + } + + return ret; +} + +/** + * Map jscoverage data for a single source file + * to a JSON structure suitable for reporting. + * + * @api private + * @param {string} filename name of the source file + * @param {Object} data jscoverage coverage data + * @return {Object} + */ +function coverage(filename, data) { + var ret = { + filename: filename, + coverage: 0, + hits: 0, + misses: 0, + sloc: 0, + source: {} + }; + + data.source.forEach(function(line, num) { + num++; + + if (data[num] === 0) { + ret.misses++; + ret.sloc++; + } else if (data[num] !== undefined) { + ret.hits++; + ret.sloc++; + } + + ret.source[num] = { + source: line, + coverage: data[num] === undefined ? '' : data[num] + }; + }); + + ret.coverage = ret.hits / ret.sloc * 100; + + return ret; +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @api private + * @param {Object} test + * @return {Object} + */ +function clean(test) { + return { + duration: test.duration, + currentRetry: test.currentRetry(), + fullTitle: test.fullTitle(), + title: test.title + }; +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./base":17,"_process":51}],24:[function(require,module,exports){ +(function (process){ +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @api public + * @param {Runner} runner + */ +function List(runner) { + Base.call(this, runner); + + var self = this; + var total = runner.total; + + runner.on('start', function() { + console.log(JSON.stringify(['start', { total: total }])); + }); + + runner.on('pass', function(test) { + console.log(JSON.stringify(['pass', clean(test)])); + }); + + runner.on('fail', function(test, err) { + test = clean(test); + test.err = err.message; + test.stack = err.stack || null; + console.log(JSON.stringify(['fail', test])); + }); + + runner.on('end', function() { + process.stdout.write(JSON.stringify(['end', self.stats])); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @api private + * @param {Object} test + * @return {Object} + */ +function clean(test) { + return { + title: test.title, + fullTitle: test.fullTitle(), + duration: test.duration, + currentRetry: test.currentRetry() + }; +} + +}).call(this,require('_process')) +},{"./base":17,"_process":51}],25:[function(require,module,exports){ +(function (process){ +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `JSON`. + */ + +exports = module.exports = JSONReporter; + +/** + * Initialize a new `JSON` reporter. + * + * @api public + * @param {Runner} runner + */ +function JSONReporter(runner) { + Base.call(this, runner); + + var self = this; + var tests = []; + var pending = []; + var failures = []; + var passes = []; + + runner.on('test end', function(test) { + tests.push(test); + }); + + runner.on('pass', function(test) { + passes.push(test); + }); + + runner.on('fail', function(test) { + failures.push(test); + }); + + runner.on('pending', function(test) { + pending.push(test); + }); + + runner.on('end', function() { + var obj = { + stats: self.stats, + tests: tests.map(clean), + pending: pending.map(clean), + failures: failures.map(clean), + passes: passes.map(clean) + }; + + runner.testResults = obj; + + process.stdout.write(JSON.stringify(obj, null, 2)); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @api private + * @param {Object} test + * @return {Object} + */ +function clean(test) { + return { + title: test.title, + fullTitle: test.fullTitle(), + duration: test.duration, + currentRetry: test.currentRetry(), + err: errorJSON(test.err || {}) + }; +} + +/** + * Transform `error` into a JSON object. + * + * @api private + * @param {Error} err + * @return {Object} + */ +function errorJSON(err) { + var res = {}; + Object.getOwnPropertyNames(err).forEach(function(key) { + res[key] = err[key]; + }, err); + return res; +} + +}).call(this,require('_process')) +},{"./base":17,"_process":51}],26:[function(require,module,exports){ +(function (process){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var inherits = require('../utils').inherits; +var cursor = Base.cursor; +var color = Base.color; + +/** + * Expose `Landing`. + */ + +exports = module.exports = Landing; + +/** + * Airplane color. + */ + +Base.colors.plane = 0; + +/** + * Airplane crash color. + */ + +Base.colors['plane crash'] = 31; + +/** + * Runway color. + */ + +Base.colors.runway = 90; + +/** + * Initialize a new `Landing` reporter. + * + * @api public + * @param {Runner} runner + */ +function Landing(runner) { + Base.call(this, runner); + + var self = this; + var width = Base.window.width * .75 | 0; + var total = runner.total; + var stream = process.stdout; + var plane = color('plane', '✈'); + var crashed = -1; + var n = 0; + + function runway() { + var buf = Array(width).join('-'); + return ' ' + color('runway', buf); + } + + runner.on('start', function() { + stream.write('\n\n\n '); + cursor.hide(); + }); + + runner.on('test end', function(test) { + // check if the plane crashed + var col = crashed === -1 ? width * ++n / total | 0 : crashed; + + // show the crash + if (test.state === 'failed') { + plane = color('plane crash', '✈'); + crashed = col; + } + + // render landing strip + stream.write('\u001b[' + (width + 1) + 'D\u001b[2A'); + stream.write(runway()); + stream.write('\n '); + stream.write(color('runway', Array(col).join('⋅'))); + stream.write(plane); + stream.write(color('runway', Array(width - col).join('⋅') + '\n')); + stream.write(runway()); + stream.write('\u001b[0m'); + }); + + runner.on('end', function() { + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ +inherits(Landing, Base); + +}).call(this,require('_process')) +},{"../utils":39,"./base":17,"_process":51}],27:[function(require,module,exports){ +(function (process){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var inherits = require('../utils').inherits; +var color = Base.color; +var cursor = Base.cursor; + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @api public + * @param {Runner} runner + */ +function List(runner) { + Base.call(this, runner); + + var self = this; + var n = 0; + + runner.on('start', function() { + console.log(); + }); + + runner.on('test', function(test) { + process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); + }); + + runner.on('pending', function(test) { + var fmt = color('checkmark', ' -') + + color('pending', ' %s'); + console.log(fmt, test.fullTitle()); + }); + + runner.on('pass', function(test) { + var fmt = color('checkmark', ' ' + Base.symbols.dot) + + color('pass', ' %s: ') + + color(test.speed, '%dms'); + cursor.CR(); + console.log(fmt, test.fullTitle(), test.duration); + }); + + runner.on('fail', function(test) { + cursor.CR(); + console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ +inherits(List, Base); + +}).call(this,require('_process')) +},{"../utils":39,"./base":17,"_process":51}],28:[function(require,module,exports){ +(function (process){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var utils = require('../utils'); + +/** + * Constants + */ + +var SUITE_PREFIX = '$'; + +/** + * Expose `Markdown`. + */ + +exports = module.exports = Markdown; + +/** + * Initialize a new `Markdown` reporter. + * + * @api public + * @param {Runner} runner + */ +function Markdown(runner) { + Base.call(this, runner); + + var level = 0; + var buf = ''; + + function title(str) { + return Array(level).join('#') + ' ' + str; + } + + function mapTOC(suite, obj) { + var ret = obj; + var key = SUITE_PREFIX + suite.title; + + obj = obj[key] = obj[key] || { suite: suite }; + suite.suites.forEach(function(suite) { + mapTOC(suite, obj); + }); + + return ret; + } + + function stringifyTOC(obj, level) { + ++level; + var buf = ''; + var link; + for (var key in obj) { + if (key === 'suite') { + continue; + } + if (key !== SUITE_PREFIX) { + link = ' - [' + key.substring(1) + ']'; + link += '(#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; + buf += Array(level).join(' ') + link; + } + buf += stringifyTOC(obj[key], level); + } + return buf; + } + + function generateTOC(suite) { + var obj = mapTOC(suite, {}); + return stringifyTOC(obj, 0); + } + + generateTOC(runner.suite); + + runner.on('suite', function(suite) { + ++level; + var slug = utils.slug(suite.fullTitle()); + buf += '' + '\n'; + buf += title(suite.title) + '\n'; + }); + + runner.on('suite end', function() { + --level; + }); + + runner.on('pass', function(test) { + var code = utils.clean(test.body); + buf += test.title + '.\n'; + buf += '\n```js\n'; + buf += code + '\n'; + buf += '```\n\n'; + }); + + runner.on('end', function() { + process.stdout.write('# TOC\n'); + process.stdout.write(generateTOC(runner.suite)); + process.stdout.write(buf); + }); +} + +}).call(this,require('_process')) +},{"../utils":39,"./base":17,"_process":51}],29:[function(require,module,exports){ +(function (process){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var inherits = require('../utils').inherits; + +/** + * Expose `Min`. + */ + +exports = module.exports = Min; + +/** + * Initialize a new `Min` minimal test reporter (best used with --watch). + * + * @api public + * @param {Runner} runner + */ +function Min(runner) { + Base.call(this, runner); + + runner.on('start', function() { + // clear screen + process.stdout.write('\u001b[2J'); + // set cursor position + process.stdout.write('\u001b[1;3H'); + }); + + runner.on('end', this.epilogue.bind(this)); +} + +/** + * Inherit from `Base.prototype`. + */ +inherits(Min, Base); + +}).call(this,require('_process')) +},{"../utils":39,"./base":17,"_process":51}],30:[function(require,module,exports){ +(function (process){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var inherits = require('../utils').inherits; + +/** + * Expose `Dot`. + */ + +exports = module.exports = NyanCat; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @param {Runner} runner + * @api public + */ + +function NyanCat(runner) { + Base.call(this, runner); + + var self = this; + var width = Base.window.width * .75 | 0; + var nyanCatWidth = this.nyanCatWidth = 11; + + this.colorIndex = 0; + this.numberOfLines = 4; + this.rainbowColors = self.generateColors(); + this.scoreboardWidth = 5; + this.tick = 0; + this.trajectories = [[], [], [], []]; + this.trajectoryWidthMax = (width - nyanCatWidth); + + runner.on('start', function() { + Base.cursor.hide(); + self.draw(); + }); + + runner.on('pending', function() { + self.draw(); + }); + + runner.on('pass', function() { + self.draw(); + }); + + runner.on('fail', function() { + self.draw(); + }); + + runner.on('end', function() { + Base.cursor.show(); + for (var i = 0; i < self.numberOfLines; i++) { + write('\n'); + } + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ +inherits(NyanCat, Base); + +/** + * Draw the nyan cat + * + * @api private + */ + +NyanCat.prototype.draw = function() { + this.appendRainbow(); + this.drawScoreboard(); + this.drawRainbow(); + this.drawNyanCat(); + this.tick = !this.tick; +}; + +/** + * Draw the "scoreboard" showing the number + * of passes, failures and pending tests. + * + * @api private + */ + +NyanCat.prototype.drawScoreboard = function() { + var stats = this.stats; + + function draw(type, n) { + write(' '); + write(Base.color(type, n)); + write('\n'); + } + + draw('green', stats.passes); + draw('fail', stats.failures); + draw('pending', stats.pending); + write('\n'); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Append the rainbow. + * + * @api private + */ + +NyanCat.prototype.appendRainbow = function() { + var segment = this.tick ? '_' : '-'; + var rainbowified = this.rainbowify(segment); + + for (var index = 0; index < this.numberOfLines; index++) { + var trajectory = this.trajectories[index]; + if (trajectory.length >= this.trajectoryWidthMax) { + trajectory.shift(); + } + trajectory.push(rainbowified); + } +}; + +/** + * Draw the rainbow. + * + * @api private + */ + +NyanCat.prototype.drawRainbow = function() { + var self = this; + + this.trajectories.forEach(function(line) { + write('\u001b[' + self.scoreboardWidth + 'C'); + write(line.join('')); + write('\n'); + }); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Draw the nyan cat + * + * @api private + */ +NyanCat.prototype.drawNyanCat = function() { + var self = this; + var startWidth = this.scoreboardWidth + this.trajectories[0].length; + var dist = '\u001b[' + startWidth + 'C'; + var padding = ''; + + write(dist); + write('_,------,'); + write('\n'); + + write(dist); + padding = self.tick ? ' ' : ' '; + write('_|' + padding + '/\\_/\\ '); + write('\n'); + + write(dist); + padding = self.tick ? '_' : '__'; + var tail = self.tick ? '~' : '^'; + write(tail + '|' + padding + this.face() + ' '); + write('\n'); + + write(dist); + padding = self.tick ? ' ' : ' '; + write(padding + '"" "" '); + write('\n'); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Draw nyan cat face. + * + * @api private + * @return {string} + */ + +NyanCat.prototype.face = function() { + var stats = this.stats; + if (stats.failures) { + return '( x .x)'; + } else if (stats.pending) { + return '( o .o)'; + } else if (stats.passes) { + return '( ^ .^)'; + } + return '( - .-)'; +}; + +/** + * Move cursor up `n`. + * + * @api private + * @param {number} n + */ + +NyanCat.prototype.cursorUp = function(n) { + write('\u001b[' + n + 'A'); +}; + +/** + * Move cursor down `n`. + * + * @api private + * @param {number} n + */ + +NyanCat.prototype.cursorDown = function(n) { + write('\u001b[' + n + 'B'); +}; + +/** + * Generate rainbow colors. + * + * @api private + * @return {Array} + */ +NyanCat.prototype.generateColors = function() { + var colors = []; + + for (var i = 0; i < (6 * 7); i++) { + var pi3 = Math.floor(Math.PI / 3); + var n = (i * (1.0 / 6)); + var r = Math.floor(3 * Math.sin(n) + 3); + var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); + var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); + colors.push(36 * r + 6 * g + b + 16); + } + + return colors; +}; + +/** + * Apply rainbow to the given `str`. + * + * @api private + * @param {string} str + * @return {string} + */ +NyanCat.prototype.rainbowify = function(str) { + if (!Base.useColors) { + return str; + } + var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; + this.colorIndex += 1; + return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; +}; + +/** + * Stdout helper. + * + * @param {string} string A message to write to stdout. + */ +function write(string) { + process.stdout.write(string); +} + +}).call(this,require('_process')) +},{"../utils":39,"./base":17,"_process":51}],31:[function(require,module,exports){ +(function (process){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var inherits = require('../utils').inherits; +var color = Base.color; +var cursor = Base.cursor; + +/** + * Expose `Progress`. + */ + +exports = module.exports = Progress; + +/** + * General progress bar color. + */ + +Base.colors.progress = 90; + +/** + * Initialize a new `Progress` bar test reporter. + * + * @api public + * @param {Runner} runner + * @param {Object} options + */ +function Progress(runner, options) { + Base.call(this, runner); + + var self = this; + var width = Base.window.width * .50 | 0; + var total = runner.total; + var complete = 0; + var lastN = -1; + + // default chars + options = options || {}; + options.open = options.open || '['; + options.complete = options.complete || '▬'; + options.incomplete = options.incomplete || Base.symbols.dot; + options.close = options.close || ']'; + options.verbose = false; + + // tests started + runner.on('start', function() { + console.log(); + cursor.hide(); + }); + + // tests complete + runner.on('test end', function() { + complete++; + + var percent = complete / total; + var n = width * percent | 0; + var i = width - n; + + if (n === lastN && !options.verbose) { + // Don't re-render the line if it hasn't changed + return; + } + lastN = n; + + cursor.CR(); + process.stdout.write('\u001b[J'); + process.stdout.write(color('progress', ' ' + options.open)); + process.stdout.write(Array(n).join(options.complete)); + process.stdout.write(Array(i).join(options.incomplete)); + process.stdout.write(color('progress', options.close)); + if (options.verbose) { + process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); + } + }); + + // tests are complete, output some stats + // and the failures if any + runner.on('end', function() { + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ +inherits(Progress, Base); + +}).call(this,require('_process')) +},{"../utils":39,"./base":17,"_process":51}],32:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var inherits = require('../utils').inherits; +var color = Base.color; +var cursor = Base.cursor; + +/** + * Expose `Spec`. + */ + +exports = module.exports = Spec; + +/** + * Initialize a new `Spec` test reporter. + * + * @api public + * @param {Runner} runner + */ +function Spec(runner) { + Base.call(this, runner); + + var self = this; + var indents = 0; + var n = 0; + + function indent() { + return Array(indents).join(' '); + } + + runner.on('start', function() { + console.log(); + }); + + runner.on('suite', function(suite) { + ++indents; + console.log(color('suite', '%s%s'), indent(), suite.title); + }); + + runner.on('suite end', function() { + --indents; + if (indents === 1) { + console.log(); + } + }); + + runner.on('pending', function(test) { + var fmt = indent() + color('pending', ' - %s'); + console.log(fmt, test.title); + }); + + runner.on('pass', function(test) { + var fmt; + if (test.speed === 'fast') { + fmt = indent() + + color('checkmark', ' ' + Base.symbols.ok) + + color('pass', ' %s'); + cursor.CR(); + console.log(fmt, test.title); + } else { + fmt = indent() + + color('checkmark', ' ' + Base.symbols.ok) + + color('pass', ' %s') + + color(test.speed, ' (%dms)'); + cursor.CR(); + console.log(fmt, test.title, test.duration); + } + }); + + runner.on('fail', function(test) { + cursor.CR(); + console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ +inherits(Spec, Base); + +},{"../utils":39,"./base":17}],33:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `TAP`. + */ + +exports = module.exports = TAP; + +/** + * Initialize a new `TAP` reporter. + * + * @api public + * @param {Runner} runner + */ +function TAP(runner) { + Base.call(this, runner); + + var n = 1; + var passes = 0; + var failures = 0; + + runner.on('start', function() { + var total = runner.grepTotal(runner.suite); + console.log('%d..%d', 1, total); + }); + + runner.on('test end', function() { + ++n; + }); + + runner.on('pending', function(test) { + console.log('ok %d %s # SKIP -', n, title(test)); + }); + + runner.on('pass', function(test) { + passes++; + console.log('ok %d %s', n, title(test)); + }); + + runner.on('fail', function(test, err) { + failures++; + console.log('not ok %d %s', n, title(test)); + if (err.stack) { + console.log(err.stack.replace(/^/gm, ' ')); + } + }); + + runner.on('end', function() { + console.log('# tests ' + (passes + failures)); + console.log('# pass ' + passes); + console.log('# fail ' + failures); + }); +} + +/** + * Return a TAP-safe title of `test` + * + * @api private + * @param {Object} test + * @return {String} + */ +function title(test) { + return test.fullTitle().replace(/#/g, ''); +} + +},{"./base":17}],34:[function(require,module,exports){ +(function (process,global){ +/** + * Module dependencies. + */ + +var Base = require('./base'); +var utils = require('../utils'); +var inherits = utils.inherits; +var fs = require('fs'); +var escape = utils.escape; +var mkdirp = require('mkdirp'); +var path = require('path'); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +/* eslint-disable no-unused-vars, no-native-reassign */ +var Date = global.Date; +var setTimeout = global.setTimeout; +var setInterval = global.setInterval; +var clearTimeout = global.clearTimeout; +var clearInterval = global.clearInterval; +/* eslint-enable no-unused-vars, no-native-reassign */ + +/** + * Expose `XUnit`. + */ + +exports = module.exports = XUnit; + +/** + * Initialize a new `XUnit` reporter. + * + * @api public + * @param {Runner} runner + */ +function XUnit(runner, options) { + Base.call(this, runner); + + var stats = this.stats; + var tests = []; + var self = this; + + if (options.reporterOptions && options.reporterOptions.output) { + if (!fs.createWriteStream) { + throw new Error('file output not supported in browser'); + } + mkdirp.sync(path.dirname(options.reporterOptions.output)); + self.fileStream = fs.createWriteStream(options.reporterOptions.output); + } + + runner.on('pending', function(test) { + tests.push(test); + }); + + runner.on('pass', function(test) { + tests.push(test); + }); + + runner.on('fail', function(test) { + tests.push(test); + }); + + runner.on('end', function() { + self.write(tag('testsuite', { + name: 'Mocha Tests', + tests: stats.tests, + failures: stats.failures, + errors: stats.failures, + skipped: stats.tests - stats.failures - stats.passes, + timestamp: (new Date()).toUTCString(), + time: (stats.duration / 1000) || 0 + }, false)); + + tests.forEach(function(t) { + self.test(t); + }); + + self.write(''); + }); +} + +/** + * Inherit from `Base.prototype`. + */ +inherits(XUnit, Base); + +/** + * Override done to close the stream (if it's a file). + * + * @param failures + * @param {Function} fn + */ +XUnit.prototype.done = function(failures, fn) { + if (this.fileStream) { + this.fileStream.end(function() { + fn(failures); + }); + } else { + fn(failures); + } +}; + +/** + * Write out the given line. + * + * @param {string} line + */ +XUnit.prototype.write = function(line) { + if (this.fileStream) { + this.fileStream.write(line + '\n'); + } else if (typeof process === 'object' && process.stdout) { + process.stdout.write(line + '\n'); + } else { + console.log(line); + } +}; + +/** + * Output tag for the given `test.` + * + * @param {Test} test + */ +XUnit.prototype.test = function(test) { + var attrs = { + classname: test.parent.fullTitle(), + name: test.title, + time: (test.duration / 1000) || 0 + }; + + if (test.state === 'failed') { + var err = test.err; + this.write(tag('testcase', attrs, false, tag('failure', {}, false, cdata(escape(err.message) + '\n' + err.stack)))); + } else if (test.pending) { + this.write(tag('testcase', attrs, false, tag('skipped', {}, true))); + } else { + this.write(tag('testcase', attrs, true)); + } +}; + +/** + * HTML tag helper. + * + * @param name + * @param attrs + * @param close + * @param content + * @return {string} + */ +function tag(name, attrs, close, content) { + var end = close ? '/>' : '>'; + var pairs = []; + var tag; + + for (var key in attrs) { + if (Object.prototype.hasOwnProperty.call(attrs, key)) { + pairs.push(key + '="' + escape(attrs[key]) + '"'); + } + } + + tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; + if (content) { + tag += content + ''; +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../utils":39,"./base":17,"_process":51,"fs":41,"mkdirp":70,"path":41}],35:[function(require,module,exports){ +(function (global){ +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter; +var Pending = require('./pending'); +var debug = require('debug')('mocha:runnable'); +var milliseconds = require('./ms'); +var utils = require('./utils'); +var inherits = utils.inherits; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +/* eslint-disable no-unused-vars, no-native-reassign */ +var Date = global.Date; +var setTimeout = global.setTimeout; +var setInterval = global.setInterval; +var clearTimeout = global.clearTimeout; +var clearInterval = global.clearInterval; +/* eslint-enable no-unused-vars, no-native-reassign */ + +/** + * Object#toString(). + */ + +var toString = Object.prototype.toString; + +/** + * Expose `Runnable`. + */ + +module.exports = Runnable; + +/** + * Initialize a new `Runnable` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + * @param {string} title + * @param {Function} fn + */ +function Runnable(title, fn) { + this.title = title; + this.fn = fn; + this.async = fn && fn.length; + this.sync = !this.async; + this._timeout = 2000; + this._slow = 75; + this._enableTimeouts = true; + this.timedOut = false; + this._trace = new Error('done() called multiple times'); + this._retries = -1; + this._currentRetry = 0; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ +inherits(Runnable, EventEmitter); + +/** + * Set & get timeout `ms`. + * + * @api private + * @param {number|string} ms + * @return {Runnable|number} ms or Runnable instance. + */ +Runnable.prototype.timeout = function(ms) { + if (!arguments.length) { + return this._timeout; + } + if (ms === 0) { + this._enableTimeouts = false; + } + if (typeof ms === 'string') { + ms = milliseconds(ms); + } + debug('timeout %d', ms); + this._timeout = ms; + if (this.timer) { + this.resetTimeout(); + } + return this; +}; + +/** + * Set & get slow `ms`. + * + * @api private + * @param {number|string} ms + * @return {Runnable|number} ms or Runnable instance. + */ +Runnable.prototype.slow = function(ms) { + if (!arguments.length) { + return this._slow; + } + if (typeof ms === 'string') { + ms = milliseconds(ms); + } + debug('timeout %d', ms); + this._slow = ms; + return this; +}; + +/** + * Set and get whether timeout is `enabled`. + * + * @api private + * @param {boolean} enabled + * @return {Runnable|boolean} enabled or Runnable instance. + */ +Runnable.prototype.enableTimeouts = function(enabled) { + if (!arguments.length) { + return this._enableTimeouts; + } + debug('enableTimeouts %s', enabled); + this._enableTimeouts = enabled; + return this; +}; + +/** + * Halt and mark as pending. + * + * @api private + */ +Runnable.prototype.skip = function() { + throw new Pending(); +}; + +/** + * Set number of retries. + * + * @api private + */ +Runnable.prototype.retries = function(n) { + if (!arguments.length) { + return this._retries; + } + this._retries = n; +}; + +/** + * Get current retry + * + * @api private + */ +Runnable.prototype.currentRetry = function(n) { + if (!arguments.length) { + return this._currentRetry; + } + this._currentRetry = n; +}; + +/** + * Return the full title generated by recursively concatenating the parent's + * full title. + * + * @api public + * @return {string} + */ +Runnable.prototype.fullTitle = function() { + return this.parent.fullTitle() + ' ' + this.title; +}; + +/** + * Clear the timeout. + * + * @api private + */ +Runnable.prototype.clearTimeout = function() { + clearTimeout(this.timer); +}; + +/** + * Inspect the runnable void of private properties. + * + * @api private + * @return {string} + */ +Runnable.prototype.inspect = function() { + return JSON.stringify(this, function(key, val) { + if (key[0] === '_') { + return; + } + if (key === 'parent') { + return '#'; + } + if (key === 'ctx') { + return '#'; + } + return val; + }, 2); +}; + +/** + * Reset the timeout. + * + * @api private + */ +Runnable.prototype.resetTimeout = function() { + var self = this; + var ms = this.timeout() || 1e9; + + if (!this._enableTimeouts) { + return; + } + this.clearTimeout(); + this.timer = setTimeout(function() { + if (!self._enableTimeouts) { + return; + } + self.callback(new Error('timeout of ' + ms + 'ms exceeded. Ensure the done() callback is being called in this test.')); + self.timedOut = true; + }, ms); +}; + +/** + * Whitelist a list of globals for this test run. + * + * @api private + * @param {string[]} globals + */ +Runnable.prototype.globals = function(globals) { + if (!arguments.length) { + return this._allowedGlobals; + } + this._allowedGlobals = globals; +}; + +/** + * Run the test and invoke `fn(err)`. + * + * @param {Function} fn + * @api private + */ +Runnable.prototype.run = function(fn) { + var self = this; + var start = new Date(); + var ctx = this.ctx; + var finished; + var emitted; + + // Sometimes the ctx exists, but it is not runnable + if (ctx && ctx.runnable) { + ctx.runnable(this); + } + + // called multiple times + function multiple(err) { + if (emitted) { + return; + } + emitted = true; + self.emit('error', err || new Error('done() called multiple times; stacktrace may be inaccurate')); + } + + // finished + function done(err) { + var ms = self.timeout(); + if (self.timedOut) { + return; + } + if (finished) { + return multiple(err || self._trace); + } + + self.clearTimeout(); + self.duration = new Date() - start; + finished = true; + if (!err && self.duration > ms && self._enableTimeouts) { + err = new Error('timeout of ' + ms + 'ms exceeded. Ensure the done() callback is being called in this test.'); + } + fn(err); + } + + // for .resetTimeout() + this.callback = done; + + // explicit async with `done` argument + if (this.async) { + this.resetTimeout(); + + if (this.allowUncaught) { + return callFnAsync(this.fn); + } + try { + callFnAsync(this.fn); + } catch (err) { + done(utils.getError(err)); + } + return; + } + + if (this.allowUncaught) { + callFn(this.fn); + done(); + return; + } + + // sync or promise-returning + try { + if (this.pending) { + done(); + } else { + callFn(this.fn); + } + } catch (err) { + done(utils.getError(err)); + } + + function callFn(fn) { + var result = fn.call(ctx); + if (result && typeof result.then === 'function') { + self.resetTimeout(); + result + .then(function() { + done(); + // Return null so libraries like bluebird do not warn about + // subsequently constructed Promises. + return null; + }, + function(reason) { + done(reason || new Error('Promise rejected with no or falsy reason')); + }); + } else { + if (self.asyncOnly) { + return done(new Error('--async-only option in use without declaring `done()` or returning a promise')); + } + + done(); + } + } + + function callFnAsync(fn) { + fn.call(ctx, function(err) { + if (err instanceof Error || toString.call(err) === '[object Error]') { + return done(err); + } + if (err) { + if (Object.prototype.toString.call(err) === '[object Object]') { + return done(new Error('done() invoked with non-Error: ' + + JSON.stringify(err))); + } + return done(new Error('done() invoked with non-Error: ' + err)); + } + done(); + }); + } +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./ms":15,"./pending":16,"./utils":39,"debug":2,"events":3}],36:[function(require,module,exports){ +(function (process,global){ +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter; +var Pending = require('./pending'); +var utils = require('./utils'); +var inherits = utils.inherits; +var debug = require('debug')('mocha:runner'); +var Runnable = require('./runnable'); +var filter = utils.filter; +var indexOf = utils.indexOf; +var keys = utils.keys; +var stackFilter = utils.stackTraceFilter(); +var stringify = utils.stringify; +var type = utils.type; +var undefinedError = utils.undefinedError; +var isArray = utils.isArray; + +/** + * Non-enumerable globals. + */ + +var globals = [ + 'setTimeout', + 'clearTimeout', + 'setInterval', + 'clearInterval', + 'XMLHttpRequest', + 'Date', + 'setImmediate', + 'clearImmediate' +]; + +/** + * Expose `Runner`. + */ + +module.exports = Runner; + +/** + * Initialize a `Runner` for the given `suite`. + * + * Events: + * + * - `start` execution started + * - `end` execution complete + * - `suite` (suite) test suite execution started + * - `suite end` (suite) all tests (and sub-suites) have finished + * - `test` (test) test execution started + * - `test end` (test) test completed + * - `hook` (hook) hook execution started + * - `hook end` (hook) hook complete + * - `pass` (test) test passed + * - `fail` (test, err) test failed + * - `pending` (test) test pending + * + * @api public + * @param {Suite} suite Root suite + * @param {boolean} [delay] Whether or not to delay execution of root suite + * until ready. + */ +function Runner(suite, delay) { + var self = this; + this._globals = []; + this._abort = false; + this._delay = delay; + this.suite = suite; + this.started = false; + this.total = suite.total(); + this.failures = 0; + this.on('test end', function(test) { + self.checkGlobals(test); + }); + this.on('hook end', function(hook) { + self.checkGlobals(hook); + }); + this._defaultGrep = /.*/; + this.grep(this._defaultGrep); + this.globals(this.globalProps().concat(extraGlobals())); +} + +/** + * Wrapper for setImmediate, process.nextTick, or browser polyfill. + * + * @param {Function} fn + * @api private + */ +Runner.immediately = global.setImmediate || process.nextTick; + +/** + * Inherit from `EventEmitter.prototype`. + */ +inherits(Runner, EventEmitter); + +/** + * Run tests with full titles matching `re`. Updates runner.total + * with number of tests matched. + * + * @param {RegExp} re + * @param {Boolean} invert + * @return {Runner} for chaining + * @api public + * @param {RegExp} re + * @param {boolean} invert + * @return {Runner} Runner instance. + */ +Runner.prototype.grep = function(re, invert) { + debug('grep %s', re); + this._grep = re; + this._invert = invert; + this.total = this.grepTotal(this.suite); + return this; +}; + +/** + * Returns the number of tests matching the grep search for the + * given suite. + * + * @param {Suite} suite + * @return {Number} + * @api public + * @param {Suite} suite + * @return {number} + */ +Runner.prototype.grepTotal = function(suite) { + var self = this; + var total = 0; + + suite.eachTest(function(test) { + var match = self._grep.test(test.fullTitle()); + if (self._invert) { + match = !match; + } + if (match) { + total++; + } + }); + + return total; +}; + +/** + * Return a list of global properties. + * + * @return {Array} + * @api private + */ +Runner.prototype.globalProps = function() { + var props = keys(global); + + // non-enumerables + for (var i = 0; i < globals.length; ++i) { + if (~indexOf(props, globals[i])) { + continue; + } + props.push(globals[i]); + } + + return props; +}; + +/** + * Allow the given `arr` of globals. + * + * @param {Array} arr + * @return {Runner} for chaining + * @api public + * @param {Array} arr + * @return {Runner} Runner instance. + */ +Runner.prototype.globals = function(arr) { + if (!arguments.length) { + return this._globals; + } + debug('globals %j', arr); + this._globals = this._globals.concat(arr); + return this; +}; + +/** + * Check for global variable leaks. + * + * @api private + */ +Runner.prototype.checkGlobals = function(test) { + if (this.ignoreLeaks) { + return; + } + var ok = this._globals; + + var globals = this.globalProps(); + var leaks; + + if (test) { + ok = ok.concat(test._allowedGlobals || []); + } + + if (this.prevGlobalsLength === globals.length) { + return; + } + this.prevGlobalsLength = globals.length; + + leaks = filterLeaks(ok, globals); + this._globals = this._globals.concat(leaks); + + if (leaks.length > 1) { + this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); + } else if (leaks.length) { + this.fail(test, new Error('global leak detected: ' + leaks[0])); + } +}; + +/** + * Fail the given `test`. + * + * @api private + * @param {Test} test + * @param {Error} err + */ +Runner.prototype.fail = function(test, err) { + ++this.failures; + test.state = 'failed'; + + if (!(err instanceof Error || err && typeof err.message === 'string')) { + err = new Error('the ' + type(err) + ' ' + stringify(err) + ' was thrown, throw an Error :)'); + } + + err.stack = (this.fullStackTrace || !err.stack) + ? err.stack + : stackFilter(err.stack); + + this.emit('fail', test, err); +}; + +/** + * Fail the given `hook` with `err`. + * + * Hook failures work in the following pattern: + * - If bail, then exit + * - Failed `before` hook skips all tests in a suite and subsuites, + * but jumps to corresponding `after` hook + * - Failed `before each` hook skips remaining tests in a + * suite and jumps to corresponding `after each` hook, + * which is run only once + * - Failed `after` hook does not alter + * execution order + * - Failed `after each` hook skips remaining tests in a + * suite and subsuites, but executes other `after each` + * hooks + * + * @api private + * @param {Hook} hook + * @param {Error} err + */ +Runner.prototype.failHook = function(hook, err) { + if (hook.ctx && hook.ctx.currentTest) { + hook.originalTitle = hook.originalTitle || hook.title; + hook.title = hook.originalTitle + ' for "' + hook.ctx.currentTest.title + '"'; + } + + this.fail(hook, err); + if (this.suite.bail()) { + this.emit('end'); + } +}; + +/** + * Run hook `name` callbacks and then invoke `fn()`. + * + * @api private + * @param {string} name + * @param {Function} fn + */ + +Runner.prototype.hook = function(name, fn) { + var suite = this.suite; + var hooks = suite['_' + name]; + var self = this; + + function next(i) { + var hook = hooks[i]; + if (!hook) { + return fn(); + } + self.currentRunnable = hook; + + hook.ctx.currentTest = self.test; + + self.emit('hook', hook); + + if (!hook.listeners('error').length) { + hook.on('error', function(err) { + self.failHook(hook, err); + }); + } + + hook.run(function(err) { + var testError = hook.error(); + if (testError) { + self.fail(self.test, testError); + } + if (err) { + if (err instanceof Pending) { + suite.pending = true; + } else { + self.failHook(hook, err); + + // stop executing hooks, notify callee of hook err + return fn(err); + } + } + self.emit('hook end', hook); + delete hook.ctx.currentTest; + next(++i); + }); + } + + Runner.immediately(function() { + next(0); + }); +}; + +/** + * Run hook `name` for the given array of `suites` + * in order, and callback `fn(err, errSuite)`. + * + * @api private + * @param {string} name + * @param {Array} suites + * @param {Function} fn + */ +Runner.prototype.hooks = function(name, suites, fn) { + var self = this; + var orig = this.suite; + + function next(suite) { + self.suite = suite; + + if (!suite) { + self.suite = orig; + return fn(); + } + + self.hook(name, function(err) { + if (err) { + var errSuite = self.suite; + self.suite = orig; + return fn(err, errSuite); + } + + next(suites.pop()); + }); + } + + next(suites.pop()); +}; + +/** + * Run hooks from the top level down. + * + * @param {String} name + * @param {Function} fn + * @api private + */ +Runner.prototype.hookUp = function(name, fn) { + var suites = [this.suite].concat(this.parents()).reverse(); + this.hooks(name, suites, fn); +}; + +/** + * Run hooks from the bottom up. + * + * @param {String} name + * @param {Function} fn + * @api private + */ +Runner.prototype.hookDown = function(name, fn) { + var suites = [this.suite].concat(this.parents()); + this.hooks(name, suites, fn); +}; + +/** + * Return an array of parent Suites from + * closest to furthest. + * + * @return {Array} + * @api private + */ +Runner.prototype.parents = function() { + var suite = this.suite; + var suites = []; + while (suite.parent) { + suite = suite.parent; + suites.push(suite); + } + return suites; +}; + +/** + * Run the current test and callback `fn(err)`. + * + * @param {Function} fn + * @api private + */ +Runner.prototype.runTest = function(fn) { + var self = this; + var test = this.test; + + if (this.asyncOnly) { + test.asyncOnly = true; + } + + if (this.allowUncaught) { + test.allowUncaught = true; + return test.run(fn); + } + try { + test.on('error', function(err) { + self.fail(test, err); + }); + test.run(fn); + } catch (err) { + fn(err); + } +}; + +/** + * Run tests in the given `suite` and invoke the callback `fn()` when complete. + * + * @api private + * @param {Suite} suite + * @param {Function} fn + */ +Runner.prototype.runTests = function(suite, fn) { + var self = this; + var tests = suite.tests.slice(); + var test; + + function hookErr(_, errSuite, after) { + // before/after Each hook for errSuite failed: + var orig = self.suite; + + // for failed 'after each' hook start from errSuite parent, + // otherwise start from errSuite itself + self.suite = after ? errSuite.parent : errSuite; + + if (self.suite) { + // call hookUp afterEach + self.hookUp('afterEach', function(err2, errSuite2) { + self.suite = orig; + // some hooks may fail even now + if (err2) { + return hookErr(err2, errSuite2, true); + } + // report error suite + fn(errSuite); + }); + } else { + // there is no need calling other 'after each' hooks + self.suite = orig; + fn(errSuite); + } + } + + function next(err, errSuite) { + // if we bail after first err + if (self.failures && suite._bail) { + return fn(); + } + + if (self._abort) { + return fn(); + } + + if (err) { + return hookErr(err, errSuite, true); + } + + // next test + test = tests.shift(); + + // all done + if (!test) { + return fn(); + } + + // grep + var match = self._grep.test(test.fullTitle()); + if (self._invert) { + match = !match; + } + if (!match) { + // Run immediately only if we have defined a grep. When we + // define a grep — It can cause maximum callstack error if + // the grep is doing a large recursive loop by neglecting + // all tests. The run immediately function also comes with + // a performance cost. So we don't want to run immediately + // if we run the whole test suite, because running the whole + // test suite don't do any immediate recursive loops. Thus, + // allowing a JS runtime to breathe. + if (self._grep !== self._defaultGrep) { + Runner.immediately(next); + } else { + next(); + } + return; + } + + function parentPending(suite) { + return suite.pending || (suite.parent && parentPending(suite.parent)); + } + + // pending + if (test.pending || parentPending(test.parent)) { + self.emit('pending', test); + self.emit('test end', test); + return next(); + } + + // execute test and hook(s) + self.emit('test', self.test = test); + self.hookDown('beforeEach', function(err, errSuite) { + if (suite.pending) { + self.emit('pending', test); + self.emit('test end', test); + return next(); + } + if (err) { + return hookErr(err, errSuite, false); + } + self.currentRunnable = self.test; + self.runTest(function(err) { + test = self.test; + if (err) { + var retry = test.currentRetry(); + if (err instanceof Pending) { + test.pending = true; + self.emit('pending', test); + } else if (retry < test.retries()) { + var clonedTest = test.clone(); + clonedTest.currentRetry(retry + 1); + tests.unshift(clonedTest); + + // Early return + hook trigger so that it doesn't + // increment the count wrong + return self.hookUp('afterEach', next); + } else { + self.fail(test, err); + } + self.emit('test end', test); + + if (err instanceof Pending) { + return next(); + } + + return self.hookUp('afterEach', next); + } + + test.state = 'passed'; + self.emit('pass', test); + self.emit('test end', test); + self.hookUp('afterEach', next); + }); + }); + } + + this.next = next; + this.hookErr = hookErr; + next(); +}; + +/** + * Run the given `suite` and invoke the callback `fn()` when complete. + * + * @api private + * @param {Suite} suite + * @param {Function} fn + */ +Runner.prototype.runSuite = function(suite, fn) { + var i = 0; + var self = this; + var total = this.grepTotal(suite); + var afterAllHookCalled = false; + + debug('run suite %s', suite.fullTitle()); + + if (!total || (self.failures && suite._bail)) { + return fn(); + } + + this.emit('suite', this.suite = suite); + + function next(errSuite) { + if (errSuite) { + // current suite failed on a hook from errSuite + if (errSuite === suite) { + // if errSuite is current suite + // continue to the next sibling suite + return done(); + } + // errSuite is among the parents of current suite + // stop execution of errSuite and all sub-suites + return done(errSuite); + } + + if (self._abort) { + return done(); + } + + var curr = suite.suites[i++]; + if (!curr) { + return done(); + } + + // Avoid grep neglecting large number of tests causing a + // huge recursive loop and thus a maximum call stack error. + // See comment in `this.runTests()` for more information. + if (self._grep !== self._defaultGrep) { + Runner.immediately(function() { + self.runSuite(curr, next); + }); + } else { + self.runSuite(curr, next); + } + } + + function done(errSuite) { + self.suite = suite; + self.nextSuite = next; + + if (afterAllHookCalled) { + fn(errSuite); + } else { + // mark that the afterAll block has been called once + // and so can be skipped if there is an error in it. + afterAllHookCalled = true; + + // remove reference to test + delete self.test; + + self.hook('afterAll', function() { + self.emit('suite end', suite); + fn(errSuite); + }); + } + } + + this.nextSuite = next; + + this.hook('beforeAll', function(err) { + if (err) { + return done(); + } + self.runTests(suite, next); + }); +}; + +/** + * Handle uncaught exceptions. + * + * @param {Error} err + * @api private + */ +Runner.prototype.uncaught = function(err) { + if (err) { + debug('uncaught exception %s', err !== function() { + return this; + }.call(err) ? err : (err.message || err)); + } else { + debug('uncaught undefined exception'); + err = undefinedError(); + } + err.uncaught = true; + + var runnable = this.currentRunnable; + + if (!runnable) { + runnable = new Runnable('Uncaught error outside test suite'); + runnable.parent = this.suite; + + if (this.started) { + this.fail(runnable, err); + } else { + // Can't recover from this failure + this.emit('start'); + this.fail(runnable, err); + this.emit('end'); + } + + return; + } + + runnable.clearTimeout(); + + // Ignore errors if complete + if (runnable.state) { + return; + } + this.fail(runnable, err); + + // recover from test + if (runnable.type === 'test') { + this.emit('test end', runnable); + this.hookUp('afterEach', this.next); + return; + } + + // recover from hooks + if (runnable.type === 'hook') { + var errSuite = this.suite; + // if hook failure is in afterEach block + if (runnable.fullTitle().indexOf('after each') > -1) { + return this.hookErr(err, errSuite, true); + } + // if hook failure is in beforeEach block + if (runnable.fullTitle().indexOf('before each') > -1) { + return this.hookErr(err, errSuite, false); + } + // if hook failure is in after or before blocks + return this.nextSuite(errSuite); + } + + // bail + this.emit('end'); +}; + +/** + * Cleans up the references to all the deferred functions + * (before/after/beforeEach/afterEach) and tests of a Suite. + * These must be deleted otherwise a memory leak can happen, + * as those functions may reference variables from closures, + * thus those variables can never be garbage collected as long + * as the deferred functions exist. + * + * @param {Suite} suite + */ +function cleanSuiteReferences(suite) { + function cleanArrReferences(arr) { + for (var i = 0; i < arr.length; i++) { + delete arr[i].fn; + } + } + + if (isArray(suite._beforeAll)) { + cleanArrReferences(suite._beforeAll); + } + + if (isArray(suite._beforeEach)) { + cleanArrReferences(suite._beforeEach); + } + + if (isArray(suite._afterAll)) { + cleanArrReferences(suite._afterAll); + } + + if (isArray(suite._afterEach)) { + cleanArrReferences(suite._afterEach); + } + + for (var i = 0; i < suite.tests.length; i++) { + delete suite.tests[i].fn; + } +} + +/** + * Run the root suite and invoke `fn(failures)` + * on completion. + * + * @param {Function} fn + * @return {Runner} for chaining + * @api public + * @param {Function} fn + * @return {Runner} Runner instance. + */ +Runner.prototype.run = function(fn) { + var self = this; + var rootSuite = this.suite; + + fn = fn || function() {}; + + function uncaught(err) { + self.uncaught(err); + } + + function start() { + self.started = true; + self.emit('start'); + self.runSuite(rootSuite, function() { + debug('finished running'); + self.emit('end'); + }); + } + + debug('start'); + + // references cleanup to avoid memory leaks + this.on('suite end', cleanSuiteReferences); + + // callback + this.on('end', function() { + debug('end'); + process.removeListener('uncaughtException', uncaught); + fn(self.failures); + }); + + // uncaught exception + process.on('uncaughtException', uncaught); + + if (this._delay) { + // for reporters, I guess. + // might be nice to debounce some dots while we wait. + this.emit('waiting', rootSuite); + rootSuite.once('run', start); + } else { + start(); + } + + return this; +}; + +/** + * Cleanly abort execution. + * + * @api public + * @return {Runner} Runner instance. + */ +Runner.prototype.abort = function() { + debug('aborting'); + this._abort = true; + + return this; +}; + +/** + * Filter leaks with the given globals flagged as `ok`. + * + * @api private + * @param {Array} ok + * @param {Array} globals + * @return {Array} + */ +function filterLeaks(ok, globals) { + return filter(globals, function(key) { + // Firefox and Chrome exposes iframes as index inside the window object + if (/^d+/.test(key)) { + return false; + } + + // in firefox + // if runner runs in an iframe, this iframe's window.getInterface method not init at first + // it is assigned in some seconds + if (global.navigator && (/^getInterface/).test(key)) { + return false; + } + + // an iframe could be approached by window[iframeIndex] + // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak + if (global.navigator && (/^\d+/).test(key)) { + return false; + } + + // Opera and IE expose global variables for HTML element IDs (issue #243) + if (/^mocha-/.test(key)) { + return false; + } + + var matched = filter(ok, function(ok) { + if (~ok.indexOf('*')) { + return key.indexOf(ok.split('*')[0]) === 0; + } + return key === ok; + }); + return !matched.length && (!global.navigator || key !== 'onerror'); + }); +} + +/** + * Array of globals dependent on the environment. + * + * @return {Array} + * @api private + */ +function extraGlobals() { + if (typeof process === 'object' && typeof process.version === 'string') { + var parts = process.version.split('.'); + var nodeVersion = utils.reduce(parts, function(a, v) { + return a << 8 | v; + }); + + // 'errno' was renamed to process._errno in v0.9.11. + + if (nodeVersion < 0x00090B) { + return ['errno']; + } + } + + return []; +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./pending":16,"./runnable":35,"./utils":39,"_process":51,"debug":2,"events":3}],37:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter; +var Hook = require('./hook'); +var utils = require('./utils'); +var inherits = utils.inherits; +var debug = require('debug')('mocha:suite'); +var milliseconds = require('./ms'); + +/** + * Expose `Suite`. + */ + +exports = module.exports = Suite; + +/** + * Create a new `Suite` with the given `title` and parent `Suite`. When a suite + * with the same title is already present, that suite is returned to provide + * nicer reporter and more flexible meta-testing. + * + * @api public + * @param {Suite} parent + * @param {string} title + * @return {Suite} + */ +exports.create = function(parent, title) { + var suite = new Suite(title, parent.ctx); + suite.parent = parent; + if (parent.pending) { + suite.pending = true; + } + title = suite.fullTitle(); + parent.addSuite(suite); + return suite; +}; + +/** + * Initialize a new `Suite` with the given `title` and `ctx`. + * + * @api private + * @param {string} title + * @param {Context} parentContext + */ +function Suite(title, parentContext) { + this.title = title; + function Context() {} + Context.prototype = parentContext; + this.ctx = new Context(); + this.suites = []; + this.tests = []; + this.pending = false; + this._beforeEach = []; + this._beforeAll = []; + this._afterEach = []; + this._afterAll = []; + this.root = !title; + this._timeout = 2000; + this._enableTimeouts = true; + this._slow = 75; + this._bail = false; + this._retries = -1; + this.delayed = false; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ +inherits(Suite, EventEmitter); + +/** + * Return a clone of this `Suite`. + * + * @api private + * @return {Suite} + */ +Suite.prototype.clone = function() { + var suite = new Suite(this.title); + debug('clone'); + suite.ctx = this.ctx; + suite.timeout(this.timeout()); + suite.retries(this.retries()); + suite.enableTimeouts(this.enableTimeouts()); + suite.slow(this.slow()); + suite.bail(this.bail()); + return suite; +}; + +/** + * Set timeout `ms` or short-hand such as "2s". + * + * @api private + * @param {number|string} ms + * @return {Suite|number} for chaining + */ +Suite.prototype.timeout = function(ms) { + if (!arguments.length) { + return this._timeout; + } + if (ms.toString() === '0') { + this._enableTimeouts = false; + } + if (typeof ms === 'string') { + ms = milliseconds(ms); + } + debug('timeout %d', ms); + this._timeout = parseInt(ms, 10); + return this; +}; + +/** + * Set number of times to retry a failed test. + * + * @api private + * @param {number|string} n + * @return {Suite|number} for chaining + */ +Suite.prototype.retries = function(n) { + if (!arguments.length) { + return this._retries; + } + debug('retries %d', n); + this._retries = parseInt(n, 10) || 0; + return this; +}; + +/** + * Set timeout to `enabled`. + * + * @api private + * @param {boolean} enabled + * @return {Suite|boolean} self or enabled + */ +Suite.prototype.enableTimeouts = function(enabled) { + if (!arguments.length) { + return this._enableTimeouts; + } + debug('enableTimeouts %s', enabled); + this._enableTimeouts = enabled; + return this; +}; + +/** + * Set slow `ms` or short-hand such as "2s". + * + * @api private + * @param {number|string} ms + * @return {Suite|number} for chaining + */ +Suite.prototype.slow = function(ms) { + if (!arguments.length) { + return this._slow; + } + if (typeof ms === 'string') { + ms = milliseconds(ms); + } + debug('slow %d', ms); + this._slow = ms; + return this; +}; + +/** + * Sets whether to bail after first error. + * + * @api private + * @param {boolean} bail + * @return {Suite|number} for chaining + */ +Suite.prototype.bail = function(bail) { + if (!arguments.length) { + return this._bail; + } + debug('bail %s', bail); + this._bail = bail; + return this; +}; + +/** + * Run `fn(test[, done])` before running tests. + * + * @api private + * @param {string} title + * @param {Function} fn + * @return {Suite} for chaining + */ +Suite.prototype.beforeAll = function(title, fn) { + if (this.pending) { + return this; + } + if (typeof title === 'function') { + fn = title; + title = fn.name; + } + title = '"before all" hook' + (title ? ': ' + title : ''); + + var hook = new Hook(title, fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.retries(this.retries()); + hook.enableTimeouts(this.enableTimeouts()); + hook.slow(this.slow()); + hook.ctx = this.ctx; + this._beforeAll.push(hook); + this.emit('beforeAll', hook); + return this; +}; + +/** + * Run `fn(test[, done])` after running tests. + * + * @api private + * @param {string} title + * @param {Function} fn + * @return {Suite} for chaining + */ +Suite.prototype.afterAll = function(title, fn) { + if (this.pending) { + return this; + } + if (typeof title === 'function') { + fn = title; + title = fn.name; + } + title = '"after all" hook' + (title ? ': ' + title : ''); + + var hook = new Hook(title, fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.retries(this.retries()); + hook.enableTimeouts(this.enableTimeouts()); + hook.slow(this.slow()); + hook.ctx = this.ctx; + this._afterAll.push(hook); + this.emit('afterAll', hook); + return this; +}; + +/** + * Run `fn(test[, done])` before each test case. + * + * @api private + * @param {string} title + * @param {Function} fn + * @return {Suite} for chaining + */ +Suite.prototype.beforeEach = function(title, fn) { + if (this.pending) { + return this; + } + if (typeof title === 'function') { + fn = title; + title = fn.name; + } + title = '"before each" hook' + (title ? ': ' + title : ''); + + var hook = new Hook(title, fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.retries(this.retries()); + hook.enableTimeouts(this.enableTimeouts()); + hook.slow(this.slow()); + hook.ctx = this.ctx; + this._beforeEach.push(hook); + this.emit('beforeEach', hook); + return this; +}; + +/** + * Run `fn(test[, done])` after each test case. + * + * @api private + * @param {string} title + * @param {Function} fn + * @return {Suite} for chaining + */ +Suite.prototype.afterEach = function(title, fn) { + if (this.pending) { + return this; + } + if (typeof title === 'function') { + fn = title; + title = fn.name; + } + title = '"after each" hook' + (title ? ': ' + title : ''); + + var hook = new Hook(title, fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.retries(this.retries()); + hook.enableTimeouts(this.enableTimeouts()); + hook.slow(this.slow()); + hook.ctx = this.ctx; + this._afterEach.push(hook); + this.emit('afterEach', hook); + return this; +}; + +/** + * Add a test `suite`. + * + * @api private + * @param {Suite} suite + * @return {Suite} for chaining + */ +Suite.prototype.addSuite = function(suite) { + suite.parent = this; + suite.timeout(this.timeout()); + suite.retries(this.retries()); + suite.enableTimeouts(this.enableTimeouts()); + suite.slow(this.slow()); + suite.bail(this.bail()); + this.suites.push(suite); + this.emit('suite', suite); + return this; +}; + +/** + * Add a `test` to this suite. + * + * @api private + * @param {Test} test + * @return {Suite} for chaining + */ +Suite.prototype.addTest = function(test) { + test.parent = this; + test.timeout(this.timeout()); + test.retries(this.retries()); + test.enableTimeouts(this.enableTimeouts()); + test.slow(this.slow()); + test.ctx = this.ctx; + this.tests.push(test); + this.emit('test', test); + return this; +}; + +/** + * Return the full title generated by recursively concatenating the parent's + * full title. + * + * @api public + * @return {string} + */ +Suite.prototype.fullTitle = function() { + if (this.parent) { + var full = this.parent.fullTitle(); + if (full) { + return full + ' ' + this.title; + } + } + return this.title; +}; + +/** + * Return the total number of tests. + * + * @api public + * @return {number} + */ +Suite.prototype.total = function() { + return utils.reduce(this.suites, function(sum, suite) { + return sum + suite.total(); + }, 0) + this.tests.length; +}; + +/** + * Iterates through each suite recursively to find all tests. Applies a + * function in the format `fn(test)`. + * + * @api private + * @param {Function} fn + * @return {Suite} + */ +Suite.prototype.eachTest = function(fn) { + utils.forEach(this.tests, fn); + utils.forEach(this.suites, function(suite) { + suite.eachTest(fn); + }); + return this; +}; + +/** + * This will run the root suite if we happen to be running in delayed mode. + */ +Suite.prototype.run = function run() { + if (this.root) { + this.emit('run'); + } +}; + +},{"./hook":7,"./ms":15,"./utils":39,"debug":2,"events":3}],38:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var Runnable = require('./runnable'); +var inherits = require('./utils').inherits; + +/** + * Expose `Test`. + */ + +module.exports = Test; + +/** + * Initialize a new `Test` with the given `title` and callback `fn`. + * + * @api private + * @param {String} title + * @param {Function} fn + */ +function Test(title, fn) { + Runnable.call(this, title, fn); + this.pending = !fn; + this.type = 'test'; + this.body = (fn || '').toString(); +} + +/** + * Inherit from `Runnable.prototype`. + */ +inherits(Test, Runnable); + +Test.prototype.clone = function() { + var test = new Test(this.title, this.fn); + test.timeout(this.timeout()); + test.slow(this.slow()); + test.enableTimeouts(this.enableTimeouts()); + test.retries(this.retries()); + test.currentRetry(this.currentRetry()); + test.globals(this.globals()); + test.parent = this.parent; + test.file = this.file; + test.ctx = this.ctx; + return test; +}; + +},{"./runnable":35,"./utils":39}],39:[function(require,module,exports){ +(function (process,Buffer){ +/* eslint-env browser */ + +/** + * Module dependencies. + */ + +var basename = require('path').basename; +var debug = require('debug')('mocha:watch'); +var exists = require('fs').existsSync || require('path').existsSync; +var glob = require('glob'); +var join = require('path').join; +var readdirSync = require('fs').readdirSync; +var statSync = require('fs').statSync; +var watchFile = require('fs').watchFile; + +/** + * Ignored directories. + */ + +var ignore = ['node_modules', '.git']; + +exports.inherits = require('util').inherits; + +/** + * Escape special characters in the given string of html. + * + * @api private + * @param {string} html + * @return {string} + */ +exports.escape = function(html) { + return String(html) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +}; + +/** + * Array#forEach (<=IE8) + * + * @api private + * @param {Array} arr + * @param {Function} fn + * @param {Object} scope + */ +exports.forEach = function(arr, fn, scope) { + for (var i = 0, l = arr.length; i < l; i++) { + fn.call(scope, arr[i], i); + } +}; + +/** + * Test if the given obj is type of string. + * + * @api private + * @param {Object} obj + * @return {boolean} + */ +exports.isString = function(obj) { + return typeof obj === 'string'; +}; + +/** + * Array#map (<=IE8) + * + * @api private + * @param {Array} arr + * @param {Function} fn + * @param {Object} scope + * @return {Array} + */ +exports.map = function(arr, fn, scope) { + var result = []; + for (var i = 0, l = arr.length; i < l; i++) { + result.push(fn.call(scope, arr[i], i, arr)); + } + return result; +}; + +/** + * Array#indexOf (<=IE8) + * + * @api private + * @param {Array} arr + * @param {Object} obj to find index of + * @param {number} start + * @return {number} + */ +exports.indexOf = function(arr, obj, start) { + for (var i = start || 0, l = arr.length; i < l; i++) { + if (arr[i] === obj) { + return i; + } + } + return -1; +}; + +/** + * Array#reduce (<=IE8) + * + * @api private + * @param {Array} arr + * @param {Function} fn + * @param {Object} val Initial value. + * @return {*} + */ +exports.reduce = function(arr, fn, val) { + var rval = val; + + for (var i = 0, l = arr.length; i < l; i++) { + rval = fn(rval, arr[i], i, arr); + } + + return rval; +}; + +/** + * Array#filter (<=IE8) + * + * @api private + * @param {Array} arr + * @param {Function} fn + * @return {Array} + */ +exports.filter = function(arr, fn) { + var ret = []; + + for (var i = 0, l = arr.length; i < l; i++) { + var val = arr[i]; + if (fn(val, i, arr)) { + ret.push(val); + } + } + + return ret; +}; + +/** + * Object.keys (<=IE8) + * + * @api private + * @param {Object} obj + * @return {Array} keys + */ +exports.keys = typeof Object.keys === 'function' ? Object.keys : function(obj) { + var keys = []; + var has = Object.prototype.hasOwnProperty; // for `window` on <=IE8 + + for (var key in obj) { + if (has.call(obj, key)) { + keys.push(key); + } + } + + return keys; +}; + +/** + * Watch the given `files` for changes + * and invoke `fn(file)` on modification. + * + * @api private + * @param {Array} files + * @param {Function} fn + */ +exports.watch = function(files, fn) { + var options = { interval: 100 }; + files.forEach(function(file) { + debug('file %s', file); + watchFile(file, options, function(curr, prev) { + if (prev.mtime < curr.mtime) { + fn(file); + } + }); + }); +}; + +/** + * Array.isArray (<=IE8) + * + * @api private + * @param {Object} obj + * @return {Boolean} + */ +var isArray = typeof Array.isArray === 'function' ? Array.isArray : function(obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; +}; + +exports.isArray = isArray; + +/** + * Buffer.prototype.toJSON polyfill. + * + * @type {Function} + */ +if (typeof Buffer !== 'undefined' && Buffer.prototype) { + Buffer.prototype.toJSON = Buffer.prototype.toJSON || function() { + return Array.prototype.slice.call(this, 0); + }; +} + +/** + * Ignored files. + * + * @api private + * @param {string} path + * @return {boolean} + */ +function ignored(path) { + return !~ignore.indexOf(path); +} + +/** + * Lookup files in the given `dir`. + * + * @api private + * @param {string} dir + * @param {string[]} [ext=['.js']] + * @param {Array} [ret=[]] + * @return {Array} + */ +exports.files = function(dir, ext, ret) { + ret = ret || []; + ext = ext || ['js']; + + var re = new RegExp('\\.(' + ext.join('|') + ')$'); + + readdirSync(dir) + .filter(ignored) + .forEach(function(path) { + path = join(dir, path); + if (statSync(path).isDirectory()) { + exports.files(path, ext, ret); + } else if (path.match(re)) { + ret.push(path); + } + }); + + return ret; +}; + +/** + * Compute a slug from the given `str`. + * + * @api private + * @param {string} str + * @return {string} + */ +exports.slug = function(str) { + return str + .toLowerCase() + .replace(/ +/g, '-') + .replace(/[^-\w]/g, ''); +}; + +/** + * Strip the function definition from `str`, and re-indent for pre whitespace. + * + * @param {string} str + * @return {string} + */ +exports.clean = function(str) { + str = str + .replace(/\r\n?|[\n\u2028\u2029]/g, '\n').replace(/^\uFEFF/, '') + .replace(/^function *\(.*\)\s*\{|\(.*\) *=> *\{?/, '') + .replace(/\s+\}$/, ''); + + var spaces = str.match(/^\n?( *)/)[1].length; + var tabs = str.match(/^\n?(\t*)/)[1].length; + var re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm'); + + str = str.replace(re, ''); + + return exports.trim(str); +}; + +/** + * Trim the given `str`. + * + * @api private + * @param {string} str + * @return {string} + */ +exports.trim = function(str) { + return str.replace(/^\s+|\s+$/g, ''); +}; + +/** + * Parse the given `qs`. + * + * @api private + * @param {string} qs + * @return {Object} + */ +exports.parseQuery = function(qs) { + return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair) { + var i = pair.indexOf('='); + var key = pair.slice(0, i); + var val = pair.slice(++i); + + obj[key] = decodeURIComponent(val); + return obj; + }, {}); +}; + +/** + * Highlight the given string of `js`. + * + * @api private + * @param {string} js + * @return {string} + */ +function highlight(js) { + return js + .replace(//g, '>') + .replace(/\/\/(.*)/gm, '//$1') + .replace(/('.*?')/gm, '$1') + .replace(/(\d+\.\d+)/gm, '$1') + .replace(/(\d+)/gm, '$1') + .replace(/\bnew[ \t]+(\w+)/gm, 'new $1') + .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1'); +} + +/** + * Highlight the contents of tag `name`. + * + * @api private + * @param {string} name + */ +exports.highlightTags = function(name) { + var code = document.getElementById('mocha').getElementsByTagName(name); + for (var i = 0, len = code.length; i < len; ++i) { + code[i].innerHTML = highlight(code[i].innerHTML); + } +}; + +/** + * If a value could have properties, and has none, this function is called, + * which returns a string representation of the empty value. + * + * Functions w/ no properties return `'[Function]'` + * Arrays w/ length === 0 return `'[]'` + * Objects w/ no properties return `'{}'` + * All else: return result of `value.toString()` + * + * @api private + * @param {*} value The value to inspect. + * @param {string} [type] The type of the value, if known. + * @returns {string} + */ +function emptyRepresentation(value, type) { + type = type || exports.type(value); + + switch (type) { + case 'function': + return '[Function]'; + case 'object': + return '{}'; + case 'array': + return '[]'; + default: + return value.toString(); + } +} + +/** + * Takes some variable and asks `Object.prototype.toString()` what it thinks it + * is. + * + * @api private + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString + * @param {*} value The value to test. + * @returns {string} + * @example + * type({}) // 'object' + * type([]) // 'array' + * type(1) // 'number' + * type(false) // 'boolean' + * type(Infinity) // 'number' + * type(null) // 'null' + * type(new Date()) // 'date' + * type(/foo/) // 'regexp' + * type('type') // 'string' + * type(global) // 'global' + */ +exports.type = function type(value) { + if (value === undefined) { + return 'undefined'; + } else if (value === null) { + return 'null'; + } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + return 'buffer'; + } + return Object.prototype.toString.call(value) + .replace(/^\[.+\s(.+?)\]$/, '$1') + .toLowerCase(); +}; + +/** + * Stringify `value`. Different behavior depending on type of value: + * + * - If `value` is undefined or null, return `'[undefined]'` or `'[null]'`, respectively. + * - If `value` is not an object, function or array, return result of `value.toString()` wrapped in double-quotes. + * - If `value` is an *empty* object, function, or array, return result of function + * {@link emptyRepresentation}. + * - If `value` has properties, call {@link exports.canonicalize} on it, then return result of + * JSON.stringify(). + * + * @api private + * @see exports.type + * @param {*} value + * @return {string} + */ +exports.stringify = function(value) { + var type = exports.type(value); + + if (!~exports.indexOf(['object', 'array', 'function'], type)) { + if (type !== 'buffer') { + return jsonStringify(value); + } + var json = value.toJSON(); + // Based on the toJSON result + return jsonStringify(json.data && json.type ? json.data : json, 2) + .replace(/,(\n|$)/g, '$1'); + } + + for (var prop in value) { + if (Object.prototype.hasOwnProperty.call(value, prop)) { + return jsonStringify(exports.canonicalize(value), 2).replace(/,(\n|$)/g, '$1'); + } + } + + return emptyRepresentation(value, type); +}; + +/** + * like JSON.stringify but more sense. + * + * @api private + * @param {Object} object + * @param {number=} spaces + * @param {number=} depth + * @returns {*} + */ +function jsonStringify(object, spaces, depth) { + if (typeof spaces === 'undefined') { + // primitive types + return _stringify(object); + } + + depth = depth || 1; + var space = spaces * depth; + var str = isArray(object) ? '[' : '{'; + var end = isArray(object) ? ']' : '}'; + var length = object.length || exports.keys(object).length; + // `.repeat()` polyfill + function repeat(s, n) { + return new Array(n).join(s); + } + + function _stringify(val) { + switch (exports.type(val)) { + case 'null': + case 'undefined': + val = '[' + val + ']'; + break; + case 'array': + case 'object': + val = jsonStringify(val, spaces, depth + 1); + break; + case 'boolean': + case 'regexp': + case 'number': + val = val === 0 && (1 / val) === -Infinity // `-0` + ? '-0' + : val.toString(); + break; + case 'date': + var sDate = isNaN(val.getTime()) // Invalid date + ? val.toString() + : val.toISOString(); + val = '[Date: ' + sDate + ']'; + break; + case 'buffer': + var json = val.toJSON(); + // Based on the toJSON result + json = json.data && json.type ? json.data : json; + val = '[Buffer: ' + jsonStringify(json, 2, depth + 1) + ']'; + break; + default: + val = (val === '[Function]' || val === '[Circular]') + ? val + : JSON.stringify(val); // string + } + return val; + } + + for (var i in object) { + if (!object.hasOwnProperty(i)) { + continue; // not my business + } + --length; + str += '\n ' + repeat(' ', space) + + (isArray(object) ? '' : '"' + i + '": ') // key + + _stringify(object[i]) // value + + (length ? ',' : ''); // comma + } + + return str + // [], {} + + (str.length !== 1 ? '\n' + repeat(' ', --space) + end : end); +} + +/** + * Test if a value is a buffer. + * + * @api private + * @param {*} value The value to test. + * @return {boolean} True if `value` is a buffer, otherwise false + */ +exports.isBuffer = function(value) { + return typeof Buffer !== 'undefined' && Buffer.isBuffer(value); +}; + +/** + * Return a new Thing that has the keys in sorted order. Recursive. + * + * If the Thing... + * - has already been seen, return string `'[Circular]'` + * - is `undefined`, return string `'[undefined]'` + * - is `null`, return value `null` + * - is some other primitive, return the value + * - is not a primitive or an `Array`, `Object`, or `Function`, return the value of the Thing's `toString()` method + * - is a non-empty `Array`, `Object`, or `Function`, return the result of calling this function again. + * - is an empty `Array`, `Object`, or `Function`, return the result of calling `emptyRepresentation()` + * + * @api private + * @see {@link exports.stringify} + * @param {*} value Thing to inspect. May or may not have properties. + * @param {Array} [stack=[]] Stack of seen values + * @return {(Object|Array|Function|string|undefined)} + */ +exports.canonicalize = function(value, stack) { + var canonicalizedObj; + /* eslint-disable no-unused-vars */ + var prop; + /* eslint-enable no-unused-vars */ + var type = exports.type(value); + function withStack(value, fn) { + stack.push(value); + fn(); + stack.pop(); + } + + stack = stack || []; + + if (exports.indexOf(stack, value) !== -1) { + return '[Circular]'; + } + + switch (type) { + case 'undefined': + case 'buffer': + case 'null': + canonicalizedObj = value; + break; + case 'array': + withStack(value, function() { + canonicalizedObj = exports.map(value, function(item) { + return exports.canonicalize(item, stack); + }); + }); + break; + case 'function': + /* eslint-disable guard-for-in */ + for (prop in value) { + canonicalizedObj = {}; + break; + } + /* eslint-enable guard-for-in */ + if (!canonicalizedObj) { + canonicalizedObj = emptyRepresentation(value, type); + break; + } + /* falls through */ + case 'object': + canonicalizedObj = canonicalizedObj || {}; + withStack(value, function() { + exports.forEach(exports.keys(value).sort(), function(key) { + canonicalizedObj[key] = exports.canonicalize(value[key], stack); + }); + }); + break; + case 'date': + case 'number': + case 'regexp': + case 'boolean': + canonicalizedObj = value; + break; + default: + canonicalizedObj = value + ''; + } + + return canonicalizedObj; +}; + +/** + * Lookup file names at the given `path`. + * + * @api public + * @param {string} path Base path to start searching from. + * @param {string[]} extensions File extensions to look for. + * @param {boolean} recursive Whether or not to recurse into subdirectories. + * @return {string[]} An array of paths. + */ +exports.lookupFiles = function lookupFiles(path, extensions, recursive) { + var files = []; + var re = new RegExp('\\.(' + extensions.join('|') + ')$'); + + if (!exists(path)) { + if (exists(path + '.js')) { + path += '.js'; + } else { + files = glob.sync(path); + if (!files.length) { + throw new Error("cannot resolve path (or pattern) '" + path + "'"); + } + return files; + } + } + + try { + var stat = statSync(path); + if (stat.isFile()) { + return path; + } + } catch (err) { + // ignore error + return; + } + + readdirSync(path).forEach(function(file) { + file = join(path, file); + try { + var stat = statSync(file); + if (stat.isDirectory()) { + if (recursive) { + files = files.concat(lookupFiles(file, extensions, recursive)); + } + return; + } + } catch (err) { + // ignore error + return; + } + if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') { + return; + } + files.push(file); + }); + + return files; +}; + +/** + * Generate an undefined error with a message warning the user. + * + * @return {Error} + */ + +exports.undefinedError = function() { + return new Error('Caught undefined error, did you throw without specifying what?'); +}; + +/** + * Generate an undefined error if `err` is not defined. + * + * @param {Error} err + * @return {Error} + */ + +exports.getError = function(err) { + return err || exports.undefinedError(); +}; + +/** + * @summary + * This Filter based on `mocha-clean` module.(see: `github.com/rstacruz/mocha-clean`) + * @description + * When invoking this function you get a filter function that get the Error.stack as an input, + * and return a prettify output. + * (i.e: strip Mocha and internal node functions from stack trace). + * @returns {Function} + */ +exports.stackTraceFilter = function() { + // TODO: Replace with `process.browser` + var slash = '/'; + var is = typeof document === 'undefined' ? { node: true } : { browser: true }; + var cwd = is.node + ? process.cwd() + slash + : (typeof location === 'undefined' ? window.location : location).href.replace(/\/[^\/]*$/, '/'); + + function isMochaInternal(line) { + return (~line.indexOf('node_modules' + slash + 'mocha' + slash)) + || (~line.indexOf('components' + slash + 'mochajs' + slash)) + || (~line.indexOf('components' + slash + 'mocha' + slash)) + || (~line.indexOf(slash + 'mocha.js')); + } + + function isNodeInternal(line) { + return (~line.indexOf('(timers.js:')) + || (~line.indexOf('(events.js:')) + || (~line.indexOf('(node.js:')) + || (~line.indexOf('(module.js:')) + || (~line.indexOf('GeneratorFunctionPrototype.next (native)')) + || false; + } + + return function(stack) { + stack = stack.split('\n'); + + stack = exports.reduce(stack, function(list, line) { + if (isMochaInternal(line)) { + return list; + } + + if (is.node && isNodeInternal(line)) { + return list; + } + + // Clean up cwd(absolute) + list.push(line.replace(cwd, '')); + return list; + }, []); + + return stack.join('\n'); + }; +}; + +}).call(this,require('_process'),require("buffer").Buffer) +},{"_process":51,"buffer":43,"debug":2,"fs":41,"glob":41,"path":41,"util":66}],40:[function(require,module,exports){ +(function (process){ +var WritableStream = require('stream').Writable +var inherits = require('util').inherits + +module.exports = BrowserStdout + + +inherits(BrowserStdout, WritableStream) + +function BrowserStdout(opts) { + if (!(this instanceof BrowserStdout)) return new BrowserStdout(opts) + + opts = opts || {} + WritableStream.call(this, opts) + this.label = (opts.label !== undefined) ? opts.label : 'stdout' +} + +BrowserStdout.prototype._write = function(chunks, encoding, cb) { + var output = chunks.toString ? chunks.toString() : chunks + if (this.label === false) { + console.log(output) + } else { + console.log(this.label+':', output) + } + process.nextTick(cb) +} + +}).call(this,require('_process')) +},{"_process":51,"stream":63,"util":66}],41:[function(require,module,exports){ + +},{}],42:[function(require,module,exports){ +arguments[4][41][0].apply(exports,arguments) +},{"dup":41}],43:[function(require,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +var base64 = require('base64-js') +var ieee754 = require('ieee754') +var isArray = require('is-array') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 +Buffer.poolSize = 8192 // not used by this implementation + +var rootParent = {} + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Due to various browser bugs, sometimes the Object implementation will be used even + * when the browser supports typed arrays. + * + * Note: + * + * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property + * on objects. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they + * get the Object implementation, which is slower but behaves correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = (function () { + function Bar () {} + try { + var arr = new Uint8Array(1) + arr.foo = function () { return 42 } + arr.constructor = Bar + return arr.foo() === 42 && // typed array instances can be augmented + arr.constructor === Bar && // constructor can be set + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +})() + +function kMaxLength () { + return Buffer.TYPED_ARRAY_SUPPORT + ? 0x7fffffff + : 0x3fffffff +} + +/** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ +function Buffer (arg) { + if (!(this instanceof Buffer)) { + // Avoid going through an ArgumentsAdaptorTrampoline in the common case. + if (arguments.length > 1) return new Buffer(arg, arguments[1]) + return new Buffer(arg) + } + + this.length = 0 + this.parent = undefined + + // Common case. + if (typeof arg === 'number') { + return fromNumber(this, arg) + } + + // Slightly less common case. + if (typeof arg === 'string') { + return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') + } + + // Unusual. + return fromObject(this, arg) +} + +function fromNumber (that, length) { + that = allocate(that, length < 0 ? 0 : checked(length) | 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < length; i++) { + that[i] = 0 + } + } + return that +} + +function fromString (that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' + + // Assumption: byteLength() return value is always < kMaxLength. + var length = byteLength(string, encoding) | 0 + that = allocate(that, length) + + that.write(string, encoding) + return that +} + +function fromObject (that, object) { + if (Buffer.isBuffer(object)) return fromBuffer(that, object) + + if (isArray(object)) return fromArray(that, object) + + if (object == null) { + throw new TypeError('must start with number, buffer, array or string') + } + + if (typeof ArrayBuffer !== 'undefined') { + if (object.buffer instanceof ArrayBuffer) { + return fromTypedArray(that, object) + } + if (object instanceof ArrayBuffer) { + return fromArrayBuffer(that, object) + } + } + + if (object.length) return fromArrayLike(that, object) + + return fromJsonObject(that, object) +} + +function fromBuffer (that, buffer) { + var length = checked(buffer.length) | 0 + that = allocate(that, length) + buffer.copy(that, 0, 0, length) + return that +} + +function fromArray (that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +// Duplicate of fromArray() to keep fromArray() monomorphic. +function fromTypedArray (that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + // Truncating the elements is probably not what people expect from typed + // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior + // of the old Buffer constructor. + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +function fromArrayBuffer (that, array) { + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + array.byteLength + that = Buffer._augment(new Uint8Array(array)) + } else { + // Fallback: Return an object instance of the Buffer class + that = fromTypedArray(that, new Uint8Array(array)) + } + return that +} + +function fromArrayLike (that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object. +// Returns a zero-length buffer for inputs that don't conform to the spec. +function fromJsonObject (that, object) { + var array + var length = 0 + + if (object.type === 'Buffer' && isArray(object.data)) { + array = object.data + length = checked(array.length) | 0 + } + that = allocate(that, length) + + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +function allocate (that, length) { + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = Buffer._augment(new Uint8Array(length)) + } else { + // Fallback: Return an object instance of the Buffer class + that.length = length + that._isBuffer = true + } + + var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 + if (fromPool) that.parent = rootParent + + return that +} + +function checked (length) { + // Note: cannot use `length < kMaxLength` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= kMaxLength()) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength().toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (subject, encoding) { + if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding) + + var buf = new Buffer(subject, encoding) + delete buf.parent + return buf +} + +Buffer.isBuffer = function isBuffer (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function compare (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('Arguments must be Buffers') + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + var i = 0 + var len = Math.min(x, y) + while (i < len) { + if (a[i] !== b[i]) break + + ++i + } + + if (i !== len) { + x = a[i] + y = b[i] + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'binary': + case 'base64': + case 'raw': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.') + + if (list.length === 0) { + return new Buffer(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; i++) { + length += list[i].length + } + } + + var buf = new Buffer(length) + var pos = 0 + for (i = 0; i < list.length; i++) { + var item = list[i] + item.copy(buf, pos) + pos += item.length + } + return buf +} + +function byteLength (string, encoding) { + if (typeof string !== 'string') string = '' + string + + var len = string.length + if (len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'binary': + // Deprecated + case 'raw': + case 'raws': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) return utf8ToBytes(string).length // assume utf8 + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +// pre-set for values that may exist in the future +Buffer.prototype.length = undefined +Buffer.prototype.parent = undefined + +function slowToString (encoding, start, end) { + var loweredCase = false + + start = start | 0 + end = end === undefined || end === Infinity ? this.length : end | 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toString = function toString () { + var length = this.length | 0 + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) str += ' ... ' + } + return '' +} + +Buffer.prototype.compare = function compare (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return 0 + return Buffer.compare(this, b) +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset) { + if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff + else if (byteOffset < -0x80000000) byteOffset = -0x80000000 + byteOffset >>= 0 + + if (this.length === 0) return -1 + if (byteOffset >= this.length) return -1 + + // Negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) + + if (typeof val === 'string') { + if (val.length === 0) return -1 // special case: looking for empty string always fails + return String.prototype.indexOf.call(this, val, byteOffset) + } + if (Buffer.isBuffer(val)) { + return arrayIndexOf(this, val, byteOffset) + } + if (typeof val === 'number') { + if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { + return Uint8Array.prototype.indexOf.call(this, val, byteOffset) + } + return arrayIndexOf(this, [ val ], byteOffset) + } + + function arrayIndexOf (arr, val, byteOffset) { + var foundIndex = -1 + for (var i = 0; byteOffset + i < arr.length; i++) { + if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex + } else { + foundIndex = -1 + } + } + return -1 + } + + throw new TypeError('val must be string, number or Buffer') +} + +// `get` is deprecated +Buffer.prototype.get = function get (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) +} + +// `set` is deprecated +Buffer.prototype.set = function set (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new Error('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; i++) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(parsed)) throw new Error('Invalid hex string') + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function binaryWrite (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset | 0 + if (isFinite(length)) { + length = length | 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + // legacy write(string, encoding, offset, length) - remove in v0.13 + } else { + var swap = encoding + encoding = offset + offset = length | 0 + length = swap + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'binary': + return binaryWrite(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function binarySlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; i++) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf + if (Buffer.TYPED_ARRAY_SUPPORT) { + newBuf = Buffer._augment(this.subarray(start, end)) + } else { + var sliceLen = end - start + newBuf = new Buffer(sliceLen, undefined) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + } + + if (newBuf.length) newBuf.parent = this.parent || this + + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new RangeError('value is out of bounds') + if (offset + ext > buf.length) throw new RangeError('index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = value + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = value + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = value < 0 ? 1 : 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = value < 0 ? 1 : 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = value + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (value > max || value < min) throw new RangeError('value is out of bounds') + if (offset + ext > buf.length) throw new RangeError('index out of range') + if (offset < 0) throw new RangeError('index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + var i + + if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (i = len - 1; i >= 0; i--) { + target[i + targetStart] = this[i + start] + } + } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + // ascending copy from start + for (i = 0; i < len; i++) { + target[i + targetStart] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), targetStart) + } + + return len +} + +// fill(value, start=0, end=buffer.length) +Buffer.prototype.fill = function fill (value, start, end) { + if (!value) value = 0 + if (!start) start = 0 + if (!end) end = this.length + + if (end < start) throw new RangeError('end < start') + + // Fill 0 bytes; we're done + if (end === start) return + if (this.length === 0) return + + if (start < 0 || start >= this.length) throw new RangeError('start out of bounds') + if (end < 0 || end > this.length) throw new RangeError('end out of bounds') + + var i + if (typeof value === 'number') { + for (i = start; i < end; i++) { + this[i] = value + } + } else { + var bytes = utf8ToBytes(value.toString()) + var len = bytes.length + for (i = start; i < end; i++) { + this[i] = bytes[i % len] + } + } + + return this +} + +/** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Only available in browsers that support ArrayBuffer. + */ +Buffer.prototype.toArrayBuffer = function toArrayBuffer () { + if (typeof Uint8Array !== 'undefined') { + if (Buffer.TYPED_ARRAY_SUPPORT) { + return (new Buffer(this)).buffer + } else { + var buf = new Uint8Array(this.length) + for (var i = 0, len = buf.length; i < len; i += 1) { + buf[i] = this[i] + } + return buf.buffer + } + } else { + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') + } +} + +// HELPER FUNCTIONS +// ================ + +var BP = Buffer.prototype + +/** + * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods + */ +Buffer._augment = function _augment (arr) { + arr.constructor = Buffer + arr._isBuffer = true + + // save reference to original Uint8Array set method before overwriting + arr._set = arr.set + + // deprecated + arr.get = BP.get + arr.set = BP.set + + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.equals = BP.equals + arr.compare = BP.compare + arr.indexOf = BP.indexOf + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUIntLE = BP.readUIntLE + arr.readUIntBE = BP.readUIntBE + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readIntLE = BP.readIntLE + arr.readIntBE = BP.readIntBE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUIntLE = BP.writeUIntLE + arr.writeUIntBE = BP.writeUIntBE + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeIntLE = BP.writeIntLE + arr.writeIntBE = BP.writeIntBE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BP.toArrayBuffer + + return arr +} + +var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; i++) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; i++) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; i++) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +},{"base64-js":44,"ieee754":45,"is-array":46}],44:[function(require,module,exports){ +var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +;(function (exports) { + 'use strict'; + + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array + + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + var PLUS_URL_SAFE = '-'.charCodeAt(0) + var SLASH_URL_SAFE = '_'.charCodeAt(0) + + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS || + code === PLUS_URL_SAFE) + return 62 // '+' + if (code === SLASH || + code === SLASH_URL_SAFE) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } + + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push (v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64 (uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length + + function encode (num) { + return lookup.charAt(num) + } + + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 +}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) + +},{}],45:[function(require,module,exports){ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + +},{}],46:[function(require,module,exports){ + +/** + * isArray + */ + +var isArray = Array.isArray; + +/** + * toString + */ + +var str = Object.prototype.toString; + +/** + * Whether or not the given `val` + * is an array. + * + * example: + * + * isArray([]); + * // > true + * isArray(arguments); + * // > false + * isArray(''); + * // > false + * + * @param {mixed} val + * @return {bool} + */ + +module.exports = isArray || function (val) { + return !! val && '[object Array]' == str.call(val); +}; + +},{}],47:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],48:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],49:[function(require,module,exports){ +module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +}; + +},{}],50:[function(require,module,exports){ +exports.endianness = function () { return 'LE' }; + +exports.hostname = function () { + if (typeof location !== 'undefined') { + return location.hostname + } + else return ''; +}; + +exports.loadavg = function () { return [] }; + +exports.uptime = function () { return 0 }; + +exports.freemem = function () { + return Number.MAX_VALUE; +}; + +exports.totalmem = function () { + return Number.MAX_VALUE; +}; + +exports.cpus = function () { return [] }; + +exports.type = function () { return 'Browser' }; + +exports.release = function () { + if (typeof navigator !== 'undefined') { + return navigator.appVersion; + } + return ''; +}; + +exports.networkInterfaces += exports.getNetworkInterfaces += function () { return {} }; + +exports.arch = function () { return 'javascript' }; + +exports.platform = function () { return 'browser' }; + +exports.tmpdir = exports.tmpDir = function () { + return '/tmp'; +}; + +exports.EOL = '\n'; + +},{}],51:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = setTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + clearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + setTimeout(drainQueue, 0); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],52:[function(require,module,exports){ +module.exports = require("./lib/_stream_duplex.js") + +},{"./lib/_stream_duplex.js":53}],53:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +module.exports = Duplex; + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +} +/**/ + + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +forEach(objectKeys(Writable.prototype), function(method) { + if (!Duplex.prototype[method]) + Duplex.prototype[method] = Writable.prototype[method]; +}); + +function Duplex(options) { + if (!(this instanceof Duplex)) + return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) + this.readable = false; + + if (options && options.writable === false) + this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) + this.allowHalfOpen = false; + + this.once('end', onend); +} + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) + return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(this.end.bind(this)); +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +}).call(this,require('_process')) +},{"./_stream_readable":55,"./_stream_writable":57,"_process":51,"core-util-is":58,"inherits":48}],54:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) + return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function(chunk, encoding, cb) { + cb(null, chunk); +}; + +},{"./_stream_transform":56,"core-util-is":58,"inherits":48}],55:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +module.exports = Readable; + +/**/ +var isArray = require('isarray'); +/**/ + + +/**/ +var Buffer = require('buffer').Buffer; +/**/ + +Readable.ReadableState = ReadableState; + +var EE = require('events').EventEmitter; + +/**/ +if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +var Stream = require('stream'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var StringDecoder; + + +/**/ +var debug = require('util'); +if (debug && debug.debuglog) { + debug = debug.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + + +util.inherits(Readable, Stream); + +function ReadableState(options, stream) { + var Duplex = require('./_stream_duplex'); + + options = options || {}; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var defaultHwm = options.objectMode ? 16 : 16 * 1024; + this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.buffer = []; + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (stream instanceof Duplex) + this.objectMode = this.objectMode || !!options.readableObjectMode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // when piping, we only care about 'readable' events that happen + // after read()ing all the bytes and not getting any pushback. + this.ranOut = false; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) + StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + var Duplex = require('./_stream_duplex'); + + if (!(this instanceof Readable)) + return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + Stream.call(this); +} + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function(chunk, encoding) { + var state = this._readableState; + + if (util.isString(chunk) && !state.objectMode) { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = new Buffer(chunk, encoding); + encoding = ''; + } + } + + return readableAddChunk(this, state, chunk, encoding, false); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function(chunk) { + var state = this._readableState; + return readableAddChunk(this, state, chunk, '', true); +}; + +function readableAddChunk(stream, state, chunk, encoding, addToFront) { + var er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (util.isNullOrUndefined(chunk)) { + state.reading = false; + if (!state.ended) + onEofChunk(stream, state); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (state.ended && !addToFront) { + var e = new Error('stream.push() after EOF'); + stream.emit('error', e); + } else if (state.endEmitted && addToFront) { + var e = new Error('stream.unshift() after end event'); + stream.emit('error', e); + } else { + if (state.decoder && !addToFront && !encoding) + chunk = state.decoder.write(chunk); + + if (!addToFront) + state.reading = false; + + // if we want the data now, just emit it. + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) + state.buffer.unshift(chunk); + else + state.buffer.push(chunk); + + if (state.needReadable) + emitReadable(stream); + } + + maybeReadMore(stream, state); + } + } else if (!addToFront) { + state.reading = false; + } + + return needMoreData(state); +} + + + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && + (state.needReadable || + state.length < state.highWaterMark || + state.length === 0); +} + +// backwards compatibility. +Readable.prototype.setEncoding = function(enc) { + if (!StringDecoder) + StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 128MB +var MAX_HWM = 0x800000; +function roundUpToNextPowerOf2(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 + n--; + for (var p = 1; p < 32; p <<= 1) n |= n >> p; + n++; + } + return n; +} + +function howMuchToRead(n, state) { + if (state.length === 0 && state.ended) + return 0; + + if (state.objectMode) + return n === 0 ? 0 : 1; + + if (isNaN(n) || util.isNull(n)) { + // only flow one buffer at a time + if (state.flowing && state.buffer.length) + return state.buffer[0].length; + else + return state.length; + } + + if (n <= 0) + return 0; + + // If we're asking for more than the target buffer level, + // then raise the water mark. Bump up to the next highest + // power of 2, to prevent increasing it excessively in tiny + // amounts. + if (n > state.highWaterMark) + state.highWaterMark = roundUpToNextPowerOf2(n); + + // don't have that much. return null, unless we've ended. + if (n > state.length) { + if (!state.ended) { + state.needReadable = true; + return 0; + } else + return state.length; + } + + return n; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function(n) { + debug('read', n); + var state = this._readableState; + var nOrig = n; + + if (!util.isNumber(n) || n > 0) + state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && + state.needReadable && + (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) + endReadable(this); + else + emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) + endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } + + if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) + state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + } + + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (doRead && !state.reading) + n = howMuchToRead(nOrig, state); + + var ret; + if (n > 0) + ret = fromList(n, state); + else + ret = null; + + if (util.isNull(ret)) { + state.needReadable = true; + n = 0; + } + + state.length -= n; + + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (state.length === 0 && !state.ended) + state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended && state.length === 0) + endReadable(this); + + if (!util.isNull(ret)) + this.emit('data', ret); + + return ret; +}; + +function chunkInvalid(state, chunk) { + var er = null; + if (!util.isBuffer(chunk) && + !util.isString(chunk) && + !util.isNullOrUndefined(chunk) && + !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + + +function onEofChunk(stream, state) { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) + process.nextTick(function() { + emitReadable_(stream); + }); + else + emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(function() { + maybeReadMore_(stream, state); + }); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && + state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + else + len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function(n) { + this.emit('error', new Error('not implemented')); +}; + +Readable.prototype.pipe = function(dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && + dest !== process.stdout && + dest !== process.stderr; + + var endFn = doEnd ? onend : cleanup; + if (state.endEmitted) + process.nextTick(endFn); + else + src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable) { + debug('onunpipe'); + if (readable === src) { + cleanup(); + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', cleanup); + src.removeListener('data', ondata); + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && + (!dest._writableState || dest._writableState.needDrain)) + ondrain(); + } + + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + var ret = dest.write(chunk); + if (false === ret) { + debug('false write response, pause', + src._readableState.awaitDrain); + src._readableState.awaitDrain++; + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EE.listenerCount(dest, 'error') === 0) + dest.emit('error', er); + } + // This is a brutally ugly hack to make sure that our error handler + // is attached before any userland ones. NEVER DO THIS. + if (!dest._events || !dest._events.error) + dest.on('error', onerror); + else if (isArray(dest._events.error)) + dest._events.error.unshift(onerror); + else + dest._events.error = [onerror, dest._events.error]; + + + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function() { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) + state.awaitDrain--; + if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + + +Readable.prototype.unpipe = function(dest) { + var state = this._readableState; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) + return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) + return this; + + if (!dest) + dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) + dest.emit('unpipe', this); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) + dests[i].emit('unpipe', this); + return this; + } + + // try to find the right one. + var i = indexOf(state.pipes, dest); + if (i === -1) + return this; + + state.pipes.splice(i, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) + state.pipes = state.pipes[0]; + + dest.emit('unpipe', this); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function(ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + // If listening to data, and it has not explicitly been paused, + // then call resume to start the flow of data on the next tick. + if (ev === 'data' && false !== this._readableState.flowing) { + this.resume(); + } + + if (ev === 'readable' && this.readable) { + var state = this._readableState; + if (!state.readableListening) { + state.readableListening = true; + state.emittedReadable = false; + state.needReadable = true; + if (!state.reading) { + var self = this; + process.nextTick(function() { + debug('readable nexttick read 0'); + self.read(0); + }); + } else if (state.length) { + emitReadable(this, state); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function() { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + if (!state.reading) { + debug('resume read 0'); + this.read(0); + } + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + process.nextTick(function() { + resume_(stream, state); + }); + } +} + +function resume_(stream, state) { + state.resumeScheduled = false; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) + stream.read(0); +} + +Readable.prototype.pause = function() { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + if (state.flowing) { + do { + var chunk = stream.read(); + } while (null !== chunk && state.flowing); + } +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function(stream) { + var state = this._readableState; + var paused = false; + + var self = this; + stream.on('end', function() { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) + self.push(chunk); + } + + self.push(null); + }); + + stream.on('data', function(chunk) { + debug('wrapped data'); + if (state.decoder) + chunk = state.decoder.write(chunk); + if (!chunk || !state.objectMode && !chunk.length) + return; + + var ret = self.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (util.isFunction(stream[i]) && util.isUndefined(this[i])) { + this[i] = function(method) { return function() { + return stream[method].apply(stream, arguments); + }}(i); + } + } + + // proxy certain important events. + var events = ['error', 'close', 'destroy', 'pause', 'resume']; + forEach(events, function(ev) { + stream.on(ev, self.emit.bind(self, ev)); + }); + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + self._read = function(n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return self; +}; + + + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +function fromList(n, state) { + var list = state.buffer; + var length = state.length; + var stringMode = !!state.decoder; + var objectMode = !!state.objectMode; + var ret; + + // nothing in the list, definitely empty. + if (list.length === 0) + return null; + + if (length === 0) + ret = null; + else if (objectMode) + ret = list.shift(); + else if (!n || n >= length) { + // read it all, truncate the array. + if (stringMode) + ret = list.join(''); + else + ret = Buffer.concat(list, length); + list.length = 0; + } else { + // read just some of it. + if (n < list[0].length) { + // just take a part of the first list item. + // slice is the same for buffers and strings. + var buf = list[0]; + ret = buf.slice(0, n); + list[0] = buf.slice(n); + } else if (n === list[0].length) { + // first list is a perfect match + ret = list.shift(); + } else { + // complex case. + // we have enough to cover it, but it spans past the first buffer. + if (stringMode) + ret = ''; + else + ret = new Buffer(n); + + var c = 0; + for (var i = 0, l = list.length; i < l && c < n; i++) { + var buf = list[0]; + var cpy = Math.min(n - c, buf.length); + + if (stringMode) + ret += buf.slice(0, cpy); + else + buf.copy(ret, c, 0, cpy); + + if (cpy < buf.length) + list[0] = buf.slice(cpy); + else + list.shift(); + + c += cpy; + } + } + } + + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) + throw new Error('endReadable called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + process.nextTick(function() { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } + }); + } +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +function indexOf (xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} + +}).call(this,require('_process')) +},{"./_stream_duplex":53,"_process":51,"buffer":43,"core-util-is":58,"events":47,"inherits":48,"isarray":49,"stream":63,"string_decoder/":64,"util":42}],56:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + + +function TransformState(options, stream) { + this.afterTransform = function(er, data) { + return afterTransform(stream, er, data); + }; + + this.needTransform = false; + this.transforming = false; + this.writecb = null; + this.writechunk = null; +} + +function afterTransform(stream, er, data) { + var ts = stream._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) + return stream.emit('error', new Error('no writecb in Transform class')); + + ts.writechunk = null; + ts.writecb = null; + + if (!util.isNullOrUndefined(data)) + stream.push(data); + + if (cb) + cb(er); + + var rs = stream._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + stream._read(rs.highWaterMark); + } +} + + +function Transform(options) { + if (!(this instanceof Transform)) + return new Transform(options); + + Duplex.call(this, options); + + this._transformState = new TransformState(options, this); + + // when the writable side finishes, then flush out anything remaining. + var stream = this; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + this.once('prefinish', function() { + if (util.isFunction(this._flush)) + this._flush(function(er) { + done(stream, er); + }); + else + done(stream); + }); +} + +Transform.prototype.push = function(chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function(chunk, encoding, cb) { + throw new Error('not implemented'); +}; + +Transform.prototype._write = function(chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || + rs.needReadable || + rs.length < rs.highWaterMark) + this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function(n) { + var ts = this._transformState; + + if (!util.isNull(ts.writechunk) && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + + +function done(stream, er) { + if (er) + return stream.emit('error', er); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + var ws = stream._writableState; + var ts = stream._transformState; + + if (ws.length) + throw new Error('calling transform done when ws.length != 0'); + + if (ts.transforming) + throw new Error('calling transform done when still transforming'); + + return stream.push(null); +} + +},{"./_stream_duplex":53,"core-util-is":58,"inherits":48}],57:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, cb), and it'll handle all +// the drain event emission and buffering. + +module.exports = Writable; + +/**/ +var Buffer = require('buffer').Buffer; +/**/ + +Writable.WritableState = WritableState; + + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Stream = require('stream'); + +util.inherits(Writable, Stream); + +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; +} + +function WritableState(options, stream) { + var Duplex = require('./_stream_duplex'); + + options = options || {}; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var defaultHwm = options.objectMode ? 16 : 16 * 1024; + this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (stream instanceof Duplex) + this.objectMode = this.objectMode || !!options.writableObjectMode; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function(er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.buffer = []; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; +} + +function Writable(options) { + var Duplex = require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. + if (!(this instanceof Writable) && !(this instanceof Duplex)) + return new Writable(options); + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function() { + this.emit('error', new Error('Cannot pipe. Not readable.')); +}; + + +function writeAfterEnd(stream, state, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); +} + +// If we get something that is not a buffer, string, null, or undefined, +// and we're not in objectMode, then that's an error. +// Otherwise stream chunks are all considered to be of length=1, and the +// watermarks determine how many objects to keep in the buffer, rather than +// how many bytes or characters. +function validChunk(stream, state, chunk, cb) { + var valid = true; + if (!util.isBuffer(chunk) && + !util.isString(chunk) && + !util.isNullOrUndefined(chunk) && + !state.objectMode) { + var er = new TypeError('Invalid non-string/buffer chunk'); + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); + valid = false; + } + return valid; +} + +Writable.prototype.write = function(chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + + if (util.isFunction(encoding)) { + cb = encoding; + encoding = null; + } + + if (util.isBuffer(chunk)) + encoding = 'buffer'; + else if (!encoding) + encoding = state.defaultEncoding; + + if (!util.isFunction(cb)) + cb = function() {}; + + if (state.ended) + writeAfterEnd(this, state, cb); + else if (validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function() { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function() { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && + !state.corked && + !state.finished && + !state.bufferProcessing && + state.buffer.length) + clearBuffer(this, state); + } +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && + state.decodeStrings !== false && + util.isString(chunk)) { + chunk = new Buffer(chunk, encoding); + } + return chunk; +} + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, chunk, encoding, cb) { + chunk = decodeChunk(state, chunk, encoding); + if (util.isBuffer(chunk)) + encoding = 'buffer'; + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) + state.needDrain = true; + + if (state.writing || state.corked) + state.buffer.push(new WriteReq(chunk, encoding, cb)); + else + doWrite(stream, state, false, len, chunk, encoding, cb); + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) + stream._writev(chunk, state.onwrite); + else + stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + if (sync) + process.nextTick(function() { + state.pendingcb--; + cb(er); + }); + else { + state.pendingcb--; + cb(er); + } + + stream._writableState.errorEmitted = true; + stream.emit('error', er); +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) + onwriteError(stream, state, sync, er, cb); + else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(stream, state); + + if (!finished && + !state.corked && + !state.bufferProcessing && + state.buffer.length) { + clearBuffer(stream, state); + } + + if (sync) { + process.nextTick(function() { + afterWrite(stream, state, finished, cb); + }); + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) + onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + + if (stream._writev && state.buffer.length > 1) { + // Fast case, write everything using _writev() + var cbs = []; + for (var c = 0; c < state.buffer.length; c++) + cbs.push(state.buffer[c].callback); + + // count the one we are adding, as well. + // TODO(isaacs) clean this up + state.pendingcb++; + doWrite(stream, state, true, state.length, state.buffer, '', function(err) { + for (var i = 0; i < cbs.length; i++) { + state.pendingcb--; + cbs[i](err); + } + }); + + // Clear buffer + state.buffer = []; + } else { + // Slow case, write chunks one-by-one + for (var c = 0; c < state.buffer.length; c++) { + var entry = state.buffer[c]; + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + c++; + break; + } + } + + if (c < state.buffer.length) + state.buffer = state.buffer.slice(c); + else + state.buffer.length = 0; + } + + state.bufferProcessing = false; +} + +Writable.prototype._write = function(chunk, encoding, cb) { + cb(new Error('not implemented')); + +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function(chunk, encoding, cb) { + var state = this._writableState; + + if (util.isFunction(chunk)) { + cb = chunk; + chunk = null; + encoding = null; + } else if (util.isFunction(encoding)) { + cb = encoding; + encoding = null; + } + + if (!util.isNullOrUndefined(chunk)) + this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) + endWritable(this, state, cb); +}; + + +function needFinish(stream, state) { + return (state.ending && + state.length === 0 && + !state.finished && + !state.writing); +} + +function prefinish(stream, state) { + if (!state.prefinished) { + state.prefinished = true; + stream.emit('prefinish'); + } +} + +function finishMaybe(stream, state) { + var need = needFinish(stream, state); + if (need) { + if (state.pendingcb === 0) { + prefinish(stream, state); + state.finished = true; + stream.emit('finish'); + } else + prefinish(stream, state); + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) + process.nextTick(cb); + else + stream.once('finish', cb); + } + state.ended = true; +} + +}).call(this,require('_process')) +},{"./_stream_duplex":53,"_process":51,"buffer":43,"core-util-is":58,"inherits":48,"stream":63}],58:[function(require,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +function isBuffer(arg) { + return Buffer.isBuffer(arg); +} +exports.isBuffer = isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} +}).call(this,require("buffer").Buffer) +},{"buffer":43}],59:[function(require,module,exports){ +module.exports = require("./lib/_stream_passthrough.js") + +},{"./lib/_stream_passthrough.js":54}],60:[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = require('stream'); +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":53,"./lib/_stream_passthrough.js":54,"./lib/_stream_readable.js":55,"./lib/_stream_transform.js":56,"./lib/_stream_writable.js":57,"stream":63}],61:[function(require,module,exports){ +module.exports = require("./lib/_stream_transform.js") + +},{"./lib/_stream_transform.js":56}],62:[function(require,module,exports){ +module.exports = require("./lib/_stream_writable.js") + +},{"./lib/_stream_writable.js":57}],63:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +module.exports = Stream; + +var EE = require('events').EventEmitter; +var inherits = require('inherits'); + +inherits(Stream, EE); +Stream.Readable = require('readable-stream/readable.js'); +Stream.Writable = require('readable-stream/writable.js'); +Stream.Duplex = require('readable-stream/duplex.js'); +Stream.Transform = require('readable-stream/transform.js'); +Stream.PassThrough = require('readable-stream/passthrough.js'); + +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; + + + +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. + +function Stream() { + EE.call(this); +} + +Stream.prototype.pipe = function(dest, options) { + var source = this; + + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } + + source.on('data', ondata); + + function ondrain() { + if (source.readable && source.resume) { + source.resume(); + } + } + + dest.on('drain', ondrain); + + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + + dest.end(); + } + + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + if (typeof dest.destroy === 'function') dest.destroy(); + } + + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } + + source.on('error', onerror); + dest.on('error', onerror); + + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + + source.removeListener('end', onend); + source.removeListener('close', onclose); + + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + + dest.removeListener('close', cleanup); + } + + source.on('end', cleanup); + source.on('close', cleanup); + + dest.on('close', cleanup); + + dest.emit('pipe', source); + + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"events":47,"inherits":48,"readable-stream/duplex.js":52,"readable-stream/passthrough.js":59,"readable-stream/readable.js":60,"readable-stream/transform.js":61,"readable-stream/writable.js":62}],64:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +var Buffer = require('buffer').Buffer; + +var isBufferEncoding = Buffer.isEncoding + || function(encoding) { + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; + default: return false; + } + } + + +function assertEncoding(encoding) { + if (encoding && !isBufferEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. CESU-8 is handled as part of the UTF-8 encoding. +// +// @TODO Handling all encodings inside a single object makes it very difficult +// to reason about this code, so it should be split up in the future. +// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code +// points as used by CESU-8. +var StringDecoder = exports.StringDecoder = function(encoding) { + this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); + assertEncoding(encoding); + switch (this.encoding) { + case 'utf8': + // CESU-8 represents each of Surrogate Pair by 3-bytes + this.surrogateSize = 3; + break; + case 'ucs2': + case 'utf16le': + // UTF-16 represents each of Surrogate Pair by 2-bytes + this.surrogateSize = 2; + this.detectIncompleteChar = utf16DetectIncompleteChar; + break; + case 'base64': + // Base-64 stores 3 bytes in 4 chars, and pads the remainder. + this.surrogateSize = 3; + this.detectIncompleteChar = base64DetectIncompleteChar; + break; + default: + this.write = passThroughWrite; + return; + } + + // Enough space to store all bytes of a single character. UTF-8 needs 4 + // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). + this.charBuffer = new Buffer(6); + // Number of bytes received for the current incomplete multi-byte character. + this.charReceived = 0; + // Number of bytes expected for the current incomplete multi-byte character. + this.charLength = 0; +}; + + +// write decodes the given buffer and returns it as JS string that is +// guaranteed to not contain any partial multi-byte characters. Any partial +// character found at the end of the buffer is buffered up, and will be +// returned when calling write again with the remaining bytes. +// +// Note: Converting a Buffer containing an orphan surrogate to a String +// currently works, but converting a String to a Buffer (via `new Buffer`, or +// Buffer#write) will replace incomplete surrogates with the unicode +// replacement character. See https://codereview.chromium.org/121173009/ . +StringDecoder.prototype.write = function(buffer) { + var charStr = ''; + // if our last write ended with an incomplete multibyte character + while (this.charLength) { + // determine how many remaining bytes this buffer has to offer for this char + var available = (buffer.length >= this.charLength - this.charReceived) ? + this.charLength - this.charReceived : + buffer.length; + + // add the new bytes to the char buffer + buffer.copy(this.charBuffer, this.charReceived, 0, available); + this.charReceived += available; + + if (this.charReceived < this.charLength) { + // still not enough chars in this buffer? wait for more ... + return ''; + } + + // remove bytes belonging to the current character from the buffer + buffer = buffer.slice(available, buffer.length); + + // get the character that was split + charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + var charCode = charStr.charCodeAt(charStr.length - 1); + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + this.charLength += this.surrogateSize; + charStr = ''; + continue; + } + this.charReceived = this.charLength = 0; + + // if there are no more bytes in this buffer, just emit our char + if (buffer.length === 0) { + return charStr; + } + break; + } + + // determine and set charLength / charReceived + this.detectIncompleteChar(buffer); + + var end = buffer.length; + if (this.charLength) { + // buffer the incomplete character bytes we got + buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); + end -= this.charReceived; + } + + charStr += buffer.toString(this.encoding, 0, end); + + var end = charStr.length - 1; + var charCode = charStr.charCodeAt(end); + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + var size = this.surrogateSize; + this.charLength += size; + this.charReceived += size; + this.charBuffer.copy(this.charBuffer, size, 0, size); + buffer.copy(this.charBuffer, 0, 0, size); + return charStr.substring(0, end); + } + + // or just emit the charStr + return charStr; +}; + +// detectIncompleteChar determines if there is an incomplete UTF-8 character at +// the end of the given buffer. If so, it sets this.charLength to the byte +// length that character, and sets this.charReceived to the number of bytes +// that are available for this character. +StringDecoder.prototype.detectIncompleteChar = function(buffer) { + // determine how many bytes we have to check at the end of this buffer + var i = (buffer.length >= 3) ? 3 : buffer.length; + + // Figure out if one of the last i bytes of our buffer announces an + // incomplete char. + for (; i > 0; i--) { + var c = buffer[buffer.length - i]; + + // See http://en.wikipedia.org/wiki/UTF-8#Description + + // 110XXXXX + if (i == 1 && c >> 5 == 0x06) { + this.charLength = 2; + break; + } + + // 1110XXXX + if (i <= 2 && c >> 4 == 0x0E) { + this.charLength = 3; + break; + } + + // 11110XXX + if (i <= 3 && c >> 3 == 0x1E) { + this.charLength = 4; + break; + } + } + this.charReceived = i; +}; + +StringDecoder.prototype.end = function(buffer) { + var res = ''; + if (buffer && buffer.length) + res = this.write(buffer); + + if (this.charReceived) { + var cr = this.charReceived; + var buf = this.charBuffer; + var enc = this.encoding; + res += buf.slice(0, cr).toString(enc); + } + + return res; +}; + +function passThroughWrite(buffer) { + return buffer.toString(this.encoding); +} + +function utf16DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 2; + this.charLength = this.charReceived ? 2 : 0; +} + +function base64DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 3; + this.charLength = this.charReceived ? 3 : 0; +} + +},{"buffer":43}],65:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],66:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":65,"_process":51,"inherits":48}],67:[function(require,module,exports){ +/* See LICENSE file for terms of use */ + +/* + * Text diff implementation. + * + * This library supports the following APIS: + * JsDiff.diffChars: Character by character diff + * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace + * JsDiff.diffLines: Line based diff + * + * JsDiff.diffCss: Diff targeted at CSS content + * + * These methods are based on the implementation proposed in + * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927 + */ +(function(global, undefined) { + var objectPrototypeToString = Object.prototype.toString; + + /*istanbul ignore next*/ + function map(arr, mapper, that) { + if (Array.prototype.map) { + return Array.prototype.map.call(arr, mapper, that); + } + + var other = new Array(arr.length); + + for (var i = 0, n = arr.length; i < n; i++) { + other[i] = mapper.call(that, arr[i], i, arr); + } + return other; + } + function clonePath(path) { + return { newPos: path.newPos, components: path.components.slice(0) }; + } + function removeEmpty(array) { + var ret = []; + for (var i = 0; i < array.length; i++) { + if (array[i]) { + ret.push(array[i]); + } + } + return ret; + } + function escapeHTML(s) { + var n = s; + n = n.replace(/&/g, '&'); + n = n.replace(//g, '>'); + n = n.replace(/"/g, '"'); + + return n; + } + + // This function handles the presence of circular references by bailing out when encountering an + // object that is already on the "stack" of items being processed. + function canonicalize(obj, stack, replacementStack) { + stack = stack || []; + replacementStack = replacementStack || []; + + var i; + + for (i = 0; i < stack.length; i += 1) { + if (stack[i] === obj) { + return replacementStack[i]; + } + } + + var canonicalizedObj; + + if ('[object Array]' === objectPrototypeToString.call(obj)) { + stack.push(obj); + canonicalizedObj = new Array(obj.length); + replacementStack.push(canonicalizedObj); + for (i = 0; i < obj.length; i += 1) { + canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack); + } + stack.pop(); + replacementStack.pop(); + } else if (typeof obj === 'object' && obj !== null) { + stack.push(obj); + canonicalizedObj = {}; + replacementStack.push(canonicalizedObj); + var sortedKeys = [], + key; + for (key in obj) { + sortedKeys.push(key); + } + sortedKeys.sort(); + for (i = 0; i < sortedKeys.length; i += 1) { + key = sortedKeys[i]; + canonicalizedObj[key] = canonicalize(obj[key], stack, replacementStack); + } + stack.pop(); + replacementStack.pop(); + } else { + canonicalizedObj = obj; + } + return canonicalizedObj; + } + + function buildValues(components, newString, oldString, useLongestToken) { + var componentPos = 0, + componentLen = components.length, + newPos = 0, + oldPos = 0; + + for (; componentPos < componentLen; componentPos++) { + var component = components[componentPos]; + if (!component.removed) { + if (!component.added && useLongestToken) { + var value = newString.slice(newPos, newPos + component.count); + value = map(value, function(value, i) { + var oldValue = oldString[oldPos + i]; + return oldValue.length > value.length ? oldValue : value; + }); + + component.value = value.join(''); + } else { + component.value = newString.slice(newPos, newPos + component.count).join(''); + } + newPos += component.count; + + // Common case + if (!component.added) { + oldPos += component.count; + } + } else { + component.value = oldString.slice(oldPos, oldPos + component.count).join(''); + oldPos += component.count; + + // Reverse add and remove so removes are output first to match common convention + // The diffing algorithm is tied to add then remove output and this is the simplest + // route to get the desired output with minimal overhead. + if (componentPos && components[componentPos - 1].added) { + var tmp = components[componentPos - 1]; + components[componentPos - 1] = components[componentPos]; + components[componentPos] = tmp; + } + } + } + + return components; + } + + function Diff(ignoreWhitespace) { + this.ignoreWhitespace = ignoreWhitespace; + } + Diff.prototype = { + diff: function(oldString, newString, callback) { + var self = this; + + function done(value) { + if (callback) { + setTimeout(function() { callback(undefined, value); }, 0); + return true; + } else { + return value; + } + } + + // Handle the identity case (this is due to unrolling editLength == 0 + if (newString === oldString) { + return done([{ value: newString }]); + } + if (!newString) { + return done([{ value: oldString, removed: true }]); + } + if (!oldString) { + return done([{ value: newString, added: true }]); + } + + newString = this.tokenize(newString); + oldString = this.tokenize(oldString); + + var newLen = newString.length, oldLen = oldString.length; + var editLength = 1; + var maxEditLength = newLen + oldLen; + var bestPath = [{ newPos: -1, components: [] }]; + + // Seed editLength = 0, i.e. the content starts with the same values + var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); + if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + // Identity per the equality and tokenizer + return done([{value: newString.join('')}]); + } + + // Main worker method. checks all permutations of a given edit length for acceptance. + function execEditLength() { + for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) { + var basePath; + var addPath = bestPath[diagonalPath - 1], + removePath = bestPath[diagonalPath + 1], + oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; + if (addPath) { + // No one else is going to attempt to use this value, clear it + bestPath[diagonalPath - 1] = undefined; + } + + var canAdd = addPath && addPath.newPos + 1 < newLen, + canRemove = removePath && 0 <= oldPos && oldPos < oldLen; + if (!canAdd && !canRemove) { + // If this path is a terminal then prune + bestPath[diagonalPath] = undefined; + continue; + } + + // Select the diagonal that we want to branch from. We select the prior + // path whose position in the new string is the farthest from the origin + // and does not pass the bounds of the diff graph + if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { + basePath = clonePath(removePath); + self.pushComponent(basePath.components, undefined, true); + } else { + basePath = addPath; // No need to clone, we've pulled it from the list + basePath.newPos++; + self.pushComponent(basePath.components, true, undefined); + } + + oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); + + // If we have hit the end of both strings, then we are done + if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + return done(buildValues(basePath.components, newString, oldString, self.useLongestToken)); + } else { + // Otherwise track this path as a potential candidate and continue. + bestPath[diagonalPath] = basePath; + } + } + + editLength++; + } + + // Performs the length of edit iteration. Is a bit fugly as this has to support the + // sync and async mode which is never fun. Loops over execEditLength until a value + // is produced. + if (callback) { + (function exec() { + setTimeout(function() { + // This should not happen, but we want to be safe. + /*istanbul ignore next */ + if (editLength > maxEditLength) { + return callback(); + } + + if (!execEditLength()) { + exec(); + } + }, 0); + }()); + } else { + while (editLength <= maxEditLength) { + var ret = execEditLength(); + if (ret) { + return ret; + } + } + } + }, + + pushComponent: function(components, added, removed) { + var last = components[components.length - 1]; + if (last && last.added === added && last.removed === removed) { + // We need to clone here as the component clone operation is just + // as shallow array clone + components[components.length - 1] = {count: last.count + 1, added: added, removed: removed }; + } else { + components.push({count: 1, added: added, removed: removed }); + } + }, + extractCommon: function(basePath, newString, oldString, diagonalPath) { + var newLen = newString.length, + oldLen = oldString.length, + newPos = basePath.newPos, + oldPos = newPos - diagonalPath, + + commonCount = 0; + while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) { + newPos++; + oldPos++; + commonCount++; + } + + if (commonCount) { + basePath.components.push({count: commonCount}); + } + + basePath.newPos = newPos; + return oldPos; + }, + + equals: function(left, right) { + var reWhitespace = /\S/; + return left === right || (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)); + }, + tokenize: function(value) { + return value.split(''); + } + }; + + var CharDiff = new Diff(); + + var WordDiff = new Diff(true); + var WordWithSpaceDiff = new Diff(); + WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) { + return removeEmpty(value.split(/(\s+|\b)/)); + }; + + var CssDiff = new Diff(true); + CssDiff.tokenize = function(value) { + return removeEmpty(value.split(/([{}:;,]|\s+)/)); + }; + + var LineDiff = new Diff(); + + var TrimmedLineDiff = new Diff(); + TrimmedLineDiff.ignoreTrim = true; + + LineDiff.tokenize = TrimmedLineDiff.tokenize = function(value) { + var retLines = [], + lines = value.split(/^/m); + for (var i = 0; i < lines.length; i++) { + var line = lines[i], + lastLine = lines[i - 1], + lastLineLastChar = lastLine && lastLine[lastLine.length - 1]; + + // Merge lines that may contain windows new lines + if (line === '\n' && lastLineLastChar === '\r') { + retLines[retLines.length - 1] = retLines[retLines.length - 1].slice(0, -1) + '\r\n'; + } else { + if (this.ignoreTrim) { + line = line.trim(); + // add a newline unless this is the last line. + if (i < lines.length - 1) { + line += '\n'; + } + } + retLines.push(line); + } + } + + return retLines; + }; + + var PatchDiff = new Diff(); + PatchDiff.tokenize = function(value) { + var ret = [], + linesAndNewlines = value.split(/(\n|\r\n)/); + + // Ignore the final empty token that occurs if the string ends with a new line + if (!linesAndNewlines[linesAndNewlines.length - 1]) { + linesAndNewlines.pop(); + } + + // Merge the content and line separators into single tokens + for (var i = 0; i < linesAndNewlines.length; i++) { + var line = linesAndNewlines[i]; + + if (i % 2) { + ret[ret.length - 1] += line; + } else { + ret.push(line); + } + } + return ret; + }; + + var SentenceDiff = new Diff(); + SentenceDiff.tokenize = function(value) { + return removeEmpty(value.split(/(\S.+?[.!?])(?=\s+|$)/)); + }; + + var JsonDiff = new Diff(); + // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a + // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: + JsonDiff.useLongestToken = true; + JsonDiff.tokenize = LineDiff.tokenize; + JsonDiff.equals = function(left, right) { + return LineDiff.equals(left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1')); + }; + + var JsDiff = { + Diff: Diff, + + diffChars: function(oldStr, newStr, callback) { return CharDiff.diff(oldStr, newStr, callback); }, + diffWords: function(oldStr, newStr, callback) { return WordDiff.diff(oldStr, newStr, callback); }, + diffWordsWithSpace: function(oldStr, newStr, callback) { return WordWithSpaceDiff.diff(oldStr, newStr, callback); }, + diffLines: function(oldStr, newStr, callback) { return LineDiff.diff(oldStr, newStr, callback); }, + diffTrimmedLines: function(oldStr, newStr, callback) { return TrimmedLineDiff.diff(oldStr, newStr, callback); }, + + diffSentences: function(oldStr, newStr, callback) { return SentenceDiff.diff(oldStr, newStr, callback); }, + + diffCss: function(oldStr, newStr, callback) { return CssDiff.diff(oldStr, newStr, callback); }, + diffJson: function(oldObj, newObj, callback) { + return JsonDiff.diff( + typeof oldObj === 'string' ? oldObj : JSON.stringify(canonicalize(oldObj), undefined, ' '), + typeof newObj === 'string' ? newObj : JSON.stringify(canonicalize(newObj), undefined, ' '), + callback + ); + }, + + createTwoFilesPatch: function(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader) { + var ret = []; + + if (oldFileName == newFileName) { + ret.push('Index: ' + oldFileName); + } + ret.push('==================================================================='); + ret.push('--- ' + oldFileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader)); + ret.push('+++ ' + newFileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader)); + + var diff = PatchDiff.diff(oldStr, newStr); + diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier + + // Formats a given set of lines for printing as context lines in a patch + function contextLines(lines) { + return map(lines, function(entry) { return ' ' + entry; }); + } + + // Outputs the no newline at end of file warning if needed + function eofNL(curRange, i, current) { + var last = diff[diff.length - 2], + isLast = i === diff.length - 2, + isLastOfType = i === diff.length - 3 && current.added !== last.added; + + // Figure out if this is the last line for the given file and missing NL + if (!(/\n$/.test(current.value)) && (isLast || isLastOfType)) { + curRange.push('\\ No newline at end of file'); + } + } + + var oldRangeStart = 0, newRangeStart = 0, curRange = [], + oldLine = 1, newLine = 1; + for (var i = 0; i < diff.length; i++) { + var current = diff[i], + lines = current.lines || current.value.replace(/\n$/, '').split('\n'); + current.lines = lines; + + if (current.added || current.removed) { + // If we have previous context, start with that + if (!oldRangeStart) { + var prev = diff[i - 1]; + oldRangeStart = oldLine; + newRangeStart = newLine; + + if (prev) { + curRange = contextLines(prev.lines.slice(-4)); + oldRangeStart -= curRange.length; + newRangeStart -= curRange.length; + } + } + + // Output our changes + curRange.push.apply(curRange, map(lines, function(entry) { + return (current.added ? '+' : '-') + entry; + })); + eofNL(curRange, i, current); + + // Track the updated file position + if (current.added) { + newLine += lines.length; + } else { + oldLine += lines.length; + } + } else { + // Identical context lines. Track line changes + if (oldRangeStart) { + // Close out any changes that have been output (or join overlapping) + if (lines.length <= 8 && i < diff.length - 2) { + // Overlapping + curRange.push.apply(curRange, contextLines(lines)); + } else { + // end the range and output + var contextSize = Math.min(lines.length, 4); + ret.push( + '@@ -' + oldRangeStart + ',' + (oldLine - oldRangeStart + contextSize) + + ' +' + newRangeStart + ',' + (newLine - newRangeStart + contextSize) + + ' @@'); + ret.push.apply(ret, curRange); + ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); + if (lines.length <= 4) { + eofNL(ret, i, current); + } + + oldRangeStart = 0; + newRangeStart = 0; + curRange = []; + } + } + oldLine += lines.length; + newLine += lines.length; + } + } + + return ret.join('\n') + '\n'; + }, + + createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { + return JsDiff.createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader); + }, + + applyPatch: function(oldStr, uniDiff) { + var diffstr = uniDiff.split('\n'), + hunks = [], + i = 0, + remEOFNL = false, + addEOFNL = false; + + // Skip to the first change hunk + while (i < diffstr.length && !(/^@@/.test(diffstr[i]))) { + i++; + } + + // Parse the unified diff + for (; i < diffstr.length; i++) { + if (diffstr[i][0] === '@') { + var chnukHeader = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/); + hunks.unshift({ + start: chnukHeader[3], + oldlength: +chnukHeader[2], + removed: [], + newlength: chnukHeader[4], + added: [] + }); + } else if (diffstr[i][0] === '+') { + hunks[0].added.push(diffstr[i].substr(1)); + } else if (diffstr[i][0] === '-') { + hunks[0].removed.push(diffstr[i].substr(1)); + } else if (diffstr[i][0] === ' ') { + hunks[0].added.push(diffstr[i].substr(1)); + hunks[0].removed.push(diffstr[i].substr(1)); + } else if (diffstr[i][0] === '\\') { + if (diffstr[i - 1][0] === '+') { + remEOFNL = true; + } else if (diffstr[i - 1][0] === '-') { + addEOFNL = true; + } + } + } + + // Apply the diff to the input + var lines = oldStr.split('\n'); + for (i = hunks.length - 1; i >= 0; i--) { + var hunk = hunks[i]; + // Sanity check the input string. Bail if we don't match. + for (var j = 0; j < hunk.oldlength; j++) { + if (lines[hunk.start - 1 + j] !== hunk.removed[j]) { + return false; + } + } + Array.prototype.splice.apply(lines, [hunk.start - 1, hunk.oldlength].concat(hunk.added)); + } + + // Handle EOFNL insertion/removal + if (remEOFNL) { + while (!lines[lines.length - 1]) { + lines.pop(); + } + } else if (addEOFNL) { + lines.push(''); + } + return lines.join('\n'); + }, + + convertChangesToXML: function(changes) { + var ret = []; + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); + } + + ret.push(escapeHTML(change.value)); + + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); + } + } + return ret.join(''); + }, + + // See: http://code.google.com/p/google-diff-match-patch/wiki/API + convertChangesToDMP: function(changes) { + var ret = [], + change, + operation; + for (var i = 0; i < changes.length; i++) { + change = changes[i]; + if (change.added) { + operation = 1; + } else if (change.removed) { + operation = -1; + } else { + operation = 0; + } + + ret.push([operation, change.value]); + } + return ret; + }, + + canonicalize: canonicalize + }; + + /*istanbul ignore next */ + /*global module */ + if (typeof module !== 'undefined' && module.exports) { + module.exports = JsDiff; + } else if (typeof define === 'function' && define.amd) { + /*global define */ + define([], function() { return JsDiff; }); + } else if (typeof global.JsDiff === 'undefined') { + global.JsDiff = JsDiff; + } +}(this)); + +},{}],68:[function(require,module,exports){ +'use strict'; + +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; + +module.exports = function (str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + + return str.replace(matchOperatorsRe, '\\$&'); +}; + +},{}],69:[function(require,module,exports){ +(function (process){ +// Growl - Copyright TJ Holowaychuk (MIT Licensed) + +/** + * Module dependencies. + */ + +var exec = require('child_process').exec + , fs = require('fs') + , path = require('path') + , exists = fs.existsSync || path.existsSync + , os = require('os') + , quote = JSON.stringify + , cmd; + +function which(name) { + var paths = process.env.PATH.split(':'); + var loc; + + for (var i = 0, len = paths.length; i < len; ++i) { + loc = path.join(paths[i], name); + if (exists(loc)) return loc; + } +} + +switch(os.type()) { + case 'Darwin': + if (which('terminal-notifier')) { + cmd = { + type: "Darwin-NotificationCenter" + , pkg: "terminal-notifier" + , msg: '-message' + , title: '-title' + , subtitle: '-subtitle' + , priority: { + cmd: '-execute' + , range: [] + } + }; + } else { + cmd = { + type: "Darwin-Growl" + , pkg: "growlnotify" + , msg: '-m' + , sticky: '--sticky' + , priority: { + cmd: '--priority' + , range: [ + -2 + , -1 + , 0 + , 1 + , 2 + , "Very Low" + , "Moderate" + , "Normal" + , "High" + , "Emergency" + ] + } + }; + } + break; + case 'Linux': + cmd = { + type: "Linux" + , pkg: "notify-send" + , msg: '' + , sticky: '-t 0' + , icon: '-i' + , priority: { + cmd: '-u' + , range: [ + "low" + , "normal" + , "critical" + ] + } + }; + break; + case 'Windows_NT': + cmd = { + type: "Windows" + , pkg: "growlnotify" + , msg: '' + , sticky: '/s:true' + , title: '/t:' + , icon: '/i:' + , priority: { + cmd: '/p:' + , range: [ + -2 + , -1 + , 0 + , 1 + , 2 + ] + } + }; + break; +} + +/** + * Expose `growl`. + */ + +exports = module.exports = growl; + +/** + * Node-growl version. + */ + +exports.version = '1.4.1' + +/** + * Send growl notification _msg_ with _options_. + * + * Options: + * + * - title Notification title + * - sticky Make the notification stick (defaults to false) + * - priority Specify an int or named key (default is 0) + * - name Application name (defaults to growlnotify) + * - image + * - path to an icon sets --iconpath + * - path to an image sets --image + * - capitalized word sets --appIcon + * - filename uses extname as --icon + * - otherwise treated as --icon + * + * Examples: + * + * growl('New email') + * growl('5 new emails', { title: 'Thunderbird' }) + * growl('Email sent', function(){ + * // ... notification sent + * }) + * + * @param {string} msg + * @param {object} options + * @param {function} fn + * @api public + */ + +function growl(msg, options, fn) { + var image + , args + , options = options || {} + , fn = fn || function(){}; + + // noop + if (!cmd) return fn(new Error('growl not supported on this platform')); + args = [cmd.pkg]; + + // image + if (image = options.image) { + switch(cmd.type) { + case 'Darwin-Growl': + var flag, ext = path.extname(image).substr(1) + flag = flag || ext == 'icns' && 'iconpath' + flag = flag || /^[A-Z]/.test(image) && 'appIcon' + flag = flag || /^png|gif|jpe?g$/.test(ext) && 'image' + flag = flag || ext && (image = ext) && 'icon' + flag = flag || 'icon' + args.push('--' + flag, quote(image)) + break; + case 'Linux': + args.push(cmd.icon, quote(image)); + // libnotify defaults to sticky, set a hint for transient notifications + if (!options.sticky) args.push('--hint=int:transient:1'); + break; + case 'Windows': + args.push(cmd.icon + quote(image)); + break; + } + } + + // sticky + if (options.sticky) args.push(cmd.sticky); + + // priority + if (options.priority) { + var priority = options.priority + ''; + var checkindexOf = cmd.priority.range.indexOf(priority); + if (~cmd.priority.range.indexOf(priority)) { + args.push(cmd.priority, options.priority); + } + } + + // name + if (options.name && cmd.type === "Darwin-Growl") { + args.push('--name', options.name); + } + + switch(cmd.type) { + case 'Darwin-Growl': + args.push(cmd.msg); + args.push(quote(msg)); + if (options.title) args.push(quote(options.title)); + break; + case 'Darwin-NotificationCenter': + args.push(cmd.msg); + args.push(quote(msg)); + if (options.title) { + args.push(cmd.title); + args.push(quote(options.title)); + } + if (options.subtitle) { + args.push(cmd.subtitle); + args.push(quote(options.subtitle)); + } + break; + case 'Darwin-Growl': + args.push(cmd.msg); + args.push(quote(msg)); + if (options.title) args.push(quote(options.title)); + break; + case 'Linux': + if (options.title) { + args.push(quote(options.title)); + args.push(cmd.msg); + args.push(quote(msg)); + } else { + args.push(quote(msg)); + } + break; + case 'Windows': + args.push(quote(msg)); + if (options.title) args.push(cmd.title + quote(options.title)); + break; + } + + // execute + exec(args.join(' '), fn); +}; + +}).call(this,require('_process')) +},{"_process":51,"child_process":41,"fs":41,"os":50,"path":41}],70:[function(require,module,exports){ +(function (process){ +var path = require('path'); +var fs = require('fs'); +var _0777 = parseInt('0777', 8); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, opts, f, made) { + if (typeof opts === 'function') { + f = opts; + opts = {}; + } + else if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + p = path.resolve(p); + + xfs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), opts, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, opts, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + xfs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, opts, made) { + if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 & (~process.umask()); + } + if (!made) made = null; + + p = path.resolve(p); + + try { + xfs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), opts, made); + sync(p, opts, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = xfs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; + +}).call(this,require('_process')) +},{"_process":51,"fs":41,"path":41}],71:[function(require,module,exports){ +(function (process,global){ +/** + * Shim process.stdout. + */ + +process.stdout = require('browser-stdout')(); + +var Mocha = require('../'); + +/** + * Create a Mocha instance. + * + * @return {undefined} + */ + +var mocha = new Mocha({ reporter: 'html' }); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date; +var setTimeout = global.setTimeout; +var setInterval = global.setInterval; +var clearTimeout = global.clearTimeout; +var clearInterval = global.clearInterval; + +var uncaughtExceptionHandlers = []; + +var originalOnerrorHandler = global.onerror; + +/** + * Remove uncaughtException listener. + * Revert to original onerror handler if previously defined. + */ + +process.removeListener = function(e, fn){ + if ('uncaughtException' == e) { + if (originalOnerrorHandler) { + global.onerror = originalOnerrorHandler; + } else { + global.onerror = function() {}; + } + var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn); + if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); } + } +}; + +/** + * Implements uncaughtException listener. + */ + +process.on = function(e, fn){ + if ('uncaughtException' == e) { + global.onerror = function(err, url, line){ + fn(new Error(err + ' (' + url + ':' + line + ')')); + return !mocha.allowUncaught; + }; + uncaughtExceptionHandlers.push(fn); + } +}; + +// The BDD UI is registered by default, but no UI will be functional in the +// browser without an explicit call to the overridden `mocha.ui` (see below). +// Ensure that this default UI does not expose its methods to the global scope. +mocha.suite.removeAllListeners('pre-require'); + +var immediateQueue = [] + , immediateTimeout; + +function timeslice() { + var immediateStart = new Date().getTime(); + while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) { + immediateQueue.shift()(); + } + if (immediateQueue.length) { + immediateTimeout = setTimeout(timeslice, 0); + } else { + immediateTimeout = null; + } +} + +/** + * High-performance override of Runner.immediately. + */ + +Mocha.Runner.immediately = function(callback) { + immediateQueue.push(callback); + if (!immediateTimeout) { + immediateTimeout = setTimeout(timeslice, 0); + } +}; + +/** + * Function to allow assertion libraries to throw errors directly into mocha. + * This is useful when running tests in a browser because window.onerror will + * only receive the 'message' attribute of the Error. + */ +mocha.throwError = function(err) { + Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) { + fn(err); + }); + throw err; +}; + +/** + * Override ui to ensure that the ui functions are initialized. + * Normally this would happen in Mocha.prototype.loadFiles. + */ + +mocha.ui = function(ui){ + Mocha.prototype.ui.call(this, ui); + this.suite.emit('pre-require', global, null, this); + return this; +}; + +/** + * Setup mocha with the given setting options. + */ + +mocha.setup = function(opts){ + if ('string' == typeof opts) opts = { ui: opts }; + for (var opt in opts) this[opt](opts[opt]); + return this; +}; + +/** + * Run mocha, returning the Runner. + */ + +mocha.run = function(fn){ + var options = mocha.options; + mocha.globals('location'); + + var query = Mocha.utils.parseQuery(global.location.search || ''); + if (query.grep) mocha.grep(new RegExp(query.grep)); + if (query.fgrep) mocha.grep(query.fgrep); + if (query.invert) mocha.invert(); + + return Mocha.prototype.run.call(mocha, function(err){ + // The DOM Document is not available in Web Workers. + var document = global.document; + if (document && document.getElementById('mocha') && options.noHighlighting !== true) { + Mocha.utils.highlightTags('code'); + } + if (fn) fn(err); + }); +}; + +/** + * Expose the process shim. + * https://github.com/mochajs/mocha/pull/916 + */ + +Mocha.process = process; + +/** + * Expose mocha. + */ + +global.Mocha = Mocha; +global.mocha = mocha; + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../":1,"_process":51,"browser-stdout":40}]},{},[71]); diff --git a/recursos/open-sans.zip b/recursos/open-sans.zip new file mode 100644 index 0000000..45385d6 Binary files /dev/null and b/recursos/open-sans.zip differ diff --git a/seeder.sh b/seeder.sh new file mode 100644 index 0000000..36abbb5 --- /dev/null +++ b/seeder.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env sh + +FORCE=true node index.js && sequelize db:seed:all --url postgres://${DB_PASSWORD}:${DB_USUARIO}@${DB_HOST}:${DB_PUERTO}/${DB_NOMBRE} --seeders-path src/seeders diff --git a/src/auth.js b/src/auth.js new file mode 100644 index 0000000..c15da36 --- /dev/null +++ b/src/auth.js @@ -0,0 +1,39 @@ +const passport2 = require("passport"); +const Strategy = require("passport-jwt").Strategy; +const ExtractJwt = require("passport-jwt").ExtractJwt; + +module.exports = app => { + + const Funcionarios = app.src.db.models.Funcionarios; + + const cfg = app.src.config.config; + const params = { + secretOrKey: cfg.jwtSecret, + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + }; + + + const strategy = new Strategy(params, (payload, done) => { + Funcionarios.findByUid(payload.id) + .then(funcionario => { + if (funcionario) { + return done(null, { + id: funcionario.uid, + }); + } + return done(null, false); + }) + .catch(error => { + console.log("Error stategy ldap", error); + done(error, null); + }); + }); + + + passport2.use(strategy); + + return { + initialize: () => passport2.initialize(), + authenticate: () => passport2.authenticate("jwt", cfg.jwtSession), + }; +}; diff --git a/src/bl/monitor/monitorBL.js b/src/bl/monitor/monitorBL.js new file mode 100644 index 0000000..6aeea46 --- /dev/null +++ b/src/bl/monitor/monitorBL.js @@ -0,0 +1,90 @@ +const Promise = require('bluebird'); +const Uuid = require('uuid'); +const moment = require('moment'); +module.exports = { + /** + * Método que realiza la creación o actualización de los registros monitor, + * cuando un usuario visita un determinado documento + * @param {Modelos} pModelo Modelos de la base de datos. + * @param {Objeto} pLog Objeto con información sobre la visita en curso. + * @return {Promesa} + */ + registrarVisita:(pModelo, pLog) => { + // Agrega a la informacion de visita la fecha actual. + pLog.fecha_visita = moment().tz("America/La_Paz").format("YYYY-MM-DD"); + + // Almacena un clon del vector ip. + const ip = pLog.ip; + + // Agrega a la informacion de visita el vector de ip's en modo texto. + pLog.ip = JSON.stringify(pLog.ip); + + // Instancia el modelo monitor, responsable de registrar visitas. + const Monitor = pModelo.monitor; + + // Instancia un nuevo objeto. + const datos={}; + + // Instancia una nueva promesa. + return new Promise((resolve, reject) => { + + // Realiza la busqueda, con relacion a la visita actual. + Monitor.findOne({ + where:{ + fid_usuario:pLog.fid_usuario, + fid_documento:pLog.fid_documento, + }, + }) + .then(pMon => { + // Si se encuentra registrada la visita. + if(pMon){ + + // Transforma las ip regitrada en modo texto a vector. + const ips= JSON.parse(pMon.ip); + + let c=0; + + // Itera las IP's obtenidas en la visita actual. + for(let i=0; i0){ + // Actualiza la información de la visita. + pLog._usuario_modificacion=pLog.fid_usuario; + pLog.contador=pMon.dataValues.contador+1; + + // Actualiza la información de la visita + return pMon.update(pLog).then(() => resolve()); + }else { + + // Actualiza la información de la visita a registrar. + pLog.contador=1; + pLog._usuario_creacion=pLog.fid_usuario; + + // Registra la visita. + return Monitor.create(pLog).then(() => resolve()); + + } + + } + // Si no se encuentra registrada la visita. + else{ + + // Actualiza la información de la visita a registrar. + pLog.contador=1; + pLog._usuario_creacion=pLog.fid_usuario; + // pLog['fecha_visita']= moment().tz("America/La_Paz").format("YYYY-MM-DD"); + + // Registra la visita. + return Monitor.create(pLog).then(() => resolve()) + } + }) + .catch(pError => { + console.log("Error al crear el registro del monitor", pError); + resolve() + }) + }) + }, +}; diff --git a/src/bl/plantillasFormly/catalogoBL.js b/src/bl/plantillasFormly/catalogoBL.js new file mode 100644 index 0000000..7088e6c --- /dev/null +++ b/src/bl/plantillasFormly/catalogoBL.js @@ -0,0 +1,222 @@ +require('colors'); +const _ = require('lodash'); +const util = require('../../lib/util'); +const hash = require('object-hash'); + + +module.exports = { + filtrarDocumentosRelacionados: (modelos, lista, id_usuario, tr) => { + const Documento = modelos.documento; + + return new Promise((resolve, reject) => { + + }); + }, + + obtenerInfoDocumentos: (modelos, lista) => { + const Documento = modelos.documento; + const documentosRespuesta = []; + const promesas = lista.map(item => new Promise((resolve) => Documento.findOne({ + attributes: ['id_documento', 'nombre', 'fecha'], + where: { + id_documento: item.fid_documento, + }, + }) + .then(respDocumento => { + if (!respDocumento) throw Error ('El documento no existe'); + const temp = JSON.parse(JSON.stringify(item)); + temp.nombre = respDocumento.dataValues.nombre; + temp.nombre_pdf = `${util.formatoNombreDoc(temp.nombre)}.pdf`; + documentosRespuesta.push(temp); + return resolve(); + }) + .catch(() => resolve()))); + + return Promise.all(promesas) + .then(() => Promise.resolve(documentosRespuesta)) + .catch(error => Promise.reject(error)); + }, + + obtenerInfoUsuarios: (modelos, lista) => { + const Usuario = modelos.usuario; + const usuariosRespuesta = []; + const promesas = lista.map(item => new Promise((resolve) => Usuario.findOne({ + attributes: ['id_usuario', 'nombres', 'apellidos', 'cargo'], + where: { + id_usuario: item.fid_usuario, + }, + }) + .then(respusuario => { + if (!respusuario) throw Error ('El usuario no existe'); + const temp = JSON.parse(JSON.stringify(item)); + temp.nombres = respusuario.nombres; + temp.apellidos = respusuario.apellidos; + temp.cargo = respusuario.cargo; + usuariosRespuesta.push(temp); + return resolve(); + }) + .catch(() => resolve()))); + + return Promise.all(promesas) + .then(() => Promise.resolve(usuariosRespuesta)) + .catch(() => Promise.reject('No se pudo obtener resultados')); + }, + + tieneRelacion: (documento, usuario) => { + const de = JSON.parse(documento.de) || []; + const via = JSON.parse(documento.via) || []; + const via_actual = documento.via_actual; + const para = JSON.parse(documento.para) || []; + const id = usuario.id_usuario; + return new Promise((resolve) => { + if ((de.indexOf(id) > -1) || (via.indexOf(id) > -1) || (para.indexOf(id) > -1) || (via_actual == id)) return resolve(true); + else return resolve(false); + }); + }, + + validarMultiple: (lista, usuario) => { + let existeRelacion = false; + const promesas = lista.map(item => module.exports.tieneRelacion(item, usuario) + .then(resp => { + if (resp == true) existeRelacion = true; + }) + .catch(error => {})); + + return Promise.all(promesas) + .then(() => Promise.resolve(existeRelacion)); + }, + + validarRelacionDocumento: (modelos, documento, usuario) => { + const Documento = modelos.documento; + return new Promise((resolve, reject) => module.exports.tieneRelacion(documento, usuario) + .then(resp => { + console.log('Revisando la relacion', resp); + + if (resp == true) return resolve(resp); + return Documento.findAll({ + attributes: ['id_documento', 'nombre', '_usuario_creacion', '_usuario_modificacion', 'firmaron', 'via_actual', 'de', 'via', 'para', 'grupo'], + where: { + grupo: documento.grupo, + }, + }); + }) + .then(respDocumentos => module.exports.validarMultiple(respDocumentos, usuario)) + .then((respMultiple) => resolve(respMultiple)) + .catch(() => reject('Error en la busqueda de documentos'))); + }, + + crearActualizarDocumentos: (modelos, lista, catalogo, tr) => { + const promesas = lista.map(item => new Promise((resolve, reject) => { + if (!item.id_catalogo_documento) { + return module.exports.crearCatalogoDocumento(modelos, item, catalogo, tr) + .then(() => resolve()) + .catch(error => reject(error)); + } + return module.exports.actualizarCatalogoDocumento(modelos, item, catalogo, tr) + .then(() => resolve()) + .catch(error => reject(error)); + })); + + return Promise.all(promesas) + .then(() => Promise.resolve()) + .catch(() => Promise.reject()); + }, + + crearCatalogoDocumento: (modelos, datos, catalogo, tr) => { + const Documento = modelos.documento; + const CatalogoDocumento = modelos.catalogo_documento; + const opcionesDocumento = { + attributes: ['id_documento', 'nombre', '_usuario_creacion', '_usuario_modificacion', 'firmaron', 'via_actual', 'de', 'via', 'para', 'grupo'], + where: { + id_documento: datos.fid_documento, + }, + }; + return new Promise((resolve,reject) => Documento.findOne(opcionesDocumento, tr) + .then(respDocumento => module.exports.tieneRelacion(respDocumento, catalogo.audit_usuario)) + .then(respRelacion => { + console.log('revisando la relacion'.white, respRelacion) + if (respRelacion == false) throw Error('El documento no presenta relacion con el usuario'); + datos.fid_catalogo = catalogo.id_catalogo; + if (!datos._usuario_creacion) datos._usuario_creacion = catalogo.audit_usuario.id_usuario; + return CatalogoDocumento.create(datos, tr); + }) + .then(() => resolve()) + .catch(error => reject(error))); + }, + + actualizarCatalogoDocumento: (modelos, datos, catalogo, tr) => { + const CatalogoDocumento = modelos.catalogo_documento; + return new Promise((resolve, reject) => CatalogoDocumento.findOne({ + where: { + id_catalogo_documento: datos.id_catalogo_documento, + fid_catalogo: catalogo.id_catalogo, + _usuario_creacion: catalogo.audit_usuario.id_usuario, + }, + }, tr) + .then(resp => { + if(!resp) throw Error('El catalogo a actualizar no se encuentra disponible'); + return resp.update(datos, tr); + }) + .then(() => resolve()) + .catch(error => reject(error))); + }, + + crearActualizarUsuarios: (modelos, lista, catalogo, tr) => { + const promesas = lista.map(item => new Promise((resolve) => { + if (!item.id_catalogo_usuario) { + return module.exports.crearCatalogoUsuario(modelos, item, catalogo, tr) + .then(() => resolve()) + .catch(() => resolve()); + } + return module.exports.actualizarCatalogoUsuario(modelos, item, catalogo, tr) + .then(() => resolve()) + .catch(() => resolve()); + })); + return Promise.all(promesas) + .then(() => Promise.resolve()) + .catch(error => Promise.reject(error)); + }, + + crearCatalogoUsuario: (modelos, datos, catalogo, tr) => { + const opcionesUsuario = { + attributes: ['id_usuario', 'nombres', 'apellidos'], + where: { + id_usuario: datos.fid_usuario, + }, + }; + const CatalogoUsuario = modelos.catalogo_usuario; + const Usuario = modelos.usuario; + return new Promise((resolve, reject) => Usuario.findOne(opcionesUsuario, tr) + .then(respUsuario => { + const usuarioEntrante = hash({ + id_usuario: datos.fid_usuario, + nombres: datos.nombres, + apellidos: datos.apellidos, + }); + const usuarioBuscado = hash(respUsuario.dataValues); + if (usuarioEntrante !== usuarioBuscado) return resolve(); + datos._usuario_creacion = catalogo.audit_usuario.id_usuario; + datos.fid_catalogo = catalogo.id_catalogo; + return CatalogoUsuario.create(datos, tr) + }) + .then(() => resolve()) + .catch(error => reject(error))); + }, + + actualizarCatalogoUsuario: (modelos, datos, catalogo, tr) => { + const CatalogoUsuario = modelos.catalogo_usuario; + return new Promise((resolve, reject) => CatalogoUsuario.findOne({ + where: { + id_catalogo_usuario: datos.id_catalogo_usuario, + fid_usuario: datos.fid_usuario, + _usuario_creacion: catalogo.audit_usuario.id_usuario, + }, + }, tr) + .then(resp => { + if (!resp) throw Error('El usuario a actulizar para el catalogo no se encuentra disponible'); + return resp.update({estado: datos.estado}, tr) + }) + .then(() => resolve()) + .catch(error => reject(error))); + }, +}; \ No newline at end of file diff --git a/src/bl/plantillasFormly/documentoBL.js b/src/bl/plantillasFormly/documentoBL.js new file mode 100644 index 0000000..8a1c120 --- /dev/null +++ b/src/bl/plantillasFormly/documentoBL.js @@ -0,0 +1,1835 @@ +require('colors'); +const Promise = require('bluebird'); +const Uuid = require('uuid'); +const Archivo = require('../../lib/archivos'); +const sequelize = require('sequelize'); +const moment = require('moment'); +const _ = require('lodash'); +const Util = require('../../lib/util'); +const notificar = require('../../lib/notificacion'); +const config = require('../../config/config')(); +const dirDocumento = config.ruta_documentos; +const blm = require('../monitor/monitorBL'); +const libAlmacen = require('../../lib/almacen'); +const libActivos = require('../../lib/activos'); +const Op = require('sequelize').Op; + +module.exports = { + + + actualizarDocumento: (pDocumento, pDatos, pModeloHistorial, tr) => + new Promise((resolve, reject) => + pDocumento.update(pDatos, tr) + .then(pDoc => { + const flag=(pDatos.estado == 'DERIVADO' && pDatos.via_actual == pDatos._usuario_modificacion)? false:true; + + if(flag ){ + pModeloHistorial.create({ + id_documento:pDoc.id_documento, + accion:pDatos.estado, + observacion:(pDatos.observaciones)?pDatos.observaciones:'', + _usuario_creacion:pDatos._usuario_modificacion, + }, tr) + .then(pResultado => resolve(pResultado)) + } + else resolve(); + + }) + .catch(pError => reject(pError)) + ), + + /** + * Función que realiza el cierre de un documento y el flujo. + * @param {Object} pModeloDocumento Objeto Sequelize del modelo de datos documento + * @param {Object} pModeloHistorial Objeto Sequelize del modelo de datos historial_flujo + * @param {Object} pDocumento Objeto con informacion sobre el documento + * @param {Number} pUsuario Identificador del usuario que realiza el cambio + * @return {Promise} Promesa. + */ + cerrarDocumento: (pModelos, pDocumento, pUsuario, tr, Sequelize) => { + + const datosActualizar = { + estado:'CERRADO', + _usuario_modificacion:pUsuario, + }; + // if(pDocumento.firmante_actual === null) datosActualizar.firmante_actual = pDocumento.firmante_actual; + return new Promise((resolve, reject) => { + if(pDocumento.grupo){ + pModelos.documento.findAll({ + where: { + grupo: pDocumento.grupo, + estado: { + [Op.notIn]: ['ELIMINADO', 'CERRADO'], + }, + }, + order: [['_fecha_creacion','ASC']], + }) + .then( pRespuesta => { + if(!Array.isArray(pRespuesta)) pRespuesta = [pRespuesta]; + return resolve(Promise.each(pRespuesta, (it) => { + const remitentes = JSON.parse(it.de); + delete datosActualizar.firmante_actual; + if(it.firmante_actual === null && it.firmaron === null) { + datosActualizar.firmante_actual = remitentes[0]; + } + return module.exports.actualizarDocumento(it, datosActualizar, pModelos.historial_flujo, tr); + })); + }) + .catch( pError => reject(pError)) + }else { + resolve(true) + } + + }) + }, + + buscarHijos:(pModeloDocumento,pDocumento) => + new Promise((resolve, reject) => pModeloDocumento.findAll({ + where:{documento_padre:pDocumento.dataValues.id_documento}, + }) + .then(pResultado => {(pResultado.length > 0)?resolve(true):resolve(false)}) + .catch(pError => reject(pError)) + ), + + eliminarDocumento: (pIdUsuario, pIdDocumento, pModelo, pModeloHistorial) => { + const condicion={}; + if(pIdUsuario!=null || pIdUsuario!=undefined) condicion._usuario_creacion=pIdUsuario + if(pIdDocumento!=null || pIdDocumento!=undefined) condicion.id_documento=pIdDocumento + return new Promise((resolve, reject) => pModelo.findOne({where:condicion}) + .then(pResultado => { + + if(pResultado != null){ + if(pResultado.estado=='NUEVO' || pResultado.estado=='RECHAZADO'){ + return module.exports.actualizarDocumento(pResultado, + { + estado:'ELIMINADO', + _usuario_modificacion: pIdUsuario, + documento_padre: -pResultado.documento_padre, + }, pModeloHistorial) + } + else throw new Error("La modificacion no esta disponible en este momento."); + } + else throw new Error("El documento solicitado no existe"); + }) + .then(() => resolve()) + .catch(pError => reject(pError))) + + }, + + documento_enviar: (modeloHistorialFlujo, doc, tr, pDirector) => + new Promise( (resolve, reject) => { + const via = JSON.parse(doc.via); + const para = JSON.parse(doc.para); + let viaActual = 0, i; + const form = JSON.parse(doc.plantilla); + + let aprobarPorDireccion = false; + for (let f = 0; f < form.length; f++) { + if (form[f].type == "datosGenerales" && form[f].templateOptions) { + aprobarPorDireccion = form[f].templateOptions.aprobarPorDireccion; + break; + } + } + + if (aprobarPorDireccion && via.length==0) { + viaActual = pDirector; + } else { + if (via.length>0) { + viaActual = via[0]; + } else { + viaActual = para[0]; + } + } + + doc.update({ + via_actual: viaActual, + estado: 'ENVIADO', + usuario_modificacion: doc._usuario_creacion, + }, tr) + .then(doc => + modeloHistorialFlujo.create({ + id_documento:doc.id_documento, + accion: 'ENVIADO', + observacion: '', + estado: 'ACTIVO', + _usuario_creacion: doc._usuario_creacion, + }, tr) + ) + .then( resu => resolve(resu)) + .catch( e => reject(e)); + }), + + /** + * Función que crea el registro en el historial + * @param {Modelo} modeloHistorialFlujo Instancia del modelo de datos del historial + * @param {Número} idDocumento Identificador del documento + * @param {Número} idUsuario Identificador del usuario que realiza la acción + * @param {Objeto} tr Instancia de la transacción en curso + * @return {Promesa} Retorna una promesa + */ + documento_crear: (modeloHistorialFlujo, idDocumento, idUsuario, tr) => + new Promise( (resolve, reject) => { + modeloHistorialFlujo.create({ + id_documento:idDocumento, + accion:'CREADO', + observacion:'', + _usuario_creacion:idUsuario, + }, tr) + .then( resu => resolve(resu)) + .catch( e => reject(e)); + }), + + /** + * Función que actualiza el identificador del grupo de un documento. + * @param {Modelo} modeloDocumento Modelo de datos del documento + * @param {Objeto} doc Instancia del documento + * @param {Objeto} tr Instancia de la transacción en curso + * @return {Promesa} Retorna una promesa. + */ + actualizarGrupo: (modeloDocumento, doc, tr) => + new Promise( (resolve, reject) => { + if(doc.documento_padre){ + modeloDocumento.findByPk(doc.documento_padre) + .then( doc_padre => doc.update({grupo: doc_padre.grupo}, tr)) + .then( resu => resolve(resu)) + .catch( e => reject(e)); + }else { + doc.update({grupo: doc.id_documento}, tr) + .then( resu => resolve(resu)) + .catch( e => reject(e)); + } + }), + + /** + * Método que crea fisicamente los base64 que se le envien. + * @param {VECTOR} pVector Contiene un vector de objetos, los cuales traen consigo un base64. + * @param {TEXTO} pRuta Cadena de texto con la ruta destino. + * @return {VECTOR} Retorna el vector de objetos actualizados, sin base64. + */ + crearExternos: (pVector, pRuta) => { + + const externos = pVector.map(pItem => { + + const data = pItem.base64; + + if(data!== undefined){ + const tipo = pItem.filetype.substr(pItem.filetype.indexOf('/')+1,pItem.filetype.length); + + pItem.nombre_privado= `${Uuid.v4()}.${tipo}`; + pItem.nombre_publico=`${pItem.filename}`; + pItem.url= `${pRuta.substr(1,pRuta.length)}/${pItem.nombre_privado}`; + delete pItem.base64; + + return Archivo.crearArchivo(pRuta, new Buffer(data, "base64"), pItem.nombre_publico, tipo, pItem.nombre_privado, true) + .then(pRespuesta => Promise.resolve()) + .catch(pError => Promise.reject(pError)); + } + else { + return Promise.resolve(); + } + + }); + + return Promise.all(externos) + .then(() => Promise.resolve(pVector)) + .catch(pError => Promise.reject(pError)); + }, + /** + * Función que verifica la existencia de archivos externos, + * si hay los crea fisicamente en el servidor. + * @param {OBJETO} pDatos Objeto que contiene los datos de un documento. Entre los cuales se encuentran documentos externos. + * @param {TEXTO} pRuta Cadena de texto que contiene la ruta donde se almacena los documentos. + * @return {TEXTO} Retorna un objeto transformado en texto en caso de que existan, de lo contrario nada. + */ + verificarExternos: (pDatos, pRuta) => { + + let tieneAdjuntos=false; + let documentos=[]; + + return new Promise((resolve, reject) => { + + if(pDatos.plantilla_valor){ + const valores= JSON.parse(pDatos.plantilla_valor); + + for (const i in valores) { + if(i.search('archivo') > -1){ + tieneAdjuntos=true; + documentos=documentos.concat(valores[i]); + } + } + if(tieneAdjuntos){ + module.exports.crearExternos(documentos, pRuta) + .then(pRespuesta => resolve(JSON.stringify(valores))) + .catch(pError => reject(pError)); + } + else{ + resolve(); + } + } + else { + resolve(); + } + + }); + + }, + + /** + * Función que verifica la existencia del componente cajachica, + * si hay los crea físicamente en la base de datos del servidor. + * @param {ENTERO} idUsuario Identificador del usuario de sesión. + * @param {MODELO} pPartida Modelo sequelizede partida.. + * @param {OBJETO} valores Retorna un objeto transformado en texto en caso de que existan, de lo contrario nada. + * @return {TEXTO} Retorna un objeto transformado en texto en caso de que existan, de lo contrario nada. + */ + + crearModificarPartidas: (idUsuario, pPartida, valores, tieneCite) => { + + let partidas = [], par; + + return new Promise((resolve, reject) => { + // solo se creara si el documento tiene el componente cajachica y no tenga cite + // la creacion sera para todos los tipos de partidas + if (!tieneCite && valores['cajachica-0']) { + + // llevamos las filas en un array con formato de la tabla partida + valores['cajachica-0'].rows.forEach( it => { + par = { + cite: valores['cite-0']['cite'], + numero: typeof it.partida=='object'? it.partida.numero : it.partida, + descripcion: it.descripcion, + monto: it.monto, + gestion: moment().tz("America/La_Paz").year(), + tipo: valores['cajachica-0']['tipo'], + _usuario_creacion: idUsuario, + }; + if (valores['cajachica-0'].tipo=='PAGADO') { + par.fid_partida = it.id_comprometido; + par.cite_ref = it.cite.nombre; + if (it.pago_multiple) { + par.fid_partida = (toFloat(it.monto)==toFloat('0.00'))? it.id_comprometido : null; + par.multiple = it.id_comprometido; + } + } + partidas.push(par); + }); + + // el parametro reurning hace que nos devuelva los ids de las partidas creadas + pPartida.bulkCreate(partidas, {returning: true}) + .then(pRespuesta => { + // asignamos el id a los valores del documento + for (let i = 0; i < pRespuesta.length; i++) + valores['cajachica-0'].rows[i].id = pRespuesta[i].id_partida; + + if (valores['cajachica-0'].tipo=='PAGADO') { + // si la creacion es de pagados actualizaremos el fid_partida de su comprometido + + // ordenar pagos de mayor a menor y hacerlos de uno en uno + partidas = _.sortBy( valores['cajachica-0'].rows, row => -toFloat(row.monto) ); + Promise.each(partidas, it => { + // si no es pago_multiple o es monto 0.00 actualizaremos el fid_partida de su comprometido + if ( !it.pago_multiple || toFloat(it.monto)==toFloat('0.00')) + pPartida.update({ fid_partida: it.id }, { + where: { + id_partida: it.id_comprometido, + tipo: 'COMPROMETIDO', + }, + }); + // si es pago_multiple y es ultimo pago 0.00 actualizaremos todos loa pagos + if ( it.pago_multiple && toFloat(it.monto)==toFloat('0.00')) + pPartida.update({ fid_partida:it.id }, { + where: { + id_partida:{ [Op.ne]:it.id }, + multiple: it.id_comprometido, + tipo: 'PAGADO', + }, + }) + }) + + } else if (valores['cajachica-0'].tipo=='COMPROMETIDO') { + // si la creacion es de comprometidos, + // se verifica que el comprometido es de pago_multiple multiple, si es true => se actualiza su columna multiple con su id + partidas = valores['cajachica-0'].rows.map( it => { + if (it.pago_multiple) { + pPartida.findByPk(it.id) + .then( comp => comp.update({ multiple: comp.id_partida})) + .then( comp => Promise.resolve()) + .catch( err => Promise.resolve()) + } else + Promise.resolve() + }); + Promise.all(partidas); + } + + }) + .then( pRespuesta => { + resolve(valores); + }) + .catch(pError => { + resolve(); + }); + + } else return resolve(); + }); + + function toFloat(string) { return parseFloat(parseFloat(string).toFixed(2)); } + }, + + /** + * Función que se encarga de verficar estado de las partidas para cada caso, si existe el componente caja chica + * @param {MODELO} pPartida Modelo sequelizede partida.. + * @param {OBJETO} valores Retorna un objeto transformado en texto en caso de que existan, de lo contrario nada. + */ + verificarPartidas: (pPartida, valores) => { + let + partidas = [], + modificados = [], + pagados = [], + comprometidos = [], + saldo, num; + const + xnumeros = [], + partidas_obj = {}, + modificados_obj = {}, + pagados_obj = {}, + comprometidos_obj = {}, + xnumeros_obj = {}, + saldos= {}, + anioActual = `${moment().tz("America/La_Paz").year()}`; + + return new Promise((resolve, reject) => { + if (valores['cajachica-0']) { + + if ( typeof valores['cajachica-0'] == 'object' ){ + if (valores['cajachica-0'].tipo == 'INICIAL') verificarExistenciaIniciales(); + else if (valores['cajachica-0'].tipo == 'COMPROMETIDO' || valores['cajachica-0'].tipo == 'MODIFICADO') verificarMontosPartidas(); + else if (valores['cajachica-0'].tipo == 'PAGADO') verificarExistenciaPagados(); + else reject("Los datos enviados de partidas, son incorrectos"); + } else reject("Los datos enviados de partidas, son incorrectos"); + + } else return resolve(); + + // verificamos que los montos no excedan de las partidas + function verificarMontosPartidas () { + valores['cajachica-0'].rows.forEach( row => { + + if (!xnumeros_obj[row.partida.numero]) { + xnumeros.push(row.partida.numero); + xnumeros_obj[row.partida.numero] = { numero:row.partida.numero, monto:toFloat(row.monto) }; + } else { + xnumeros_obj[row.partida.numero].monto += toFloat(row.monto); + } + }); + + pPartida.findAll({ + attributes: ['id_partida', 'numero', 'monto'], + where: { + numero: {[Op.in]:xnumeros}, + tipo: 'INICIAL', + gestion: anioActual, + estado: 'ACTIVO', + }, + raw: true, + }) + .then( resp => { + partidas = resp; + return pPartida.findAll({ + attributes: ['numero', [sequelize.fn('SUM',sequelize.fn('COALESCE', (sequelize.col('monto')), 0)), 'monto']], + where: { + numero: { [Op.in]:xnumeros }, + tipo: 'MODIFICADO', + gestion: anioActual, + estado: 'ACTIVO', + }, + group: 'numero', + raw: true, + }) + }) + .then( resp => { + modificados = resp; + return pPartida.findAll({ + attributes: ['numero', [sequelize.fn('SUM',sequelize.fn('COALESCE', (sequelize.col('monto')), 0)), 'monto']], + where: { + numero: { [Op.in]:xnumeros }, + tipo: 'COMPROMETIDO', + gestion: anioActual, + fid_partida: null, //los comprometidos que no fueron paagados + estado: 'ACTIVO', + }, + group: 'numero', + raw: true, + }) + }) + .then( resp => { + comprometidos = resp; + return pPartida.findAll({ + attributes: ['numero', [sequelize.fn('SUM',sequelize.fn('COALESCE', (sequelize.col('monto')), 0)), 'monto']], + where: { + numero: { [Op.in]:xnumeros }, + tipo: 'PAGADO', + gestion: anioActual, + fid_partida: {[Op.ne]:null}, + estado: 'ACTIVO', + }, + group: 'numero', + raw: true, + }) + + }) + .then( resp => { + pagados = resp; + arrToObj(partidas, partidas_obj, 'numero'); + arrToObj(pagados, pagados_obj, 'numero'); + arrToObj(comprometidos, comprometidos_obj, 'numero'); + arrToObj(modificados, modificados_obj, 'numero'); + + xnumeros.forEach( num => { + if(!saldos[num]) saldos[num] = {}; + saldo = toFloat( getMonto(partidas_obj, num) - getMonto(comprometidos_obj,num) - getMonto(pagados_obj,num) + getMonto(modificados_obj,num) ); + saldos[num].saldoInicial = saldo; + if( valores['cajachica-0'].tipo == 'COMPROMETIDO') { + if ((saldo-getMonto(xnumeros_obj,num))<0) { + newError(`La partida número ${num} no cuenta con saldo suficiente para el requerimiento.
    + Saldo actual < monto total requerido
    + ${saldo} < ${getMonto(xnumeros_obj,num)}`); + } + else { + saldos[num].saldoFinal = saldo - getMonto(xnumeros_obj, num); + saldos[num].montoComprometido = getMonto(xnumeros_obj, num); + } + } else if( valores['cajachica-0'].tipo == 'MODIFICADO') { + if (getMonto(xnumeros_obj,num)<0){ + + if ((saldo+getMonto(xnumeros_obj,num))<0) { + newError(`La partida número ${num} no cuenta con saldo suficiente para la modificación.
    + Saldo actual < monto total a cambiar
    + ${saldo} < ${getMonto(xnumeros_obj,num)}`); + } + } + } + }) + // throw new Error('---------Error generado manual --------------------'); + + resolve(saldos); + }) + .catch( err => { console.log(err); reject('Ocurrio un error al verificar el presupuesto')}) + } + + // verifica que no se inicien dos partidas con el mismo numero para una gestion + function verificarExistenciaIniciales() { + valores['cajachica-0'].rows.forEach( row => { + if (!xnumeros_obj[row.partida]) { + xnumeros.push(row.partida); + xnumeros_obj[row.partida] = true; + } + }); + + pPartida.findAll({ + where: { + numero: {[Op.in]:xnumeros}, + tipo: 'INICIAL', + gestion: anioActual, + estado: 'ACTIVO', + }, + limit:3, + raw: true, + }) + .then( resp => { + // throw new Error('---------Error generado manual --------------------'); + if (resp.length==0) { + resolve(); + } + newError(`La partida número ${resp[0].numero} ya existe.
    Partida: ${resp[0].numero} - ${resp[0].descripcion}`); + }) + .catch( err => { console.log(err); reject('Ocurrio un error al verificar las partidas')}) + } + + function verificarExistenciaPagados() { + valores['cajachica-0'].rows.forEach( row => { + + if (pagados_obj[row.id_comprometido] && !row.pago_multiple) { + newError(`El pago:
    + -cite: ${row.cite.nombre}
    + -partida: ${row.partida.num_des}
    + No debe repetirse, por favor verifique los datos enviados.`); + } + + if (row.pago_multiple) { + if (!pagados_obj[row.id_comprometido]) { + pagados.push(row.id_comprometido); // pagados multiples + pagados_obj[row.id_comprometido] = row; + pagados_obj[row.id_comprometido].pago_total = 0; + } + pagados_obj[row.id_comprometido].pago_total += toFloat(row.monto); + } + + comprometidos.push(row.id_comprometido); // todos + + if (toFloat(row.saldo? row.saldo : row.comprometido) + -cite: ${row.cite.nombre}
    + -partida: ${row.partida.num_des}
    + -detalle: ${row.descripcion}.
    + Excede el ${row.saldo? 'saldo' : 'monto comprometido'}.
    + ${row.saldo? 'saldo' : 'comprometido'} < pagado
    + ${row.saldo? row.saldo : row.comprometido} < ${row.monto}.`); + } + }); + + // buscamos a los compromeidos que fueron pagados + pPartida.findAll({ + where: { + fid_partida: {[Op.in]:comprometidos}, + tipo: 'PAGADO', + estado: 'ACTIVO', + }, + raw: true, + }) + .then( resp => { + if (resp.length!=0) { + newError(`La partida número ${resp[0].numero} con:
    + -cite: ${resp[0].cite_ref}
    + -detalle: ${resp[0].descripcion}
    + Ya fue pagada en el documento ${resp[0].cite}.`); + } + + // buscamos el total pagado de cada comprometido + return pPartida.findAll({ + attributes: ['multiple', [sequelize.fn('SUM',sequelize.fn('COALESCE', (sequelize.col('monto')), 0)), 'monto']], + where: { + multiple: {[Op.in]:pagados}, + tipo: 'PAGADO', + estado: 'ACTIVO', + }, + group: 'multiple', + raw: true, + }) + }) + .then( pagos => { + if (pagos) { + pagos.forEach( it => { + if (!xnumeros_obj[it.multiple]) { + xnumeros_obj[it.multiple] = it; + } + }); + for (var k in pagados_obj) { + num = pagados_obj[k]; + saldo = toFloat(num.comprometido); + if (xnumeros_obj[num.id_comprometido]) { + saldo -= toFloat(xnumeros_obj[num.id_comprometido].monto); + } + if ( toFloat(num.pago_total) > toFloat(saldo) ) { + newError(`El pago:
    + -número: ${num.partida.numero}
    + -cite: ${num.cite.nombre}
    + -detalle: ${num.descripcion}
    + Excede el saldo del comprometido.
    + Saldo actual < Pago total
    + ${saldo} < ${toFloat(num.pago_total)}`); + } + } + + } + resolve(); + }) + .catch( err => { console.log(err); reject('Ocurrio un error al verificar las partidas')}) + + } + + function newError(msg) { reject(msg); throw new Error(msg); } + + function arrToObj(arr, obj, key) { arr.forEach( row => { if (!obj[row[key]]) { obj[row[key]] = row; }}); } + + function toFloat(string) { return parseFloat(parseFloat(string).toFixed(2)); } + + function getMonto(obj, num) { return (obj && obj[num] && obj[num].monto)? toFloat(obj[num].monto) : 0; } + }); + }, + + /** + * Función que valida la relación de un usuario con un documento. + * @param {Modelo} pModeloDocumento Instancia del modelo de datos para documento + * @param {Modelo} pModeloHistorial Instancia del modelo de datos para historialFlujo + * @param {Objeto} pDocumento Instancia del documento + * @param {Objeto} pUsuario Instancia del usuario solicitante + * @return {Promesa} Retorna una promesa. + */ + validarPeticionGet:(pModeloDocumento, pModeloHistorial, pDocumento, pUsuario) => { + return new Promise((resolve, reject) => { + + if(pDocumento.estado !== 'NUEVO'){ + + const via = JSON.parse(pDocumento.via); + const para = JSON.parse(pDocumento.para); + const de = JSON.parse(pDocumento.de); + module.exports.obtenerDocumentos(pModeloDocumento, pModeloHistorial, pDocumento) + .then(pDocumentos => { + + if(pDocumentos.length > 0 ){ + return pDocumentos.forEach((pDoc, pIndice) => { + + switch (pDocumento.estado) { + case 'CERRADO': + pUsuario.roles.forEach(pRol => { + switch (pRol.rol.nombre) { + case 'OPERADOR': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'CONFIGURADOR': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'JEFE': + if(via.indexOf(pUsuario.id_usuario) > -1 || + para.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario || + pDoc._usuario_creacion == pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'SECRETARIA': + resolve(true); + break; + case 'CORRESPONDENCIA': + if(via.indexOf(pUsuario.id_usuario) > -1 || + para.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario || + pDoc._usuario_creacion == pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + } + }); + break; + case 'ENVIADO': + pUsuario.roles.forEach(pRol => { + switch (pRol.rol.nombre) { + case 'OPERADOR': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'CONFIGURADOR': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'JEFE': + if(via.indexOf(pUsuario.id_usuario) > -1 || + para.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario || + pDoc._usuario_creacion == pUsuario.id_usuario ){ + resolve(true); + } + else resolve(false); + break; + case 'SECRETARIA': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'CORRESPONDENCIA': + if(via.indexOf(pUsuario.id_usuario) > -1 || + para.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario || + pDoc._usuario_creacion == pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + } + }); + break; + case 'RECHAZADO': + pUsuario.roles.forEach(pRol => { + switch (pRol.rol.nombre) { + case 'OPERADOR': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual == pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'CONFIGURADOR': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'JEFE': + if(via.indexOf(pUsuario.id_usuario) > -1 || + para.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario || + pDoc._usuario_creacion == pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'SECRETARIA': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'CORRESPONDENCIA': + if(via.indexOf(pUsuario.id_usuario) > -1 || + para.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + } + }); + break; + case 'DERIVADO': + pUsuario.roles.forEach(pRol => { + switch (pRol.rol.nombre) { + case 'OPERADOR': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'CONFIGURADOR': + if(pDoc._usuario_creacion == pUsuario.id_usuario || + de.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'JEFE': + if(via.indexOf(pUsuario.id_usuario) > -1 || + para.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'CORRESPONDENCIA': + if(via.indexOf(pUsuario.id_usuario) > -1 || + para.indexOf(pUsuario.id_usuario) > -1 || + pDocumento.via_actual==pUsuario.id_usuario){ + resolve(true); + } + else resolve(false); + break; + case 'SECRETARIA': + resolve(true); + break; + } + }); + break; + + } + }); + } else { + resolve(false); + } + + }) + .catch(pError => { + console.log("Error en la obtención de los documentos desde el global", pError); + resolve(false); + }); + + } + else if(pDocumento.estado == 'NUEVO'){ + resolve((pDocumento._usuario_creacion == pUsuario.id_usuario)? true:false); + } + else resolve(false); + }); + + }, + + /** + * Función que obtiene documentos y su historial. + * @param {Modelo} pModeloDocumento Instancia del modelos de datos para documento + * @param {Modelo} pModeloHistorial Instancia del modelos de datos para historial + * @param {Objeto} pDocumento Instancia del documento base + * @return {Promesa} Promesa + */ + obtenerDocumentos: (pModeloDocumento, pModeloHistorial, pDocumento) => + new Promise((resolve, reject) => + module.exports.obtenerIdDocumentos(pModeloDocumento, pDocumento.grupo) + .then(pIds => pModeloHistorial.findAll({where:{id_documento:{[Op.in]:pIds}}}) + .then(pDocumentos => resolve(pDocumentos)) + ) + .catch(pError => { + console.log("Error al buscar en el historial", pError); + reject(pError); + }) + ), + + /** + * Función que obtiene los identificadores de un determinado grupo. + * @param {Modelo} pModeloDocumento Instancia del modelo de datos para documento + * @param {Número} pGrupo Identificador del grupo + * @return {Promesa} Promesa + */ + obtenerIdDocumentos:(pModeloDocumento, pGrupo) => { + const documentos=[]; + + return new Promise((resolve, reject) => + pModeloDocumento.findAll({ + attributes:['id_documento'], + where:{grupo:pGrupo}, + }) + .then(pDocumentos => { + + if(pDocumentos.length > 0){ + return pDocumentos.forEach((pDoc, pIndice) => { + documentos.push(pDoc.id_documento); + if(pIndice === pDocumentos.length-1) resolve(documentos); + }); + } else { + resolve(documentos); + } + }) + .catch(pError => { + console.log("Error al buscar los ids del grupo", pError); + reject(pError); + }) + ); // fin iteracion. + + }, + buscarAnuladores: (datos) => { + let documentosAnular=[]; + let plantilla = datos; + if(typeof datos === 'string') plantilla = JSON.parse(plantilla); + if(Util.verificarJSON(plantilla) === false) return []; + _.mapKeys(plantilla, (valor, llave) => { + if(llave.indexOf('documentosAnular')>-1) documentosAnular.push(plantilla[llave]); + }); + documentosAnular = _.flattenDeep(documentosAnular); + return documentosAnular; + + }, + + anularDocumentos: (pModelos, pDocumento, pRuta, idUsuario, tr) => { + const paraAnular = module.exports.buscarAnuladores(pDocumento.plantilla_valor); + return Util.generarAnulador({cite:pDocumento.nombre}) + .then(bufferAnulador => module.exports.ejecutarAnulacion(paraAnular, pRuta, pModelos, idUsuario, pDocumento,bufferAnulador, tr)); + }, + + ejecutarAnulacion: (documentos, ruta, pModelos, idUsuario, pDocumento, pBuffer, tr) => { + const modeloDocumento = pModelos.documento; + const modeloHistorial = pModelos.historial_flujo; + + const promesas = documentos.map(documento => { + const rutaDocumento = `${ruta}${Util.formatoNombreDoc(documento.nombre)}.pdf`; + return Archivo.anular(rutaDocumento, pBuffer, tr) + .then(() => { + const condicion = { + where: { id_documento: documento.id_documento} + }; + const datos = { + anulado: true, + _usuario_modificacion: idUsuario, + }; + return modeloDocumento.update(datos, condicion, tr); + }) + .then(() => { + const origen = JSON.parse(pDocumento.de)[0]; + const historico = { + id_documento: documento.id_documento, + accion: 'ANULADO', + observacion: pDocumento.nombre, + _usuario_creacion: origen, + _usuario_modificacion: idUsuario, + }; + return modeloHistorial.create(historico, tr); + }) + .then(() => Promise.resolve()) + .catch(error => { + return Promise.reject(); + }); + }); + + return Promise.all(promesas) + .then(() => Promise.resolve()) + .catch((e) => { + console.log("Revisando el error desde la anulación de documentos", e); + return Promise.reject(e); + }); + }, + + validarYaFirmo: (firmantes, firmaron, firmanteActual) => { + const respuesta = {}; + let cont = 0; + const noFirmaron = []; + _.map(firmantes, item => { + if(firmaron.indexOf(item) > -1) cont++; + else noFirmaron.push(item); + }); + if(cont === firmantes.length) respuesta.firmado = true; + else respuesta.firmante_actual = noFirmaron[0]; + + return respuesta; + }, + + crearCodigoFirma: (pModelos, documento, req) => { + let codigo = `${config.prefijo}-${Util.generarCodigo(6, 'A#')}`; + return pModelos.firma.create({ + fid_documento: documento.id_documento, + _usuario_creacion: req.body.audit_usuario.id_usuario, + codigo, + }) + .then(respuesta => { + return respuesta.codigo; + }) + .catch(error => { + console.log("Revisando el error al crear el codigo", error); + }); + }, + + generarCodigo: (pModelos, pDocumento, idUsuario, tr) => { + const codigo = `${config.prefijo}-${Util.generarCodigo(8, 'A#')}`; + const Firma = pModelos.firma; + return new Promise((resolve, reject) => { + return Firma.findOne({ + where: { + codigo, + } + }, tr) + .then(firma => { + if (!firma || firma.length === 0) { + return Firma.create({ + fid_documento: pDocumento.id_documento, + _usuario_creacion: idUsuario, + codigo, + }, tr); + } + }) + .then((firmaResp) => { + + return resolve(firmaResp); + }) + .catch(error => { + console.log('Error en la busqueda de firmas', error); + return reject(error); + }); + }); + + }, + + obtenerCrearHash: (pDocumento, auditUsuario, tr) => { + + const nombreDocumento = Util.formatoNombreDoc(pDocumento.nombre); + const existe = Util.existePdf(nombreDocumento); + const rutaDocumentos = Util.rutaDocumentos(); + if(!existe || existe === false) { + const datos = { + doc: { + nombre: nombreDocumento, + plantilla: pDocumento.plantilla + }, + form_actual: Util.dataToView(JSON.parse(pDocumento.plantilla), JSON.parse(pDocumento.plantilla_valor)), + model_actual: JSON.parse(pDocumento.plantilla_valor), + audit_usuario: auditUsuario, + host: 'hla', + grupo: pDocumento.grupo, + codigo: pDocumento.codigo, + }; + datos.model_actual['cite-0'].fecha = Util.formatearFecha(datos.model_actual['cite-0'].fecha); + + return Util.generarDocumento(datos, true, tr) + .then(() => { + return Util.obtenerHash(nombreDocumento); + }); + } + const hash = Util.obtenerHash(nombreDocumento); + return hash; + }, + + actualizarFirmaHash: (pModelos, pHash, pDoc, idUsuario, tr) => { + return pModelos.firma.update({ + hash: pHash, + _usuario_modificacion: idUsuario, + }, + { + where: { + fid_documento: pDoc.id_documento, + } + }, tr) + .then(() => { + return; + }) + .catch(error => { + console.log("Error en la actualizacion del hash", error); + return; + }); + }, + + + aprobarVia: (modelos, documento, datos) => { + + const via = JSON.parse(documento.via) || []; + const plantilla = JSON.parse(documento.plantilla); + const para = JSON.parse(documento.para)[0]; + const compDatosGenerales = _.find(plantilla, ['type', 'datosGenerales']); + + let viaActual = documento.via_actual; + let aprobarPorDireccion = false; + + if (compDatosGenerales.templateOptions) { + const opcionesComponente = compDatosGenerales.templateOptions; + aprobarPorDireccion = opcionesComponente.aprobarPorDireccion || false; + } + let indiceVia = null; + _.findIndex(via, (item, indice) => { + if (item == viaActual) { + return indiceVia = indice + 1; + } + + }); + + if ((viaActual == via[via.length - 1]) && aprobarPorDireccion) { + viaActual = (viaActual == datos.director)? para: datos.director; + } + else if (via.length == 0 && aprobarPorDireccion) { + if (viaActual == datos.director) viaActual = para; + } + else if ((viaActual == datos.director) && aprobarPorDireccion) { + viaActual = para; + } + else { + viaActual = (indiceVia < via.length)? via[indiceVia]: para; + } + const datosActualizar = { + via_actual: viaActual, + estado: 'ENVIADO', + _usuario_modificacion: datos.usuarioModificacion, + }; + const condActualizar = {where: { id_documento: datos.idDocumento}}; + const datosHistorial= { + id_documento: datos.idDocumento, + accion: 'APROBADO', + observacion: '', + _usuario_creacion: datos.usuarioModificacion, + }; + let datosActualizados = null; + + return documento.update(datosActualizar, condActualizar) + .then(respActualizar => { + datosActualizados = respActualizar; + return modelos.historial_flujo.create(datosHistorial); + }) + .then(() => { + if(datosActualizados.estado == 'ENVIADO') { + // console.log('REALIZAR NOTIFICACION'); + + } + else if (datosActualizados.estado== 'APROBADO') { + // console.log('RETORNANDO OBJETO'); + } + }) + .then(() => datosActualizados) + .catch(error => { + console.log('Error en la aprobacion de VIAS', error); + return error; + + }); + }, + + aprobarParaMultiple: (modelos, documento, datos, req) => { + const datosPlantilla = JSON.parse(documento.plantilla_valor); + const contactos = datosPlantilla['listaContactos-0']; + const documentos = []; + let listaContactos = []; + if (!contactos || contactos.lista) listaContactos = contactos.lista; + _.map(listaContactos, (item, index) => { + const clon = JSON.parse(JSON.stringify(documento)); + const contacto = { + contacto: item.id_contacto, + lista: listaContactos, + }; + const tempValor = JSON.parse(clon.plantilla_valor); + tempValor['listaContactos-0'] = contacto; + clon.plantilla_valor = JSON.stringify(tempValor); + if (index > 0) clon.id_documento = null; + console.log('[documentoBL] Revisando valores para no romper el flujo'.green, clon.grupo, clon.documento_padre ); + documentos.push(clon); + }); + const contador = 0; + return new Promise((resolve, reject) => { + return module.exports.crearAprobarDocumentos(modelos, documentos, datos, req, contador) + .then(resp => resolve()) + .catch(error => { + console.log('Error en la creación y aprobación de documentos', error); + return reject(error); + }); + }); + }, + + crearAprobarDocumentos: (modelos, listaDocumentos, datos, req, indice) => { + + if(indice < listaDocumentos.length) { + + const item = listaDocumentos[indice]; + if (item.id_documento !== null && item.id_documento) { + const datosTemp = JSON.parse(JSON.stringify(datos)); + let documentoBase; + return modelos.documento.findByPk(item.id_documento) + .then(respDoc => { + datosTemp.id_documento = respDoc.id_documento; + documentoBase = respDoc; + return respDoc.update({plantilla_valor: item.plantilla_valor}, {where: {id_documento: item.id_documento}}); + }). + then((r) => module.exports.aprobarPara(modelos, documentoBase, datosTemp, req)) + .then(() => { + indice++; + return module.exports.crearAprobarDocumentos(modelos, listaDocumentos, datos, req, indice); + }); + } + else { + delete item.id_documento; + delete item.grupo; + return modelos.documento.create(item) + .then(documentoResp => { + const datosTemp = JSON.parse(JSON.stringify(datos)); + datosTemp.idDocumento = documentoResp.id_documento; + datos.grupo = documentoResp.id_documento; + return module.exports.aprobarPara(modelos, documentoResp, datos, req); + }) + .then(() => { + indice++ + return module.exports.crearAprobarDocumentos(modelos, listaDocumentos, datos, req, indice); + }); + } + } + else { + return new Promise(resolve => resolve()); + } + + }, + + aprobarPara: (modelos, documento, datos, req) => { + return new Promise((resolve, reject) => { + + const datosPlantilla = JSON.parse(documento.plantilla_valor); + const fecha = moment().tz('America/La_Paz').format(); + const datosActualizar = { + via_actual: datos.viaActual, + _usuario_modificacion: datos.usuarioModificacion, + estado: 'APROBADO', + fecha, + }; + let certificacion = {}; + let firmanteActual = null; + if(datos.derivar == true) datosActualizar.observaciones = datos.observaciones; + if (documento.multiple && documento.multiple != null && documento.multiple.length>5) { + datosActualizar.grupo = documento.id_documento; + } + return module.exports.verificarPartidas(modelos.partida, datosPlantilla) + .then(saldos => { + certificacion = saldos; + return module.exports.obtenerCrearCite(modelos, documento, datos.usuarioModificacion) + }) + .then(citeResp => { + datosActualizar.nombre = citeResp.cite; + datosActualizar.plantilla_valor = JSON.stringify(citeResp.datosPlantilla); + return module.exports.crearModificarPartidas(datos.usuarioModificacion, modelos.partida, citeResp.datosPlantilla, datos.tieneCite); + }) + .then(partidasResp => { + // TODO: Considerar la respuesta de la creación de partidas + if (partidasResp) { + partidasResp['certificacionComprometido-0'] = certificacion; + datosActualizar.plantilla_valor = JSON.stringify(partidasResp); + } + // else { + // // // datosActualizar.plantilla_valor = documento.plantilla_valor; + // } + return module.exports.crearSolicitudAlmacen(modelos, datosActualizar, documento.id_documento); + }) + .then(() => { + console.log('[documentoBL] verificando si tiene el componente para ingreso de materiales'); + return module.exports.crearIngresoAlmacen(modelos, datosActualizar, documento.id_documento); + }) + .then(() => { + return module.exports.notificarEntregaAlmacen(modelos, datosActualizar, documento.id_documento); + }) + .then(() => { + console.log('[documentoBL] +++++++++++++++++++++++++++++++++++++++++++++++++++++++'.red); + console.log('[documentoBL] +++++++++++++++++++++++++++++++++++++++++++++++++++++++'.red); + console.log('[documentoBL] +++++++++++++++++++++++++++++++++++++++++++++++++++++++'.red); + console.log('[documentoBL] +++++++++++++++++++++++++++++++++++++++++++++++++++++++'.yellow); + console.log('[documentoBL] +++++++++++++++++++++++++++++++++++++++++++++++++++++++'.yellow); + return module.exports.asignarActivo(modelos, datosActualizar, documento.id_documento); + }) + .then(() => { + console.log('[documentoBL] +++++++++++++++++++++++++++++++++++++++++++++++++++++++'.white); + console.log('[documentoBL] antes de actualizar', datosActualizar); + return module.exports.actualizarDocumento(documento, datosActualizar, modelos.historial_flujo); + }) + .then(actualizacionResp => { + return module.exports.generarCodigo(modelos, actualizacionResp, datos.usuarioModificacion); + }) + .then(codigoResp => { + documento.codigo = codigoResp.codigo; + + const remitentes = JSON.parse(documento.de); + if (Array.isArray(remitentes) && remitentes.length > 0 && documento.dataValues.firmaron === null) { + firmanteActual = remitentes[0]; + } + + if(datos.derivar === true) { + const datosDerivar = { + estado: 'DERIVADO', + via_actual: datos.usuarioDerivar, + observaciones: datos.observaciones, + _usuario_modificacion: datos.usuarioModificacion, + firmante_actual: firmanteActual, + }; + return module.exports.actualizarDocumento(documento, datosDerivar, modelos.historial_flujo) + .then(() => { + // TODO: registrar la visita en los logs de monitoreo + const rmip = req.connection.remoteAddress; + const miIp = rmip.substr(rmip.lastIndexOf(':') + 1, rmip.length); + const log = { + fid_usuario: datos.usuarioModificacion, + fid_documento: documento.id_documento, + cite: true, + ip: [miIp], + }; + return blm.registrarVisita(modelos, log); + }) + .then(() => notificar.enviar(modelos, documento, 'derivado', {})) + .then(() => notificar.enviar(modelos, documento, 'aprobado', {})); + } + + return module.exports.cerrarDocumento(modelos, documento, datos.usuarioModificacion) + // TODO: Falta el registro de la visita + .then(() => notificar.enviar(modelos, documento, 'aprobado', {})); + }) + .then(() => module.exports.anularDocumentos(modelos, documento, dirDocumento, datos.usuarioModificacion)) + .then(() => module.exports.obtenerCrearHash(documento, datos.auditUsuario)) + .then(hashResp => { + return module.exports.actualizarFirmaHash(modelos, hashResp, documento, datos.usuarioModificacion) + }) + .then(() => { + return resolve(); + }) + .catch(error => { + console.log('Error en la aprobacion para', error); + // return error; + return reject(error); + }); + }); + + }, + + obtenerCrearCite: (modelos, documento, idUsuario) => { + const citeGuia = config.sistema.cite_principal; + const plantilla = JSON.parse(documento.plantilla); + const datosPlantilla = JSON.parse(documento.plantilla_valor); + const fechaActual = moment().tz('America/La_Paz').format(); + let citeSinNumero = null; + let tieneCite = false; + return modelos.usuario.findOne({ + where: { id_usuario: documento._usuario_creacion }, + include: { model: modelos.unidad, as: 'unidad' }, + }) + .then(usuarioResp => { + const compCite = _.find(plantilla, ['type', 'cite']); + const esCiteGeneral = (compCite.templateOptions.tipo == 'general'); + const unidad = usuarioResp.unidad; + if (!compCite.templateOptions.tipo) throw Error('La plantilla no cuenta con el control de "CITE"'); + if (!unidad) throw Error('El usuario que envió el documento no tiene unidad, solicite al administrador del sistema que le asigne su unidad'); + if (documento.fecha !== undefined && documento.fecha !== null) { + tieneCite = true; + return documento.nombre; + } + if (esCiteGeneral) return (`${citeGuia}/${documento.abreviacion}`); + if (unidad) return `${citeGuia}-${unidad.abreviacion}/${documento.abreviacion}`; + }) + .then(citeResp => { + citeSinNumero = citeResp; + return modelos.correlativo.findOne({ + where: { + abreviacion: citeResp, + anio: `${moment(fechaActual).year()}`, + }, + }); + }) + .then(correlativoResp => { + if(correlativoResp) return correlativoResp; + return modelos.correlativo.create({ + abreviacion: citeSinNumero, + anio: `${moment(fechaActual).year()}`, + valor: 1, + _usuario_creacion: idUsuario, + }); + }) + .then(correlativoResp => { + const cantCeros = config.sistema.cite_ceros - parseInt((`${correlativoResp.valor}`).length); + let correlativoCeros = ''; + for(let i =0; i< cantCeros; i++) correlativoCeros += '0'; + correlativoCeros += correlativoResp.valor; + datosPlantilla['cite-0'] = { + cite: (tieneCite == true) ? citeSinNumero : `${citeSinNumero}/${correlativoCeros}/${correlativoResp.anio}`, + }; + if (datosPlantilla['cite-0'].fecha == undefined) datosPlantilla['cite-0'].fecha = fechaActual; + return correlativoResp.update({ + valor: correlativoResp.valor + 1, + _usuario_modificacion: idUsuario, + }); + }) + .then(correlativoAct => { + const respuesta = { + cite: datosPlantilla['cite-0'].cite, + datosPlantilla, + }; + if(tieneCite === true) respuesta.cite = citeSinNumero; + return respuesta; + }) + .catch(error => { + console.log('revisando el error en la obtencion o generacion del cite'.yellow, error); + + return error; + }); + + }, + + verificarObtenerMultipleX: (datos, tr) => { + // partidasResp['certificacionComprometido-0'] = certificacion; + const respuesta = { + multiple: false, + documentos: [], + }; + return new Promise((resolve, reject) => { + const plantillaValor = JSON.parse(datos.plantilla_valor); + let listaContactos = plantillaValor['listaContactos-0']; + if (plantillaValor['listaContactos-0']) { + listaContactos = listaContactos.lista + } + else { + respuesta.documentos.push(datos); + return resolve(respuesta); + } + if(!listaContactos || listaContactos.length ==0) { + listaContactos = plantillaValor['listaContactos-0'].lista; + respuesta.documentos.push(datos); + return resolve(respuesta); + } + respuesta.multiple = true; + if (!datos.multiple || datos.multiple == null) { + datos.multiple = Util.generarUiid(); + } + _.map(listaContactos, (item) => { + const clon = JSON.parse(JSON.stringify(datos)); + const contacto = { + contacto: item.id_contacto, + lista: listaContactos, + }; + + const tempValor = JSON.parse(clon.plantilla_valor); + + tempValor['listaContactos-0'] = contacto; + // tempValor['listaContactos-0'] = JSON.stringify(contacto); + // console.log('Revisando el tempValor', typeof tempValor); + // tempValor['listaContactos-0'] = tempValor; + clon.plantilla_valor= JSON.stringify(tempValor); + respuesta.documentos.push(clon); + // const tempValor = clon['listaContactos-0'] + }); + return resolve(respuesta); + }); + }, + verificarObtenerMultiple: (datos, tr) => { + const respuesta = { + esMultiple: false, + }; + return new Promise((resolve, reject) => { + const plantillaValor = JSON.parse(datos.plantilla_valor); + const listaContactos = plantillaValor['listaContactos-0']; + if (listaContactos && Array.isArray(listaContactos.lista)) { + respuesta.multiple = Util.generarUiid(); + respuesta.esMultiple = true; + } + return resolve(respuesta); + }); + }, + + crearMultiple: (modelos, datos, tr) => { + const promesas = datos.documentos.map(item => { + let xdoc; + const model = JSON.parse(item.plantilla_valor); + return modelos.documento.create(item, tr) + .then(respDoc => { + xdoc = respDoc; + return module.exports.actualizarGrupo(item, respDoc, tr); + }) + .then(() => { + if(datos.sw.xenviar) { + return module.exports.verificarPartidas(modelos.partida, model); + } + return; + }) + .then(() => { + if (datos.sw.xenviar && datos.sw.es_respuesta) { + return module.exports.documento_crear(modelos.historial_flujo, xdoc.documento_padre, xdoc._usuario_creacion, tr); + } + return; + }) + .then(() => { + if (datos.sw.xenviar) { + return module.exports.documento_enviar(modelos.historial_flujo, xdoc, tr, datos.director) + // .then(() => t.commit()) + .finally(() => datos.notificar.enviar(modelos, xdoc, 'enviado', tr)); + } + }) + .then(() => { + // if (!datos.sw.xenviar) t.commit(); + }); + }); + + return Promise.all(promesas) + .then(respPromesas => { + return Promise.resolve(respPromesas); + }) + .catch(error => { + return Promise.reject(error); + }); + }, + + obtenerDatosUsuario: (modelos, id) => { + return modelos.usuario.findOne({ + attributes: ['id_usuario', 'nombres', 'apellidos', 'email', 'fid_unidad', 'numero_documento', 'cargo'], + where: { + id_usuario: id, + }, + include: [{ + model: modelos.unidad, + as : 'unidad', + attributes: ['nombre'], + }], + }); + }, + + crearSolicitudAlmacen: (modelos, datosActualizar, id) => { + console.log('[crearSolicitudAlmacenBL] Iniciando', id); + console.log('[crearSolicitudAlmacenBL] ================================================================='.red); + console.log('[crearSolicitudAlmacenBL] datosActualizar'.yellow, datosActualizar); + console.log('[crearSolicitudAlmacenBL] datosActualizar'.yellow, typeof datosActualizar.plantilla_valor, datosActualizar.plantilla_valor); + return new Promise((resolve, reject) => { + // TODO: Buscar todos los componentes consultaAlmacen + + // Obtiene los datos del solicitante + const solicitante = {}; + const responsable = {}; + let componente = null; + let cite = null; + const datosPlantilla = JSON.parse(datosActualizar.plantilla_valor); + // Obtiene los items solicitados + let itemsSolicitados = []; + for (const key in datosPlantilla) { + if (key.indexOf('consultaAlmacen-') > -1) { + itemsSolicitados = datosPlantilla[key].filas; + componente = key; + } + if (key.indexOf('cite-') > -1) { + cite = datosPlantilla[key].cite; + } + + if (key.indexOf('datosGenerales-') > -1) { + // TODO: Solicitudes grupales en el sistema de almacenes + const datosGenerales = datosPlantilla[key]; + solicitante.id_usuario = datosGenerales.de[0].id_usuario; + + responsable.id_usuario = datosGenerales.para.id_usuario; + } + } + + if (componente == null) return resolve(datosActualizar); + + return module.exports.obtenerDatosUsuario(modelos, solicitante.id_usuario) + .then(respUsuario => { + if (!respUsuario || !respUsuario.dataValues.nombres ) { + throw Error('Los datos del solicitante no son correctos'); + } + if (!respUsuario || !respUsuario.unidad || !respUsuario.unidad.dataValues.nombre) { + throw Error('El solicitante no pertenece a una unidad'); + } + + console.log('[crearSolicitudAlmacen] revisando datos solicitante', respUsuario.dataValues); + solicitante.nombres = respUsuario.nombres; + solicitante.apellidos = respUsuario.apellidos; + solicitante.numero_documento = respUsuario.numero_documento; + solicitante.cargo = respUsuario.cargo; + solicitante.email = respUsuario.email; + solicitante.unidad = respUsuario.unidad.dataValues.nombre; + delete solicitante.id_usuario; + return module.exports.obtenerDatosUsuario(modelos, responsable.id_usuario); + }) + .then(respUsuario => { + if (!respUsuario || !respUsuario.dataValues.nombres ) { + throw Error('Los datos del solicitante no son correctos'); + } + if (!respUsuario || !respUsuario.unidad || !respUsuario.unidad.dataValues.nombre) { + throw Error('El responsable no pertenece a una unidad'); + } + responsable.nombres = respUsuario.nombres; + responsable.apellidos = respUsuario.apellidos; + responsable.numero_documento = respUsuario.numero_documento; + responsable.cargo = respUsuario.cargo; + responsable.email = respUsuario.email; + responsable.unidad = respUsuario.unidad.dataValues.nombre; + delete responsable.id_usuario; + + return libAlmacen.crearSolicitud(solicitante, responsable, itemsSolicitados, id, cite); + }) + .then(respCreacion => { + console.log('[documentoBL] respuesta a la creacion', respCreacion); + if (!respCreacion || !respCreacion.id) { + throw Error(respCreacion.mensaje); + } + // TODO: Corregir los valores en la integracion con el servicio + datosPlantilla[componente].solicitud = respCreacion.id + // return resolve(); + datosActualizar.plantilla_valor = JSON.stringify(datosPlantilla); + return resolve(datosActualizar); + }) + .catch(error => { + console.log('[documentoBL] error al crear la solicitud del almacen', error); + return reject(error); + }); + }); + }, + crearIngresoAlmacen: (modelos, datosActualizar, id) => { + console.log('[crearIngresoAlmacenBL] Iniciando', id); + return new Promise((resolve, reject) => { + const datosIngresoEnviar = { + reingreso: 0, + responsable: {}, + cabecera: {}, + detalle: { + items: [], + descuento: "0.00", + total: "", + }, + id, + }; + let idSolicitante = 0; + let idResponsable = 0; + + const datosPlantilla = JSON.parse(datosActualizar.plantilla_valor); + // Obtiene los items solicitados + let datosIngreso = null; + let componente = null; + for (const key in datosPlantilla) { + if (key.indexOf('ingresoAlmacen-') > -1) { + datosIngreso = datosPlantilla[key]; + componente = key; + } + + if (key.indexOf('datosGenerales-') > -1) { + // TODO: Existen solicitudes grupales en el sistema de almacenes + const datosGenerales = datosPlantilla[key]; + idResponsable = datosGenerales.de[0].id_usuario; + } + } + + if (componente == null) return resolve(datosActualizar); + if (datosIngreso !== null) { + datosIngresoEnviar.cabecera.proveedor = datosIngreso.proveedor.id; + datosIngresoEnviar.cabecera.c31 = datosIngreso.c31; + datosIngresoEnviar.cabecera.c31_fecha = datosIngreso.c31_fecha; + datosIngresoEnviar.cabecera.nota_entrega_numero = datosIngreso.nota_entrega_numero; + datosIngresoEnviar.cabecera.nota_entrega_fecha = datosIngreso.nota_entrega_fecha; + datosIngresoEnviar.cabecera.factura_numero = datosIngreso.factura_numero; + datosIngresoEnviar.cabecera.factura_autorizacion = datosIngreso.factura_autorizacion; + datosIngresoEnviar.cabecera.factura_fecha = datosIngreso.factura_fecha; + datosIngresoEnviar.detalle.items = datosIngreso.items; + datosIngresoEnviar.detalle.descuento = datosIngreso.descuento; + datosIngresoEnviar.detalle.subtotal = datosIngreso.subtotal; + datosIngresoEnviar.detalle.total = datosIngreso.total; + datosIngresoEnviar.reingreso = datosIngreso.reingreso == true || datosIngreso.reingreso == 'true' ? 1 : 0; + } + + return module.exports.obtenerDatosUsuario(modelos, idResponsable) + .then(respResponsable => { + if (!respResponsable || !respResponsable.dataValues.nombres) { + throw Error('Los datos del solicitante no son correctos'); + } + if (!respResponsable || !respResponsable.unidad || !respResponsable.unidad.dataValues.nombre) { + throw Error('El responsable no pertenece a una unidad'); + } + datosIngresoEnviar.responsable.nombres = respResponsable.nombres; + datosIngresoEnviar.responsable.apellidos = respResponsable.apellidos; + datosIngresoEnviar.responsable.numero_documento = respResponsable.numero_documento; + datosIngresoEnviar.responsable.email = respResponsable.email; + datosIngresoEnviar.responsable.cargo = respResponsable.cargo; + datosIngresoEnviar.responsable.unidad = respResponsable.unidad.dataValues.nombre; + console.log('[crearIngresoAlmacenBL] Revisando los datos obtenidos', datosIngresoEnviar); + return libAlmacen.crearIngreso(datosIngresoEnviar); + }) + .then(respIngreso => { + console.log('[documentoBL] respuesta a la creacion', respIngreso); + if (!respIngreso || !respIngreso.id) { + throw Error(respIngreso.mensaje); + } + datosPlantilla[componente].id_ingreso = respIngreso.id + datosActualizar.plantilla_valor = JSON.stringify(datosPlantilla); + return resolve(datosActualizar); + }) + .catch(error => { + console.log('[documentoBL] error al crear ingreso al almacen', error); + return reject(error); + }); + }); + + }, + + notificarEntregaAlmacen: (modelos, datosActualizar, id) => { + console.log('Iniciando la notificacion al sistema de almacenes'); + return new Promise((resolve, reject) => { + const datosNotificar = { }; + let componente = null; + const datosPlantilla = JSON.parse(datosActualizar.plantilla_valor); + for (const key in datosPlantilla) { + if (key.indexOf('cite-') > -1) { + datosNotificar.cite_ems = datosPlantilla[key].cite; + } + if (key.indexOf('recuperarEntregaAlmacen-') > -1) { + componente = key; + datosNotificar.cite_sms = datosPlantilla[key].cite_sms; + datosNotificar.id = datosPlantilla[key].id_solicitud; + } + } + + if (componente == null) return resolve(datosActualizar); + return libAlmacen.notificar(datosNotificar) + .then(() => resolve()) + .catch(error => reject(error)); + }); + }, + + asignarActivo: (modelos, datosActualizar, id) => { + + console.log('[asignarActivo] Iniciando la asignacion de activos'); + return new Promise((resolve, reject) => { + const datosEnviar = { + estado_usr_nuevo: false, + solicitante: {}, + id_documento: id, + + }; + const idPersonas = { + solicitante: null, + admin: null, + }; + + const datosPlantilla = JSON.parse(datosActualizar.plantilla_valor); + let componenteActivos = null; + let componenteGenerales = null; + for (const key in datosPlantilla) { + if (key.indexOf('tablaActivos-') > -1) { + const datosActivo = datosPlantilla[key] + console.log('[asignarActivo] check data'.green, datosActivo ); + componenteActivos = datosActivo; + // existeComponente = true; + datosEnviar.asset_ids = _.map(datosActivo.filas, 'id'); + datosEnviar.estado_usr_nuevo = datosActivo.usuario_nuevo; + idPersonas.solicitante = datosActivo.documentoDe.id_usuario; + + } + if (key.indexOf('datosGenerales-') > -1) { + const datosGenerales = datosPlantilla[key]; + componenteGenerales = datosGenerales; + console.log('[asignarActivo] datos generales'.green, datosGenerales); + idPersonas.admin = datosGenerales.de[0].id_usuario + } + if (key.indexOf('cite-') > -1) { + datosEnviar.cite = datosPlantilla[key].cite; + datosEnviar.fecha = datosPlantilla[key].fecha; + } + } + console.log('[asignarActivo] Revisando los datos a enviar para la asignacion'.yellow, datosEnviar); + + // TODO: Si el usuario es nuevo obtener los datos + if (componenteActivos === null ) return resolve(); + if (componenteActivos !== null && componenteActivos.tipoFormulario == 'SOLICITUD' ) return resolve(); + + if (componenteActivos.tipoFormularioSeleccionado == 'DEVOLUCION') { + idPersonas.admin = componenteGenerales.para.id_usuario; + idPersonas.solicitante = componenteGenerales.de[0].id_usuario; + } + return modelos.usuario.findOne({ + attributes: ['id_usuario', 'numero_documento'], + where: { + id_usuario: idPersonas.admin, + }, + }) + .then(respAdmin => { + if (!respAdmin) return reject('Los datos del administrador de activos no son correctos'); + console.log('Revisando los datos del admin', respAdmin.dataValues); + datosEnviar.admin_ci = respAdmin.numero_documento; + return modelos.usuario.findOne({ + attributes: ['id_usuario', 'nombres', 'apellidos', 'numero_documento', 'cargo', 'email'], + where: {id_usuario: idPersonas.solicitante }, + include: [ + { + model: modelos.unidad, + as: 'unidad', + }, + ], + }); + }) + .then(respSolicitante => { + if (!respSolicitante) return reject('Los datos del solicitante no son correctos.'); + datosEnviar.user_ci = respSolicitante.numero_documento; + datosEnviar.solicitante.numero_documento = respSolicitante.numero_documento; + datosEnviar.solicitante.nombres = respSolicitante.nombres; + datosEnviar.solicitante.apellidos = respSolicitante.apellidos, + datosEnviar.solicitante.email = respSolicitante.email; + datosEnviar.solicitante.cargo = respSolicitante.cargo; + if (!respSolicitante.unidad) throw Error('El solicitante no pertenece a una unidad.') + datosEnviar.solicitante.unidad = respSolicitante.unidad.dataValues.nombre; + if (datosEnviar.estado_usr_nuevo == true) datosEnviar.user_ci = null; + console.log('[asignarActivo] revisando data', datosEnviar); + console.log('Alto!!!! '.red, componenteActivos); + + if (componenteActivos.tipoFormularioSeleccionado == 'ASIGNACION') return libActivos.asignar(datosEnviar); + if (componenteActivos.tipoFormularioSeleccionado == 'DEVOLUCION') return libActivos.devolver(datosEnviar); + }) + .then(resp => { + console.log('Respuesta de activos', resp); + return resolve() + }) + .catch(error => { + console.log('Error en activos', error); + return reject(error); + }); + + }); + }, +}; diff --git a/src/bl/plantillasFormly/firmadoBL.js b/src/bl/plantillasFormly/firmadoBL.js new file mode 100644 index 0000000..692f586 --- /dev/null +++ b/src/bl/plantillasFormly/firmadoBL.js @@ -0,0 +1,49 @@ +const _ = require('lodash'); + +module.exports = { + procesarFirmas: (usuarios, firmas) => { + return new Promise((resolve,reject) => { + try { + const firmaUsada = []; + const validas = usuarios.map(usuario => { + const nombreUsuario = `${usuario.nombres} ${usuario.apellidos}`.toUpperCase(); + const buscado = _.findIndex(firmas, item => item.nombreComunSubject.toUpperCase() === nombreUsuario); + const obj = { + firmante: nombreUsuario, + firmo: false, + registradoSistema: true, + }; + if (buscado > -1) { + obj.revocado = !firmas[buscado].no_revocado; + obj.fechaFirma = firmas[buscado].fechaFirma; + obj.fechaFinValidez = firmas[buscado].finValidez; + obj.firmo = true; + firmaUsada.push(firmas[buscado]); + } else { + obj.revocado = null; + obj.fechaFirma = null; + obj.fechaFinValidez = null; + } + return obj; + }); + + const firmaNoUsada = _.differenceWith(firmas, firmaUsada, _.isEqual); + const noValidas = firmaNoUsada.map(firma => ({ + firmante: firma.nombreComunSubject.toUpperCase(), + firmo: true, + registradoSistema: false, + revocado: !firma.no_revocado, + fechaFirma: firma.fechaFirma, + fechaFinValidez: firma.finValidez, + })); + let respuesta = validas.concat(noValidas); + respuesta = _.orderBy(respuesta, 'fechaFirma', 'desc') + return resolve(respuesta); + } catch (error) { + console.log('Revisando el error al filtrar las firmas',error); + + return reject(error); + } + }); + }, +}; \ No newline at end of file diff --git a/src/bl/plantillasFormly/plantillasBL.js b/src/bl/plantillasFormly/plantillasBL.js new file mode 100644 index 0000000..5b70970 --- /dev/null +++ b/src/bl/plantillasFormly/plantillasBL.js @@ -0,0 +1,46 @@ +const _ = require('lodash'); +const hash = require('object-hash'); + +module.exports = { + + + validarPlantilla: (plantillas, plantillaValidar) => { + const hashAValidar = hash(JSON.parse(plantillaValidar)); + const estadosValidos= ['ACTIVO']; + let respuesta = false; + let cont = 0; + + _.map(plantillas, item => { + const objTemp = item.dataValues; + if(estadosValidos.indexOf(objTemp.estado) > -1) { + const hashTemp = hash(JSON.parse(objTemp.plantilla)); + if(hashAValidar === hashTemp) cont++; + } + }); + + if(cont > 0) respuesta = true; + return respuesta; + }, + + /** + * Función que actualiza el identificador del grupo de un documento. + * @param {Modelo} modeloDocumento Modelo de datos del documento + * @param {Objeto} doc Instancia del documento + * @param {Objeto} tr Instancia de la transaccion en curso + * @return {Promesa} Retorna una promesa. + */ + actualizarGrupo: (modeloDocumento, doc, tr) => + new Promise( (resolve, reject) => { + if(doc.documento_padre){ + modeloDocumento.findByPk(doc.documento_padre) + .then( doc_padre => doc.update({grupo: doc_padre.grupo}, tr)) + .then( resu => resolve(resu)) + .catch( e => reject(e)); + }else { + doc.update({grupo: doc.id_documento}, tr) + .then( resu => resolve(resu)) + .catch( e => reject(e)); + } + }), + +}; diff --git a/src/bl/seguridad/autorizacion.controller.js b/src/bl/seguridad/autorizacion.controller.js new file mode 100644 index 0000000..b0448ab --- /dev/null +++ b/src/bl/seguridad/autorizacion.controller.js @@ -0,0 +1,308 @@ +const crypto = require('crypto'); +const url = require('url'); +const jwt = require("jwt-simple"); +const util = require('../../lib/util'); +const bl = require('../../bl/seguridad/usuarioBL'); +const Uuid = require('uuid'); +const moment = require('moment'); +const activeDirectory = require('activedirectory'); +const _ = require('lodash'); + +module.exports = (app) => { + const _app = app; + let cliente; + + // configuracion para authenticacion por base de datos + // TODO: Realizar varios archivos de autencicacion para diferentes tecnoclogias OAUTH , OAUT2 que estee encapsulado en este archivo + const usuarios = app.src.db.models.usuario; + const UsuariosRoles = app.src.db.models.usuario_rol; + const Roles = app.src.db.models.rol; + const RolesMenus = app.src.db.models.rol_menu; + const Menus = app.src.db.models.menu; + const cfg = app.src.config.config; + const Unidad = app.src.db.models.unidad; + const AuthUser = app.src.db.models.auth_user; + const ConfNotificacion = app.src.db.models.conf_notificacion; + + + _app.controller = {}; + _app.controller.autorizacion = {}; + const autorizacionController = _app.controller.autorizacion; + + /** + * El método permite obtener el state y nonce para iniciar el flujo oauth 2.0 + * @param {object} req + * @param {object} res + * @returns {JSON} + */ + async function codigo(req, res) { + cliente = cliente || await app.src.openid; + // parámetros necesarios para iniciar el flujo de autenticación + const _state = crypto.randomBytes(16).toString('hex'); + const _nonce = crypto.randomBytes(16).toString('hex'); + + try { + const authorizeUrl = await cliente.authorizationUrl({ + redirect_uri: app.src.config.config.client.redirect_uris[0], + scope: `${app.src.config.config.client_params.scope}`, + state: _state, + nonce: _nonce, + }); + await app.dao.autorizacion.guardarState(_state, { + nonce: _nonce, + }); + return res.status(200).json({ + finalizado: true, + mensaje: '', + datos: { + url: authorizeUrl, + codigo: _state, + }, + }); + } catch (err) { + res.status(412).json({ + finalizado: false, + mensaje: err.message, + datos: {}, + }); + } + } + + /** + * El método permite realizar el intercambio del code por el id_token y access_token + * @param {object} req + * @param {object} res + * @returns {JSON} + */ + async function autorizar(req, res) { + + cliente = cliente || await app.src.openid; + if (req.query.error) { + res.status(412).json({ + finalizado: false, + mensaje: req.query.error, + datos: {}, + }); + } else { + let postUrl = cliente.post_logout_redirect_uris[0]; + try { + const parametros = cliente.callbackParams(req); + if (!parametros.state) throw new Error('Parámetro state es requerido.'); + if (!parametros.code) throw new Error('Parámetro code es requerido.'); + const resultadoState = await app.dao.autorizacion.buscaState(parametros.state); + + if (resultadoState) { + const respuestaCode = await cliente.callback(cliente.redirect_uris[0], parametros, { + nonce: resultadoState.parametros.nonce, + state: resultadoState.state, + }); + resultadoState.tokens = respuestaCode; + const claims = await cliente.userinfo(respuestaCode); + const id_token = respuestaCode.id_token; + + const _user = { + nombre: claims.profile.nombre.nombres, + apellido: `${claims.profile.nombre.primer_apellido} ${claims.profile.nombre.segundo_apellido}`, + email: claims.email, + uid: claims.profile.documento_identidad.numero_documento, + cargo: 'Sin cargo', + numero_documento: claims.profile.documento_identidad.numero_documento, + }; + + postUrl = cliente.endSessionUrl({ + id_token_hint: id_token, + post_logout_redirect_uri: cliente.post_logout_redirect_uris[0] + }); + + const datosJwt = await obtenerJwt(claims.profile.documento_identidad.numero_documento, _user); + const data = util.formatearMensaje("EXITO", "Acceso al sistema correcto", datosJwt.datosTemporal, datosJwt.token); + resultadoState.id_usuario = datosJwt.datosTemporal.user.id; + await app.dao.autorizacion.actualizarTokens(resultadoState); + + res.status(200).json(data); + } else { + console.log('---------------------------State NOT MATCH'); + res.status(412).json({ + finalizado: false, + mensaje: 'El state no coincide', + datos: postUrl, + }); + } + } catch (err) { + console.log('--------------------error autorize ', err); + res.status(412).json({ + finalizado: false, + mensaje: err.message, + datos: postUrl, + }); + } + } + } + + /** + * La función retorna la url para logout del proveedor de identidad + * @param {object} req + * @param {object} res + * @returns {JSON} + */ + async function salir(req, res) { + cliente = cliente || await app.src.openid; + try { + // busqueda para obtener el id_token + const resultadoTokens = await app.dao.autorizacion.buscaToken(req.body.audit_usuario.id_usuario.toString(), req.query.codigo); // validar requerid + if (!resultadoTokens) { + console.log('--------------------------------errpr'); + } + // construcción de la url para la redirección + const postUrl = cliente.endSessionUrl({ + id_token_hint: resultadoTokens.tokens.id_token, + post_logout_redirect_uri: cliente.post_logout_redirect_uris[0] + }); + res.status(200).json({ + finalizado: true, + mensaje: '', + datos: postUrl, + }); + } catch (err) { + res.status(412).json({ + finalizado: false, + mensaje: err.message, + datos: postUrl, + }); + } + } + + async function obtenerJwt(ci, user) { + let menu, rol, usuario; + let roles = []; + const condicion = { + numero_documento: ci, + }; + try { + // const esValidoLdap = await validarConLdap(user); + // if (esValidoLdap.valido == false) throw new Error('Usted no esta autorizado para ingresar al sistema.'); + let pUsuario = await usuarios.findOne({ where: condicion }); + if (!pUsuario) { + // console.log('////////////////// user', user); + + const pRespuesta = await bl.procesaUsuario(user, UsuariosRoles, Unidad, AuthUser, usuarios); + const pConf = await ConfNotificacion.create({ + fid_usuario: pRespuesta.id_usuario, + _usuario_creacion: pRespuesta.id_usuario, + }); + pUsuario = pRespuesta; + } + // Verifica si el usuario existe y esta activo. + usuario = pUsuario; + if (pUsuario.estado !== 'ACTIVO') + throw new Error("Este usuario esta inactivo."); + else { + const pRespuesta2 = await bl.obtenerRoles(UsuariosRoles, Roles, usuario.id_usuario); + const pRespuestaMenu = await bl.obtenerMenus(RolesMenus, Menus, pRespuesta2); + menu = pRespuestaMenu.menu; + roles = pRespuestaMenu.rol; + + const cifrar = { + id_usuario: usuario.id_usuario, + usuario: usuario.usuario, + secret: jwt.encode({ + fecha: moment().tz('America/La_Paz').add(cfg.tiempo_token, 'minutes').format(), + clave: Uuid.v4(), + }, cfg.jwtSecret), + clave: Uuid.v4(), + tiempo: cfg.tiempo_token, + roles, + } + + const usuarioEnviar = { + id: usuario.id_usuario, + username: usuario.usuario, + first_name: usuario.nombres, + last_name: usuario.apellidos, + cargo: usuario.cargo, + doc: usuario.numero_documento, + email: usuario.email, + date_joined: usuario._fecha_creacion, + ldap: true, + } + + const datosTemporal = { + user: usuarioEnviar, + menu: menu.menu, + menuEntrar: menu.menuEntrar, + roles, + } + const token = jwt.encode(cifrar, app.src.config.config.jwtSecret); + const sesion = app.get("sesion"); + + sesion[usuario.id_usuario] = { + fecha: moment(moment().tz('America/La_Paz').format()).add(1, 'minutes'), + backup: null, + token, + } + return { datosTemporal, token }; + } + + } catch (e) { + console.log('**************************** ', e) + throw new Error(e); + } + } + async function validarConLdap(user) { + const respuesta = { + valido: false, + mensaje: '' + }; + const configLdap = { + url: cfg.ldap.server.url, + // baseDN: cfg.ldap.server.baseDn || 'ou=usuarios,dc=agetic,dc=gob,dc=bo', + baseDN: cfg.ldap.server.searchBase, + bindDN: cfg.ldap.server.bindDn, + bindCredentials: cfg.ldap.server.bindCredentials, + attributes: { + user: ['mail', 'givenName', 'sn', 'employeeNumber'] + } + }; + let mensajeError = 'Usted no esta autorizado para ingresar al sistema.'; + let ad; + return new Promise((resolve, reject) => { + try { + ad = new activeDirectory(configLdap); + const query = `employeeNumber=${user.numero_documento}`; + return ad.find(query, (error, respLdap) => { + if (error) { + respuesta.mensaje = 'El servicio de autenticacion única no responde.' + respuesta.valido = false; + return resolve(respuesta); + }; + if (!respLdap) return resolve(respuesta); + // console.log(`Buscando query ${query}`, respLdap); + + _.each(respLdap.other, usuario => { + const email = usuario.mail; + const validar = email.split('@'); + if (validar[1].indexOf('agetic.gob.bo') == -1) { + respuesta.mensaje = 'Usted no esta autorizado para ingresar al sistema.'; + respuesta.valido = false; + return resolve(respuesta); + } + else { + respuesta.valido = true; + } + }); + return resolve(respuesta); + + }); + } catch (e) { + console.log('Error en la validacion LDAP', e); + respuesta.mensaje = e; + respuesta.valido = false; + return resolve(respuesta); + } + }); + } + + autorizacionController.codigo = codigo; + autorizacionController.autorizar = autorizar; + autorizacionController.salir = salir; +}; diff --git a/src/bl/seguridad/autorizacion.dao.js b/src/bl/seguridad/autorizacion.dao.js new file mode 100644 index 0000000..df513dd --- /dev/null +++ b/src/bl/seguridad/autorizacion.dao.js @@ -0,0 +1,73 @@ +module.exports = (app) => { + const _app = app; + _app.dao = {}; + _app.dao.autorizacion = {}; + + const AuthModel = app.src.db.models.auth; + + /** + * Función para guardar los parametros de inicio de flujo para autenticación + * @param {string} _state + * @param {string} _parametros + * @returns {JSON} + */ + async function guardarState(_state, _parametros) { + const datos = await AuthModel.create({ state: _state, parametros: _parametros }); + return datos; + } + + /** + * Función de actualización en el objeto auth + * @param {object} auth + * @returns {JSON} + */ + async function actualizarTokens(auth) { + const authActualizar = { + tokens: auth.tokens, + id_usuario: auth.id_usuario, + estado: 'ACTIVO', + }; + const query = { + where: { + state: auth.state, + estado: 'INICIO', + }, + }; + const datos = await AuthModel.update(authActualizar, query); + return datos; + } + + /** + * Función de busqueda del objeto oauth a partir del parametro codigo=id_usuario + * @param {string} _id_usuario + * @param {string} _state + * @returns {JSON} + */ + async function buscaToken(_id_usuario, _state) { + const datos = await AuthModel.findOne({ + where: { + id_usuario: _id_usuario, + state: _state, + estado: 'ACTIVO', + }, + // order: [['id', 'DESC']], + }); + return datos; + } + + /** + * Función de busqueda del objeto oauth a partir del parametro state + * @param {string} estado + * @returns {JSON} + */ + async function buscaState(estado) { + const datos = await AuthModel.findOne({ where: { state: estado, estado: 'INICIO' } }); + return datos; + } + + + _app.dao.autorizacion.guardarState = guardarState; + _app.dao.autorizacion.buscaState = buscaState; + _app.dao.autorizacion.buscaToken = buscaToken; + _app.dao.autorizacion.actualizarTokens = actualizarTokens; +}; diff --git a/src/bl/seguridad/roles_menusBL.js b/src/bl/seguridad/roles_menusBL.js new file mode 100644 index 0000000..bd530c8 --- /dev/null +++ b/src/bl/seguridad/roles_menusBL.js @@ -0,0 +1,80 @@ +/** + * Archivo pra la lógica de negocio para roles_menus + * - relacionar permisos de menús y acciones + */ + + const Q = require('q'); + +module.exports = { + /** + * Función que relaciona permisos (ver, crear, modificar y eliminar) a un + * rol + * @param {Array} menus Array de objetos de tipo menus + * @param {Array} roles_menus Array de objetos de tipo roles_menus + * @return {Array} Array de objetos de tipo menus con permisos + */ + establecerMenusPermisos: (menus, roles_menus) => { + + const deferred = Q.defer(); + let menu, submenus, submenu; + for(let i = 0; i < menus.length; i++){ + menu = menus[i]; + if(menu.submenu.length > 0){ + submenus = menu.submenu; + for(let j = 0; j < submenus.length; j++){ + submenu = submenus[j]; + for(let k = 0; k < roles_menus.length; k++){ + if(submenu.id_menu == roles_menus[k].fid_menu){ + if(roles_menus[k].method_get) + menus[i].submenu[j].dataValues.get = true; + if(roles_menus[k].method_post) + menus[i].submenu[j].dataValues.post = true; + if(roles_menus[k].method_put) + menus[i].submenu[j].dataValues.put = true; + if(roles_menus[k].method_delete) + menus[i].submenu[j].dataValues.delete = true; + } + } + } + + } + if(i+1 == menus.length){ + deferred.resolve(menus); + } + } + + return deferred.promise + }, + + /** + * [function description] + * @param {Object} rol_menu Objeto rol_menu + * @param {Object} menus Objeto menu + * @return {Object} rol_menu Objeto rol_menu + */ + crearMenusPermisos: (rol_menu, menus) => { + let menu = false; + if(menus.hasOwnProperty('get') && menus.get){ + rol_menu.method_get = true; + menu = true; + } + if(menus.hasOwnProperty('post') && menus.post){ + rol_menu.method_post = true; + menu = true; + } + if(menus.hasOwnProperty('put') && menus.put){ + rol_menu.method_put = true; + menu = true; + } + if(menus.hasOwnProperty('delete') && menus.delete){ + rol_menu.method_delete = true; + menu = true; + } + if(menu){ + return rol_menu; + }else{ + return null; + } + }, + +}; diff --git a/src/bl/seguridad/roles_rutasBL.js b/src/bl/seguridad/roles_rutasBL.js new file mode 100644 index 0000000..3dd1e0b --- /dev/null +++ b/src/bl/seguridad/roles_rutasBL.js @@ -0,0 +1,74 @@ +/** + * Archivo pra la lógica de negocio para roles_rutas + * - relacionar permisos de roles_ruta con acciones de ver, crear, modificar y + * eliminar + */ + + const Q = require('q'); + +module.exports = { + + /** + * Función que relaciona permisos (ver, crear, modificar y eliminar) a un + * rol + * @param {Array} rutas Array de objetos de tipo rutas + * @param {Array} roles_rutas Array de objetos de tipo roles_rutas + * @return {Array} Array de objetos de tipo rutas con permisos + */ + establecerRutasPermisos: (rutas, roles_rutas) => { + const deferred = Q.defer(); + let ruta; + for(let i = 0; i < rutas.length; i++){ + ruta = rutas[i]; + for(let k = 0; k < roles_rutas.length; k++){ + if(ruta.id_ruta == roles_rutas[k].id_ruta){ + if(roles_rutas[k].method_get) + rutas[i].dataValues.get = true; + if(roles_rutas[k].method_post) + rutas[i].dataValues.post = true; + if(roles_rutas[k].method_put) + rutas[i].dataValues.put = true; + if(roles_rutas[k].method_delete) + rutas[i].dataValues.delete = true; + } + } + + if(i+1 == rutas.length){ + deferred.resolve(rutas); + } + } + + return deferred.promise + }, + /** + * [function description] + * @param {Object} rol_ruta Objeto rol_ruta + * @param {Object} rutas Objeto ruta + * @return {Object} rol_ruta Objeto rol_ruta + */ + crearRutasPermisos: (rol_ruta, rutas) => { + let ruta = false; + if(rutas.hasOwnProperty('get') && rutas.get){ + rol_ruta.method_get = true; + ruta = true; + } + if(rutas.hasOwnProperty('post') && rutas.post){ + rol_ruta.method_post = true; + ruta = true; + } + if(rutas.hasOwnProperty('put') && rutas.put){ + rol_ruta.method_put = true; + ruta = true; + } + if(rutas.hasOwnProperty('delete') && rutas.delete){ + rol_ruta.method_delete = true; + ruta = true; + } + if(ruta){ + return rol_ruta; + }else{ + return null; + } + }, + +}; diff --git a/src/bl/seguridad/usuarioBL.js b/src/bl/seguridad/usuarioBL.js new file mode 100644 index 0000000..24c7ba1 --- /dev/null +++ b/src/bl/seguridad/usuarioBL.js @@ -0,0 +1,371 @@ + +const hash = require('object-hash'); +const Promise = require('bluebird'); +const Op = require('sequelize').Op; + +module.exports={ + + /** Función que procesa los datos ldap del usuario. + @param {Objeto} pDatos Objeto que contiene los datos del usuario ldap. + @param {Modelo} pModeloUsuarioRol modelo de datos de la tabla usuario_rol. + @param {Modelo} pModeloUnidad modelo de datos de la tabla unidad. + @param {Modelo} pModeloAuth modelo de datos de la tabla auth_user. + @param {Modelo} pModeloUsuario modelo de datos de la tabla usuario. + */ + procesaUsuario:(pDatos, pModeloUsuarioRol, pModeloUnidad, pModeloAuth, pModeloUsuario) => { + let resultado; + return new Promise((resolve,reject) => { + const insertar={ + // fid_unidad:pUnidad, + usuario:pDatos.uid, + contrasena:'', + numero_documento: pDatos.numero_documento || '11111111', + nombres:pDatos.nombre || 'Nombres', + apellidos:pDatos.apellido, + cargo:pDatos.cargo, + email:pDatos.email || 'email@email.gob.bo', + _usuario_creacion:1, + } + + // Inserta el usuario ldap en la tabla usuario. + return pModeloUsuario.create(insertar) + .then(pRespuesta => { + resultado=pRespuesta; + const insertarUsuarioRol={ + fid_rol:module.exports.obtenerRol(pRespuesta.cargo), + fid_usuario:pRespuesta.id_usuario, + _usuario_creacion:pRespuesta._usuario_creacion, + }; + + // Crea el rol del usuario. + return pModeloUsuarioRol.create(insertarUsuarioRol) + .then(pRol => resolve(resultado)) + .catch(pErrorRol => reject(pErrorRol)) + }) + .catch(pError => reject(pError)) + + }) + }, + + /** Función que obtiene la unidad. + @param {Modelo} pModeloUnidad modelo de datos de la tabla unidad. + @param {Modleo} pModeloAuth modelo de datos de la tabla auth_user. + @param {Texto} pUsuario nombre del usuario. + @return retorna una promesa, con la unidad. + */ + obtenerUnidad: (pModeloUnidad, pModeloAuth, pUsuario) => { + + let unidad=''; + let unidadAux=''; + return new Promise ((resolve, reject) => { + pModeloAuth.findOne({ + attributes:['unidad_dependencia'], + where:{username: pUsuario}, + }) + .then(pRespuestaAuth => + unidadAux=module.exports.quitarAcentos(pRespuestaAuth.dataValues.unidad_dependencia) + ) + .then(() => + pModeloUnidad.findAll({attributes:['nombre', 'id_unidad']}) + .then(pRespuestaUnidad => pRespuestaUnidad.forEach((pItem, pIndice) => { + unidad = module.exports.quitarAcentos(pItem.dataValues.nombre); + if(unidadAux == unidad) resolve(pItem.id_unidad); + else resolve(null); + })) + .catch(pErrorUnidad => reject(pErrorUnidad)) + ) + .catch(pErrorAuth => reject(pErrorAuth)) + }); + + }, + + /** Función que obtiene el rol basado en una cadena de texto que es su cargo. + @param {Texto} pCadena cadena de texto que es el cargo del usuario. + @return {Número} retorna un numero identificador del rol en base a su cargo. + */ + obtenerRol:(pCadena) => { + const texto = pCadena.toLowerCase(); + if(texto.search("responsable") > -1 || texto.search("jefe") > -1 || texto.search("director") > -1) return 2 + else if(texto.search("secretaria") > -1) return 4; + else return 3; + }, + + /** Función que limpia una cadena de texto de acentos + @param {Texto} pCadena cadena de texto con tildes. + @return {Texto} retorna la cadena de texto sin tildes. + */ + quitarAcentos: (pCadena) => { + let cadena = pCadena.toLowerCase(); + + // Quita los acentos. + cadena = cadena.replace(/á/gi,"a"); + cadena = cadena.replace(/é/gi,"e"); + cadena = cadena.replace(/í/gi,"i"); + cadena = cadena.replace(/ó/gi,"o"); + cadena = cadena.replace(/ú/gi,"u"); + + return cadena; + }, + + /** Función que ordena el menu. + @param {Vector} pRolesMenu Vector de objetos, con informacion sobre roles y + menus. + @return {Objeto} Objeto con informacion de los menus y el menu de ingreso. + */ + ordenarMenu:(pRolesMenu) => { + const respuesta={}; + const menusDevolver=[],menusDevolverAux=[]; + let menuEntrar=null; + + for(const r in pRolesMenu){ + const menu = pRolesMenu[r].menu; + const padre = pRolesMenu[r].menu.menu_padre; + const objPadre = JSON.stringify(padre); + let existe = false; + for(let g = 0; g < menusDevolverAux.length; g++){ + if(JSON.stringify(menusDevolverAux[g]) == objPadre){ + existe = true; + break; + } + } + + if(!existe){ + delete padre.estado; + menusDevolverAux.push(padre) + } + else if(menu.fid_menu_padre == null ){ + const menuDatos = JSON.parse(JSON.stringify(menu)); + delete menuDatos.menu_padre; + menusDevolverAux.push(menuDatos); + } + } + + for (const i in menusDevolverAux) { + + const padre = JSON.parse(JSON.stringify(menusDevolverAux[i])); + if(padre != null){ + padre.submenu = []; + for (const j in pRolesMenu) { + + if(padre.id_menu == pRolesMenu[j].menu.fid_menu_padre && + pRolesMenu[j].menu.fid_menu_padre != null){ + + const hijo = JSON.parse(JSON.stringify(pRolesMenu[j].menu)); + delete hijo.menu_padre; + delete hijo.estado; + padre.submenu.push(hijo); + + if(!menuEntrar){ + menuEntrar=`/${hijo.url}`; + } + + } + } + + delete padre.estado; + menusDevolver.push(padre); + } + } + respuesta.menu=menusDevolver; + respuesta.menuEntrar=menuEntrar; + return respuesta; + }, + + /** Función que hace una busqueda en la db para obtener los menus de un rol. + @param {Modelo} pModeloRolMenu modelo de datos de la tabla rol_menu + @param {Modelo} pModeloMenu modelo de datos de la tabla menu + @param {Número} pIdRol identificador del rol, para el cual se obtiene los + menus. + @return Retorna una promesa, la cual retorna el menu del rol. + */ + obtenerMenu:(pModeloRolMenu, pModeloMenu, pIdRol) => + new Promise((resolve, reject) => { + pModeloRolMenu.findAll({ + where:{ + fid_rol:pIdRol, + estado:'ACTIVO', + }, + include:[{ + model:pModeloMenu, + as:'menu', + attributes:[['nombre','label'],['ruta','url'], + ['icono','icon'],'fid_menu_padre','estado'], + where:{estado:'ACTIVO'}, + include:[{ + model:pModeloMenu, + as:'menu_padre', + attributes:['id_menu',['nombre','label'],['ruta','url'], + ['icono','icon'],'estado'], + where:{estado:'ACTIVO'}, + }], + }], + }) + .then(pRolesMenu => resolve(module.exports.ordenarMenu(pRolesMenu))) + .catch(pError => reject(pError)) + }), + + /** Función que busca el rol de mayor peso. + @param {Modelo} pModeloUsuarioRol modelo de datos de la tabla usuario_rol. + @param {Modelo} pModeloRol modelo de datos de la tabla rol. + @param {Número} pIdUsuario identificador del usuario. + @return retorna una promesa, con el rol. + */ + buscarRol: (pModeloUsuarioRol, pModeloRol, pIdUsuario) => + new Promise((resolve, reject) => { + pModeloUsuarioRol.findOne({ + // attributes:['fid_rol'], + where:{ + fid_usuario: pIdUsuario, + estado: 'ACTIVO'}, + include:[{ + model: pModeloRol, + as: 'rol', + order: [['peso','ASC']]}], + }) + .then(pRespuesta => { + if(pRespuesta) resolve(pRespuesta) + else throw new Error("Este usuario no tiene un rol asignado, contacte con el administrador.") + }) + .catch(pError => reject(pError)) + }), + + /** Función que obtiene los roles de un usuario. + @param {Modelo} pModeloUsuarioRol modelo de datos de la tabla usuario_rol. + @param {Modelo} pModeloRol modelo de datos de la tabla rol. + @param {Número} pIdUsuario indentificador del usuario. + @return retorna una promesa, con los roles. + */ + obtenerRoles:(pModeloUsuarioRol, pModeloRol, pIdUsuario) => + new Promise((resolve, reject) => { + pModeloUsuarioRol.findAll({ + attributes:['fid_rol'], + where:{fid_usuario:pIdUsuario, estado:'ACTIVO'}, + include:[{ + attributes:['peso', 'nombre'], + model:pModeloRol, + as:'rol', + where:{estado:'ACTIVO'}, + }], + }) + .then(pRespuesta => resolve(pRespuesta?pRespuesta:[])) + .catch(pError => reject(pError)) + }), + + /** Función que obtiene los menus basado en los roles. + @param {Modelo} pModeloRolMenu modelo de datos de la tabla rol_menu. + @param {Modelo} pModeloMenu modelo de datos de la tabla menu. + @param {Vector} pVector vector de datos, con informacion sobre menus por rol. + */ + obtenerMenus: (pModeloRolMenu, pModeloMenu,pVector) => { + + const condicion=[] + const peso=0; + let rol; + for(const i in pVector){ + const obj={ fid_rol: pVector[i].dataValues.fid_rol} + condicion.push(obj) + const pesoActual = pVector[i].dataValues.rol.dataValues.peso + if(peso<=pesoActual){ + rol = pVector[i]; + } + + } + console.log('Revisando la condicion', condicion); + // const Op = Sequelize.Op; + return new Promise((resolve, reject) => + pModeloRolMenu.findAll({ + where:{ + [Op.or]:condicion, + estado:'ACTIVO', + }, + include:[{ + model:pModeloMenu, + as:'menu', + attributes:[['nombre','label'],['ruta','url'], + ['icono','icon'],'fid_menu_padre','estado'], + where:{estado:'ACTIVO'}, + include:[{ + model:pModeloMenu, + as:'menu_padre', + attributes:['id_menu',['nombre','label'],['ruta','url'], + ['icono','icon'],'estado'], + where:{estado:'ACTIVO'}, + }], + }], + }) + .then(pRespuesta => { + console.log('Revisando la respuesta', pRespuesta.length); + const menuOrdenado = module.exports.ordenarMenu(pRespuesta) + + const menu=menuOrdenado.menu; + + for(const i in menu){ + const submenusIterar=menu[i].submenu; + const submenuFinal=[]; + for(const j in submenusIterar){ + let contador=0; + if(submenuFinal.length>0){ + for(const k in submenuFinal){ + if(hash(submenusIterar[j]) == hash(submenuFinal[k])) contador ++; + } + if(contador ==0) submenuFinal.push(submenusIterar[j]); + } + else submenuFinal.push(submenusIterar[0]); + } + menu[i].submenu=submenuFinal; + } + menuOrdenado.menu = menu; + const respuesta={ + menu:menuOrdenado, + rol:pVector, + } + resolve(respuesta) + }) + .catch(pError => { + console.log('Errorzango', pError); + reject(pError) + }) + ) + + }, + + buscarRolUno: (id, UsuarioRol, Rol, Usuario, Oficina) => Usuario.findOne({ + where: { + id_usuario: id, + }, + include: [{ + model: UsuarioRol, + as: 'usuario_rol', + attributes: ['fid_rol', 'estado'], + required: false, + where: { + estado: 'ACTIVO', + }, + include: [{ + model: Rol, + as: 'rol', + attributes: ['id_rol', 'nombre', 'estado'], + required: false, + }], + }], + }), + buscarRolTodos: (UsuarioRol, Rol, Usuario, Oficina, condicion) => Usuario.findAll({ + where: condicion, + order: 'estado ASC, usuario ASC', + include: [{ + model: UsuarioRol, + as: 'usuario_rol', + attributes: ['fid_rol', 'fid_usuario', 'id_usuario_rol', 'estado'], + where: { + estado: 'ACTIVO', + }, + order: 'nombre', + include: [{ + model: Rol, + as: 'rol', + attributes: ["id_rol", "nombre", 'estado'], + }], + }], + }), + +} diff --git a/src/bl/seguridad/virtualBL.js b/src/bl/seguridad/virtualBL.js new file mode 100644 index 0000000..6acbc28 --- /dev/null +++ b/src/bl/seguridad/virtualBL.js @@ -0,0 +1,75 @@ +const blu = require('./usuarioBL'); +const moment = require('moment'); +const Uuid = require('uuid'); +const jwt = require('jwt-simple'); + + +module.exports = { + obtenerToken: (modelos, usuarioActivar, usuarioTitular, app) => { + const cfg = app.src.config.config; + return new Promise((resolve, reject) => { + if(!usuarioActivar) return reject('No existen datos del usuario a activar.'); + return blu.obtenerRoles(modelos.usuario_rol, modelos.rol, usuarioActivar.id_usuario) + .then(rolesResp => { + if(!rolesResp) throw Error('No se pudo obtener los roles del usuario a activar.'); + return blu.obtenerMenus(modelos.rol_menu, modelos.menu, rolesResp); + }) + .then(menuRolesResp => { + const cifrar = { + id_usuario: usuarioActivar.id_usuario, + usuario: usuarioActivar.usuario, + secret: jwt.encode({ + fecha: moment().tz('America/La_Paz').add(cfg.tiempo_token, 'minutes').format(), + clave: Uuid.v4(), + }, cfg.jwtSecret), + clave: Uuid.v4(), + tiempo: cfg.tiempo_token, + virtual: usuarioActivar.virtual, + roles: menuRolesResp.rol, + }; + const token = jwt.encode(cifrar, cfg.jwtSecret); + const respuesta = { + user: { + id: usuarioActivar.id_usuario, + username: usuarioActivar.usuario, + first_name: usuarioActivar.nombres, + last_name: usuarioActivar.apellidos, + cargo: usuarioActivar.cargo, + doc: usuarioActivar.numero_documento, + email: usuarioActivar.email, + date_joined: usuarioActivar._fecha_creacion, + }, + menu: menuRolesResp.menu, + menurEntrar: menuRolesResp.menurEntrar, + roles: menuRolesResp.rol, + // virtual: usuarioActivar.virtual, + token, + }; + + const sesion = app.get('sesion'); + sesion[usuarioActivar.id_usuario] = { + fecha: moment(moment().tz('America/La_Paz').format()).add(1, 'minutes'), + backup: null, + token, + }; + + if ( usuarioActivar.virtual === true ) { + const sesionVirtual = app.get('virtual'); + sesionVirtual[usuarioActivar.id_usuario] = { + titular: usuarioTitular.id_usuario, + docTitular: usuarioTitular.numero_documento, + token, + } + app.set("virtual", sesionVirtual); + } + + return resolve(respuesta); + }) + .catch(error => { + console.log('Error en la obtencion del token', error); + return reject(error) + + }); + }); + }, +}; \ No newline at end of file diff --git a/src/config/config.js.sample b/src/config/config.js.sample new file mode 100644 index 0000000..facb4c4 --- /dev/null +++ b/src/config/config.js.sample @@ -0,0 +1,123 @@ +const params = require('./config.json'); +const logger = require('../lib/logger'); + +module.exports = () => { + let env = process.env.NODE_ENV; + + if (!env) { + env = 'development'; + } + + if (!params.hasOwnProperty(env)) { + env = 'development'; + } + const config = { + database: { + name: process.env.DB_NOMBRE || params[env].database, + username: process.env.DB_USUARIO || params[env].username, + password: process.env.DB_PASSWORD || params[env].password, + timezone: process.env.TZ || '-04:00', + lang: process.env.DB_LANGUAGE || 'es', + params: { + dialect: params[env].dialect || 'postgres', + port: process.env.DB_PUERTO || params[env].port, + host: process.env.DB_HOST || params[env].host, + sync: { + force: process.env.FORCE || false, + }, + logging: (sql) => { + if (env === 'development') { + // logger.log('info', `[${new Date()}] ${sql}`); + } + }, + define: { + freezeTableName: true, + }, + }, + }, + ruta_externos: process.env.RUTA_ARCHIVOS_EXTERNOS || "./public/externos", // ".public/externos" + ruta_documentos: process.env.RUTA_DOCUMENTOS || "./public/documentos/", + host: process.env.HOST_BACKEND || 'localhost:8001', // Host backend sobre dominio + front: process.env.HOST_FRONTEND || 'localhost:3000', // Host frontend sobre dominio + urlVerificar: process.env.URL_VERIFICACION || 'https://mi.dominio.net/verificar', + prefijo: 1, // Prefijo en los documentos para su verificación + tiempo_token: process.env.TIEMPO_TOKEN || 60, // Tiempo en minutos, tiempo de vida del token. + validacion: {}, + sistema: { + // remover el [], dejar solamente el numero identificador. + director: process.env.IDENTIFICADOR_DIRECTOR || 1, // id_usuario del usuario con cargo de MAE + direccion: process.env.IDENTIFICADOR_DIRECTOR_UNIDAD || 1, // id_unidad de la unidad Dirección General Ejecutiva + cite_ceros: process.env.CITE_DIGITOS || 5, // Cantidad de digitos que posee el cite. + cite_principal: process.env.CITE_GUIA || 'PLANTILLAS', // Descripción guia del cite, miCiteGuia/IT/0001/2020 + }, + correo: { + port: process.env.CORREO_PUERTO || 25, // 25 + host: process.env.CORREO_HOST || 'localhost', // localhost + remitente: process.env.CORREO_REMITENTE || 'Sistema de plantillas', // Sistema de ... + origen: process.env.CORREO_ORIGEN || 'plantillas@entidad.net', // example@abc.de + secure: process.env.CORREO_SECURE || false, + ignoreTLS: process.env.CORREO_IGNORETLS || false, + tls: { + rejectUnauthorized: process.env.CORREO_TLS_RECHAZAR || false, + }, + }, + notificacion: { + sms_url: process.env.NOTIFICACION_SMS_URL || 'http://localhost/miApiSms', + sms_token: process.env.NOTIFICACION_SMS_TOKEN || '[miTokenSms]', + correo_url: process.env.NOTIFICACION_CORREO_URL || 'http://localhost/miApiCorreo', + correo_token: process.env.NOTIFICACION_CORREO_TOKEN || '[miTokenCorreo]', + }, + ldap: { + server: { + url: process.env.LDAP_URL || 'ldaps://ldap.example.abc:123', + bindDn: process.env.LDAP_BIND_DN || 'uid=usuarioLDAP...', + bindCredentials: process.env.LDAP_BIND_PASSWORD || 'pwdLDAP', + searchBase: process.env.LDAP_SEARCHBASE || 'ou=usuarios...', + searchFilter: process.env.LDAP_SEARCHFILTER || '(uid={{username}})', + }, + }, + // configuracion con jwt poner una palabra secreta segura + jwtSecret: process.env.JWT_SECRET || 'AGETIC-2020', //Se recomienda una llave alfanumerica generada min de 20 caracteres + jwtSession: { + session: process.env.JWT_SESSION || false, + }, + puerto: process.env.BACKEND_PUERTO || 8001, // Puerto donde se expone el api + almacen: { + url_estado: process.env.ALMACEN_ESTADO || 'http://localhost:3000/', + url_consulta: process.env.ALMACEN_CONSULTA || 'http://localhost:3000/api/v2/almacenes/articulos', + url_crear_solicitud: process.env.ALMACEN_CREAR_SOLICITUD || 'http://localhost:3000/api/v2/almacenes/solicitud', + url_recuperar: process.env.ALMACEN_RECUPERAR || 'http://localhost:3000/api/v2/almacenes/solicitud', + url_notificar: process.env.ALMACEN_NOTIFICAR || 'http://localhost:3000/api/v2/almacenes/solicitud', + url_proveedor: process.env.ALMACEN_PROVEEDOR || 'http://localhost:3000/api/v2/almacenes/proveedores', + url_ingreso: process.env.ALMACEN_INGRESO || 'http://localhost:3000/api/v2/almacenes/ingreso', + token: process.env.ALMACEN_TOKEN || 'Bearer TOKEN_ACCESSO', + }, + activos: { + url_estado: process.env.ACTIVOS_ESTADO || 'http://localhost:3000/', + url_consulta: process.env.ACTIVOS_CONSULTA || 'http://localhost:3000/api/v2/activos/buscar', + url_asignacion: process.env.ACTIVOS_ASIGNACION || 'http://localhost:3000/api/v2/activos/asignacion', + url_devolucion: process.env.ACTIVOS_DEVOLUCION || 'http://localhost:3000/api/v2/activos/devolucion', + url_consulta_por_usuario: process.env.ACTIVOS_CONSULTA_POR_USUARIO || 'http://localhost:3000/api/v2/activos/usuario', + token: process.env.ACTIVOS_TOKEN || 'Bearer TOKEN_ACCESO', + }, + // Configuracion de cliente, para ciudadania digital + issuer: process.env.ISSUER || 'https://account-idetest.agetic.gob.bo/', + client: { + post_logout_redirect_uris: [ + 'http://localhost:3000/oauth/logout.html', + ], + client_id: '4b64b225-52b1-4d66-9ba8-27e33ca56a7c', + client_secret: '2W3D5JFXfL3NRoKZ1CthJQoWDraiTt9+v6MBhE8g+TkMwp0ySqiKfsaL00fRLwJy', + redirect_uris: [ + 'http://localhost:3000/oauth/login', + ] + }, + // parameters registry client + client_params: { + scope: ['openid nombre documento_identidad email celular'] + }, + + }; + + return config; +}; diff --git a/src/config/config.json.sample b/src/config/config.json.sample new file mode 100644 index 0000000..faadf04 --- /dev/null +++ b/src/config/config.json.sample @@ -0,0 +1,42 @@ +{ + "development": { + "username": "postgres" , + "password": "postgres", + "database": "name_database", + "host": "127.0.0.1", + "port": 5432, + "dialect": "postgres", + "pool": { + "max": 15, + "min": 0, + "idle": 10000 + }, + "timezone": "America/La_Paz" + }, + "test": { + "username": "postgres", + "password": "postgres", + "database": "name_database", + "host": "127.0.0.1", + "port": 5432, + "dialect": "postgres", + "pool": { + "max": 15, + "min": 0, + "idle": 10000 + } + }, + "production": { + "username": "postgres", + "password": "postgres", + "database": "name_database", + "host": "127.0.0.1", + "port": 5432, + "dialect": "postgres", + "pool": { + "max": 15, + "min": 0, + "idle": 10000 + } + } +} diff --git a/src/db.js b/src/db.js new file mode 100644 index 0000000..67e2e64 --- /dev/null +++ b/src/db.js @@ -0,0 +1,87 @@ + +const fs = require("fs"); +const path = require("path"); +const Sequelize = require("sequelize"); +let db = null; +module.exports = app => { + + if (!db) { + const config = app.src.config.config.database; + const Op = Sequelize.Op; + const alias = { + $eq: Op.eq, + $ne: Op.ne, + $gte: Op.gte, + $gt: Op.gt, + $lte: Op.lte, + $lt: Op.lt, + $not: Op.not, + $in: Op.in, + $notIn: Op.notIn, + $is: Op.is, + $like: Op.like, + $notLike: Op.notLike, + $iLike: Op.iLike, + $notILike: Op.notILike, + $regexp: Op.regexp, + $notRegexp: Op.notRegexp, + $iRegexp: Op.iRegexp, + $notIRegexp: Op.notIRegexp, + $between: Op.between, + $notBetween: Op.notBetween, + $overlap: Op.overlap, + $contains: Op.contains, + $contained: Op.contained, + $adjacent: Op.adjacent, + $strictLeft: Op.strictLeft, + $strictRight: Op.strictRight, + $noExtendRight: Op.noExtendRight, + $noExtendLeft: Op.noExtendLeft, + $and: Op.and, + $or: Op.or, + $any: Op.any, + $all: Op.all, + $values: Op.values, + $col: Op.col + }; + config.params.operatorsAliases = alias; + const sequelize = new Sequelize( + config.name, + config.username, + config.password, + config.params + ); + + db = { + sequelize, + Sequelize, + models: {}, + }; + + const dirModels = path.join(__dirname, "models"); + // Obtiene los modelos del directorio "models". + fs.readdirSync(dirModels).forEach(dir => { + if(fs.statSync(`${dirModels}/${dir}`).isDirectory()){ + const subDirModels = path.join(dirModels, dir); + if(dir !== "ejemplos")//TODO: commentar si es que se quieren cargar los modelos de ejemplos + fs.readdirSync(subDirModels).forEach(file => { + const pathFile = path.join(subDirModels, file); + const model = sequelize.import(pathFile); + // Almacena los objetos modelo en un JSON. + db.models[model.name] = model; + }); + } + }); + console.log("cargando asociaciones...."); + Object.keys(db.models).forEach(key => { + console.log(`---->${key+db.models[key]}`); + // Control de relaciones(associate) de los modelos. + if(db.models[key].associate!=undefined){ + db.models[key].associate(db.models); + + } + }); + + } + return db; +}; diff --git a/src/lib/FirmaPkcs11PdfLib.jar b/src/lib/FirmaPkcs11PdfLib.jar new file mode 100644 index 0000000..40d2519 Binary files /dev/null and b/src/lib/FirmaPkcs11PdfLib.jar differ diff --git a/src/lib/activos.js b/src/lib/activos.js new file mode 100644 index 0000000..c408212 --- /dev/null +++ b/src/lib/activos.js @@ -0,0 +1,121 @@ +const _ = require('lodash'); +const axios = require('axios'); + +const config = require('../config/config')(); + +module.exports = { + consultar: (textoBuscar = '') => { + console.log('[libActivos] consultar ...'); + + return _buscar(textoBuscar, 'codigo') + .then(resp1 => _buscar(textoBuscar, 'descripcion').then(resp2 => resp1.concat(resp2))) + .catch(error => { + console.log('[libActivos] Error al consultar en el Servicio de Activos: ', error); + const errMsg = (error.response && error.response.data && error.response.data.mensaje) ? error.response.data.mensaje : `${error}`; + throw new Error(errMsg); + }); + }, + + consultarPorUsuario: (ci = '') => { + console.log('[libActivos] consultarPorUsuario ...'); + + return new Promise((resolve, reject) => { + const url = encodeURI(`${config.activos.url_consulta_por_usuario}/${ci}`); + console.log('[libActivos] url = ', url); + return axios({ method: 'get', url, headers: { 'Authorization': config.activos.token } }) + .then(resp => { + if ((resp.status === 200 || resp.status === 202) && resp.data.finalizado) { + return resolve(resp.data.data || []); + } + console.log('[libActivos] Error al consultar en el Servicio de Activos: ', resp.data); + const errMsg = (resp.data && resp.data.mensaje) ? resp.data.mensaje : 'Error al consultar en el Servicio de Activos'; + return reject(errMsg); + }) + .catch(error => { + console.log('[libActivos] Error al consultar en el Servicio de Activos: ', error); + const errMsg = (error.response && error.response.data && error.response.data.mensaje) ? error.response.data.mensaje : `${error}`; + return reject(errMsg); + }); + }); + }, + + asignar: (data) => { + console.log('[libActivos] asignar ....'.blue, data); + + return new Promise((resolve, reject) => { + const url = encodeURI(config.activos.url_asignacion); + console.log('[libActivos] url = '.blue, url); + // return axios({ + // method: 'post', + // url, + // headers: { + // 'Authorization': config.almacen.token, + // }, + // data: datos, + // }) + return axios({ method: 'post', url, data, headers: { 'Authorization': config.activos.token } }) + .then(resp => { + console.log('[libActivos] revisando respuesta'.blue, resp); + if ((resp.status === 200 || resp.status === 202) && resp.data.finalizado) { + return resolve(); + // return resolve(resp.data.pdf); + } + console.log('[libActivos] Error al consultar en el Servicio de Activos: ', resp.data); + const errMsg = (resp.data && resp.data.mensaje) ? resp.data.mensaje : 'Error al consultar en el Servicio de Activos'; + return reject(new Error(errMsg)); + }) + .catch(error => { + console.log('[libActivos] Error al consultar en el Servicio de Activos: ', error); + const errMsg = (error.response && error.response.data && error.response.data.mensaje) ? error.response.data.mensaje : `${error}`; + return reject(new Error(errMsg)); + }); + }); + }, + + devolver: (data) => { + console.log('[libActivos] devolver _________...'.yellow); + + return new Promise((resolve, reject) => { + const url = encodeURI(config.activos.url_devolucion); + console.log('[libActivos] url = ', url); + return axios({ method: 'post', url, data, headers: { 'Authorization': config.activos.token } }) + .then(resp => { + console.log('[libActivos] revisando la resp', resp) + if ((resp.status === 200 || resp.status === 202) && resp.data.finalizado) { + return resolve(); + // return resolve(resp.data.pdf); + } + console.log('[libActivos] Error al consultar en el Servicio de Activos: ', resp.data); + const errMsg = (resp.data && resp.data.mensaje) ? resp.data.mensaje : 'Error al consultar en el Servicio de Activos'; + return reject(new Error(errMsg)); + }) + .catch(error => { + console.log('[libActivos] Error al consultar en el Servicio de Activos: ', error); + const errMsg = (error.response && error.response.data && error.response.data.mensaje) ? error.response.data.mensaje : `${error}`; + return reject(new Error(errMsg)); + }); + }); + }, +}; + +function _buscar(textoBuscar, campo = 'descripcion') { + return new Promise((resolve, reject) => { + const url = encodeURI(`${config.activos.url_consulta}?${campo}=${textoBuscar}`); + + console.log('[libActivos] url = ', url); + return axios({ method: 'get', url, headers: { 'Authorization': config.activos.token } }) + .then(resp => { + if ((resp.status === 200 || resp.status === 202) && resp.data.finalizado) { + return resolve(resp.data.data || []); + } + console.log('[libActivos] Error al consultar en el Servicio de Activos: ', resp.data); + const errMsg = (resp.data && resp.data.mensaje) ? resp.data.mensaje : 'Error al consultar en el Servicio de Activos'; + return reject(errMsg); + }) + .catch(error => { + console.log('[libActivos] Error al consultar en el Servicio de Activos: ', error); + const errMsg = (error.response && error.response.data && error.response.data.mensaje) ? error.response.data.mensaje : `${error}`; + return reject(errMsg); + }); + }); +} diff --git a/src/lib/almacen.js b/src/lib/almacen.js new file mode 100644 index 0000000..3979522 --- /dev/null +++ b/src/lib/almacen.js @@ -0,0 +1,131 @@ +require('colors'); +const axios = require('axios'); +const _ = require('lodash'); +const config = require('../config/config')(); +const headers = { + 'Authorization': config.almacen.token, +}; + +module.exports = { + + crearSolicitud: (solicitante, responsable, items, id) => new Promise((resolve, reject) => { + const datos = { + solicitante, + responsable, + items, + id, + } + return axios({ + method: 'post', + url: config.almacen.url_crear_solicitud, + headers, + data: datos, + }) + .then(resp => { + if (resp.status !== 200) throw Error('Estado diferente al de exito.'); + if (resp.data.finalizado === false) throw Error('La peticion no fue procesada completamente.'); + return resolve(resp.data); + }) + .catch(error => { + let respError = error; + if (error.response && error.response.data && error.response.data.mensaje) respError = error.response.data.mensaje; + else respError = 'El sistema de almacenes no se encuentra disponible en estos momentos.'; + return reject(respError); + }); + }), + + consultar: (textoBuscar, todos) => { + let url = config.almacen.url_consulta; + if (textoBuscar) url = `${url}?descripcion=${textoBuscar}`; + if (todos && todos == 1) url += '&todos=1'; + return new Promise((resolve, reject) => axios({ + method: 'get', + url, + headers, + }) + .then(resp => { + if (resp.status !== 200) throw Error('Estado diferente al de exito.'); + if (resp.data.finalizado === false) throw Error('La peticion no fue procesada completamente.'); + return resolve(resp.data.items); + }) + .catch(error => { + let respError = error; + if (error.status == 401) respError = Error('Credenciales de acceso invalidas'); + if (error.response && error.response.data && error.response.data.mensaje) respError = error.response.data.mensaje; + return reject(respError); + })); + }, + + recuperar: (id) => new Promise((resolve, reject) => { + if (!id) return resolve([]); + const url = `${config.almacen.url_recuperar}?id=${id}`; + return axios({ + method: 'get', + url, + headers, + }) + .then(resp => { + if (resp.status !== 200) throw Error('Estado diferente al de exito.'); + if (resp.data.finalizado === false) throw Error('La peticion no fue procesada completamente.'); + const datos = resp.data.datos.items || []; + datos.map(item => { + item.cantidad = item.cantidad_entregada; + item.solicitado = item.cantidad_solicitada; + }); + return resolve({ + cabecera: resp.data.datos.cabecera, + items: datos, + }); + }) + .catch(error => { + let respError = error; + if (error.response && error.response.data && error.response.data.mensaje) respError = error.response.data.mensaje; + return reject(respError); + }); + }), + + notificar: (datos) => new Promise((resolve, reject) => axios({ + method: 'patch', + url: config.almacen.url_notificar, + headers, + data: datos, + }) + .then(() => resolve()) + .catch(error => reject(error))), + + consultarProveedores: (textoBuscar) => new Promise((resolve, reject) => { + if (!textoBuscar || textoBuscar.length == 0) return resolve([]); + return axios({ + method: 'get', + url: `${config.almacen.url_proveedor}?descripcion=${textoBuscar}`, + headers, + }) + .then(resp => { + if (resp.status !== 200) throw Error('Estado diferente al de exito.'); + if (resp.data.finalizado === false) throw Error('La peticion no fue procesada completamente.'); + return resolve(resp.data.datos); + }) + .catch(error => { + let respError = error; + if (error.response && error.response.data && error.response.data.mensaje) respError = error.response.data.mensaje; + return reject(respError); + }); + }), + + crearIngreso: (datos) => new Promise((resolve, reject) => axios({ + method: 'post', + url: config.almacen.url_ingreso, + headers, + data: datos, + }) + .then(resp => { + if (resp.status !== 200) throw Error('Estado diferente al de exito.'); + if (resp.data.finalizado === false) throw Error('La peticion no fue procesada completamente.'); + return resolve(resp.data); + }) + .catch(error => { + let respError = error; + if (error.response && error.response.data && error.response.data.mensaje) respError = error.response.data.mensaje; + return reject(respError); + })), +}; \ No newline at end of file diff --git a/src/lib/archivos.js b/src/lib/archivos.js new file mode 100644 index 0000000..7e502d6 --- /dev/null +++ b/src/lib/archivos.js @@ -0,0 +1,370 @@ +/** + Archivo con funciones y metodos para el manejo de archivos. + */ + +const fs = require('fs'); +const util = require('./util'); +const Uuid = require('uuid'); +const pdftk = require('node-pdftk'); +const _ = require('lodash'); +module.exports={ + + /** + Función que crea un archivo, valida la ruta, si no existe la ruta la crea. + @param {pRuta} Texto Cadena de texto que contiene la ruta destino para el archivo. + @param {pData} Data Información a ser escrita en el archivo. + @param {pNombrePublico} Texto Cadena de texto que contiene el nombre del archivo mas su extensión. + @param {pSobreEscribir} Boleano Es usado para sobreescribir un archivo. + @example Ejemplo de uso. + var files=require('../../lib/archivos'); + let ruta=RutaAdjuntos+"prueba2/1/2/3/4/5/6/7/8/9/10/11/12"; + let data="Hola mundo desde un txt5!!!" + let nombre="archivo5.txt"; + let privado="c1afac81-2465-4315-b3d6-d8c14a9316f0.txt" + + files.crearArchivo(ruta,data,nombre,privado,false) + .then(pRespuesta=>{ + console.log("Archivo creado", pRespuesta); + }) + .catch(pError=>{ + console.log("Error al crear ", pError); + }); + */ + crearArchivo:(pRuta, pData, pNombrePublico,pTipo, pNombrePrivado, pSobreEscribir)=>{ + + // Declara e inicializa variables locales. + let rutaOrigen=null,indiceBarra=null,dir=null,indiceBarraFin=null,temp=null; + let nombreGenerado=pNombrePrivado? pNombrePrivado:Uuid.v4()+pNombrePublico.substring(pNombrePublico.lastIndexOf("."),pNombrePublico.length); + + // Instancia una nueva promesa, con sus dos metodos. + return new Promise((resolve,reject)=>{ + // TODO: Considerar los demas tipos de ruta. + // Procesa parte inicial de una ruta del tipo ./ruta/... + indiceBarra=pRuta.indexOf('/'); + temp=pRuta.substring(0,indiceBarra+1); + pRuta=pRuta.substring(indiceBarra+1,pRuta.length); + indiceBarra=pRuta.indexOf('/'); + dir=temp+pRuta.substring(0,indiceBarra); + + // Realiza la iteracion mientras la longitud de la ruta sea mayor a 0 y no exista '/'. + while (pRuta.length>0 && indiceBarra!==-1) { + + // Si no existe la ruta la crea. + if(!fs.existsSync(dir)) fs.mkdirSync(dir); + + // Actualiza los datos de las variables. + rutaOrigen=dir; + pRuta=pRuta.substring(indiceBarra+1,pRuta.length); + indiceBarra=pRuta.indexOf('/'); + dir=rutaOrigen+"/"+pRuta.substring(0,indiceBarra); + } + + // Si la longitud de la ruta es mayor a 0. + if(pRuta.length>0){ + dir+=pRuta; + + // Si no existe la ruta la crea. + if(!fs.existsSync(dir)) fs.mkdirSync(dir); + } + + // Almacena la ruta completa del archivo. + let rutaArchivo=dir+"/"+nombreGenerado; + + // Objeto a enviar. + let respuesta={nombre_publico:pNombrePublico,nombre_privado:nombreGenerado,data:pData,type:pTipo} + + // Verifica si existe el parametro para sobreescribir el archivo, crea o sobre-escribe el archivo. + if(pSobreEscribir && pSobreEscribir==true) + fs.writeFile(rutaArchivo, pData, {flag: 'w+'},(pErrorEscritura)=> pErrorEscritura? reject(pErrorEscritura) : resolve(respuesta)); + + // Si no existe el parametro para sobreescribir, verifica la existencia. + else + !fs.existsSync(rutaArchivo)? + fs.writeFile(rutaArchivo, pData, {flag: 'w+'},pErrorEscritura=> pErrorEscritura? reject(pErrorEscritura) : resolve(respuesta)) : + reject("El archivo ya existe."); + + }); + }, + + guardarFirmado: (ruta, data, nombreDocumento, sobreescribir) => { + // Declara e inicializa variables locales. + // let nombreGenerado=pNombrePrivado? pNombrePrivado:Uuid.v4()+pNombrePublico.substring(pNombrePublico.lastIndexOf("."),pNombrePublico.length); + module.exports.validarCrearRuta(ruta); + + const rutaArchivo = `${ruta}${nombreDocumento}`; + const respuesta = 'Archivo guardado correctamente'; + return new Promise((resolve, reject) => { + if(sobreescribir && sobreescribir===true) { + return fs.writeFile(rutaArchivo, data, {flag:'w+'}, error => error? reject(error): resolve(respuesta)); + } + + if(!fs.existsSync(rutaArchivo)) { + return fs.writeFile(rutaArchivo, data, {flag: 'w+'}, error => error? reject(error): resolve(respuesta)); + } + else { + return reject('El archivo ya existe.'); + } + }); + }, + + validarCrearRuta: (pRuta) => { + let rutaOrigen=null,indiceBarra=null,dir=null,indiceBarraFin=null,temp=null; + indiceBarra=pRuta.indexOf('/'); + temp=pRuta.substring(0,indiceBarra+1); + pRuta=pRuta.substring(indiceBarra+1,pRuta.length); + indiceBarra=pRuta.indexOf('/'); + dir=temp+pRuta.substring(0,indiceBarra); + + // Realiza la iteracion mientras la longitud de la ruta sea mayor a 0 y no exista '/'. + while (pRuta.length>0 && indiceBarra!==-1) { + + // Si no existe la ruta la crea. + if(!fs.existsSync(dir)) fs.mkdirSync(dir); + + // Actualiza los datos de las variables. + rutaOrigen=dir; + pRuta=pRuta.substring(indiceBarra+1,pRuta.length); + indiceBarra=pRuta.indexOf('/'); + dir=rutaOrigen+"/"+pRuta.substring(0,indiceBarra); + } + + // Si la longitud de la ruta es mayor a 0. + if(pRuta.length>0){ + dir+=pRuta; + + // Si no existe la ruta la crea. + if(!fs.existsSync(dir)) fs.mkdirSync(dir); + } + }, + + anular: (rutaDocumento, buffer) => { + return new Promise((resolve,reject) => { + if(fs.existsSync(rutaDocumento)===false) return reject('El documento a anular no existe.'); + return pdftk.input(fs.readFileSync(rutaDocumento)) + .stamp(buffer) + .output() + .then(buffer => { + return fs.writeFile(rutaDocumento, buffer, {flag:'w+'}, error => error? reject(error): resolve('OK')); + }) + }); + }, + + obtenerBufferLista: (rutaBase, lista) => { + const documentos = {}; + let generar = true; + + lista.map((item, indice) => { + const nombreDocumento = util.formatoNombreDoc(item.nombre); + const rutaDocumento = `${rutaBase}${nombreDocumento}.pdf`; + let clave = util.generarCodigo(6, 'A'); + + while(generar === true) { + if(!documentos[clave]) generar = false; + else clave = util.generarCodigo(6, 'A'); + } + + documentos[clave] = fs.readFileSync(rutaDocumento); + }); + + return pdftk.input(documentos) + .output() + .then(respBuffer => { + return respBuffer; + }) + .catch(error => { + console.log('Error en la obtencion del buffer de documentos', error); + return error; + }); + }, + + corregirAnulacion: (datos, models, sequelize) => { + return new Promise((resolve, reject) => { + + const datosAnulador = {}; + let docsCorregir = []; + return models.documento.findOne({ + where: { + nombre: { + $like: datos.nombre, + }, + }, + }) + .then(docResp => { + if(!docResp) throw Error('No éxiste el informe de anulación.'); + const plantillaValor = JSON.parse(docResp.plantilla_valor); + const docsAnular = plantillaValor['documentosAnular-0']; + const idsAnular = _.map(docsAnular, 'id_documento'); + console.log('Revisando los ids', idsAnular); + + datosAnulador.para = JSON.parse(docResp.para)[0]; + datosAnulador.de = JSON.parse(docResp.de)[0]; + datosAnulador.cite = docResp.nombre; + datosAnulador.idDocumento = docResp.id_documento; + return models.documento.findAll({ + where: { + id_documento: { + $in: idsAnular, + } + } + }); + }) + .then(docsResp => { + if(!docsResp) throw Error('No existen documentos'); + console.log('-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-++-++--+--+-+-+-+-+-+-'); + console.log('Documentos destinados a su anulacion', docsResp.length); + + docsCorregir = _.filter(docsResp, { anulado: false }); + console.log('-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-++-++--+--+-+-+-+-+-+-'); + console.log('Documentos destinados a su CORRECCION', docsCorregir.length); + // return obtenerFecha(datosAnulador); + return models.historial_flujo.findOne({ + where: { + id_documento: datosAnulador.idDocumento, + accion: 'APROBADO', + } + }) + }) + .then(fechaResp => { + if(!fechaResp) throw Error('No existe la aprobacion del informe de anulación.'); + datosAnulador.fecha = fechaResp._fecha_creacion; + return module.exports.corregir(docsCorregir, datosAnulador, models, sequelize); + }) + .then(r => { + console.log('YA termino'); + return resolve(r); + + }) + .catch(error => { + console.log('Error en la correccion de anulaciones', error); + return reject(); + }); + }); + }, + corregirSolo: (docCorregir, anulador, Modelos, sequelize) => { + return new Promise((resolve, reject) => { + const temp = docCorregir.dataValues; + let transaccion; + const tr= {}; + const datosParaAnular = { + cite: anulador.cite, + ruta: temp.ruta, + }; + + return Modelos.historial_flujo.findOne({ + where: { + id_documento: temp.id_documento, + accion: 'ANULADO', + } + }) + .then(respHistorial => { + return sequelize.transaction() + .then( t => { + transaccion = t; + tr.transaction = t; + if(!respHistorial) { + return Modelos.historial_flujo.create({ + id_documento: temp.id_documento, + accion: 'ANULADO', + observacion: anulador.cite, + _usuario_creacion: anulador.de, + _usuario_modificacion: anulador.para, + _fecha_creacion: new Date(anulador.fecha), + }, tr); + } + return respHistorial; + }) + .then(historial => sequelize.query(` + UPDATE historial_flujo set _fecha_modificacion =to_timestamp('${anulador.fecha}', 'Dy Mon DD YYYY HH24:MI:SS') where id_historial_flujo = ${historial.id_historial_flujo}; + UPDATE historial_flujo set _fecha_creacion =to_timestamp('${anulador.fecha}', 'Dy Mon DD YYYY HH24:MI:SS') where id_historial_flujo = ${historial.id_historial_flujo}; + `, tr)) + .then(() => sequelize.query(`UPDATE documento SET anulado = true WHERE id_documento = ${temp.id_documento};`, tr)) + .then(() => module.exports.anularPDF(datosParaAnular)) + .then(() => { + transaccion.commit(); + return ({ + id_documento: temp.id_documento, + nombre: temp.nombre, + corregido: true, + }); + }) + .catch(errorTransaction => { + console.log('Error en la transacion', errorTransaction); + transaccion.rollback(); + return ({ + id_documento: temp.id_documento, + nombre: temp.nombre, + corregido: false, + error: errorTransaction, + }); + }); + }) + .then(resp => { + return resolve(resp); + + }) + }); + + }, + + corregir: (docsCorregir, anulador, Modelos, app) => { + const respuesta = []; + const dirDocumento = app.src.config.config.ruta_documentos; + + const promesas = docsCorregir.map(item => { + return new Promise((resolve, reject) => { + const nombreArchivo = util.formatoNombreDoc(item.nombre); + + const objTemp = { + id_documento: item.id_documento, + nombre: item.nombre, + corregido: false, + ruta: `${dirDocumento}${nombreArchivo}.pdf`, + }; + item.dataValues.ruta = `${dirDocumento}${nombreArchivo}.pdf`; + return module.exports.corregirSolo(item, anulador, Modelos, app.src.db.sequelize) + .then((resp) => { + objTemp.corregido= true; + respuesta.push(resp); + return resolve(objTemp); + // return; + }) + .catch(error => { + console.log('Error en la correccion SOLO', error); + objTemp.error = error; + respuesta.push(resp); + return resolve(objTemp); + // return; + }); + }); + }); + + return Promise.all(promesas) + .then(() => { + return Promise.resolve(respuesta); + }) + .catch(error => { + console.log('Error en las promesas', error); + return Promise.reject(); + }); + + }, + + anularPDF: (datos) => { + return new Promise((resolve, reject) => { + return util.generarAnulador(datos) + .then(bufferResp => { + + if(!bufferResp) throw Error('No existe el buffer para la anulación'); + + return module.exports.anular(datos.ruta, bufferResp); + }) + .then(() => { + return resolve(); + }) + .catch(error => { + console.log('Error en la anulacion del pdf', error); + return reject(error); + }) + }); + }, +}; diff --git a/src/lib/boot.js b/src/lib/boot.js new file mode 100644 index 0000000..cff242e --- /dev/null +++ b/src/lib/boot.js @@ -0,0 +1,48 @@ +module.exports = app => { + + // Almacena las rutas contenidas en el sistema. + const rutas = {GET:[],PUT:[],POST:[],OPTIONS:[],DELETE:[]}; + for (let k in app._router.stack) { + if (app._router.stack[k].route) { + for (let m in app._router.stack[k].route.methods) { + rutas[m.toUpperCase()].push(app._router.stack[k].regexp); + } + } + } + app.set('ruta',rutas); + if (process.env.NODE_ENV !== "test") { + app.src.db.sequelize.sync().done(() => { + if (process.env.FORCE || false){ + console.log("------------BASE DE DATOS CREADA--------------"); + process.exit(0); + }else{ + app.listen(app.get("port"), () => { + console.log(` + _.-'~~~~~~\`-._ + / || \\ + / || \\ PLANTILLAS + | || | FORMLY + | _______||_______ | + |/ ----- \\/ ----- \\| + / ( ) ( ) \\ + / \\ ----- () ----- / \\ + / \\ /||\\ / \\ + / \\ /||||\\ / \\ + / \\ /||||||\\ / \\ + /_ \\o========o/ _\\ + \`--...__|\`-._ _.-'|__...--' + | \`' | + + `); + console.log(`Iniciando servidor en el puerto ${app.get('port')} `); + }); + } + }); + }else{ + app.src.db.sequelize.sync().done(() => { + console.log("------------BASE DE DATOS CREADA--------------"); + if (process.env.FORCE || false) + process.exit(0); + }); + } +}; diff --git a/src/lib/correo.js b/src/lib/correo.js new file mode 100644 index 0000000..d49a21e --- /dev/null +++ b/src/lib/correo.js @@ -0,0 +1,56 @@ +/* + Archivo con los recursos necesarios para poder enviar correo. + */ +const nodemailer = require('nodemailer'); +const logger = require('./logger'); +const config = require('./../config/config'); +const Promise=require('bluebird'); +let configCorreo = config().correo; + + +var jsonConfig = { + port: configCorreo.port, + host: configCorreo.host, + secure: true, + ignoreTLS:true, + tls: { + rejectUnauthorized: true + }, + auth: { + user: configCorreo.user, + pass: configCorreo.pass + } +}; + +var transporte = nodemailer.createTransport(jsonConfig); + +var correo = { + /** + * Envia el un correo con parametros necesarios + * @param {type} datosEnvio + * @returns {unresolved} + */ + enviar: function(datosEnvio) { + return new Promise((resolve, reject) => { + const opciones = { + from: configCorreo.user, + to: datosEnvio.para, + subject: datosEnvio.titulo, + text: datosEnvio.mensaje, + html: datosEnvio.html + }; + + transporte.sendMail(opciones, function(error, info){ + if(error){ + logger.error(error); + reject(error); + } + logger.info('Mensaje enviado: ' + info.response); + resolve() + }); + + }) + } +}; + +module.exports = correo; diff --git a/src/lib/firma.js b/src/lib/firma.js new file mode 100644 index 0000000..ca99f54 --- /dev/null +++ b/src/lib/firma.js @@ -0,0 +1,30 @@ +const PATH_PKCS11_FIRMA = '/FirmaPkcs11PdfLib.jar'; +const { exec } = require('child_process'); +const comandoBase = 'java -jar :libreriaJar -doc :documentoPdf'; + +const ejecutarComando = (comando) => new Promise((resolve,reject) => { + exec(comando, (error, stdout, stderr) => { + try { + if(error) throw Error(error); + const resp = JSON.parse(stdout); + return resolve(resp); + } catch (e) { + return reject(e); + } + }); +}); + + +const obtenerFirmas = (pdf) => { + + const libreria = `${__dirname}${PATH_PKCS11_FIRMA}`; + const comando = comandoBase.replace(':libreriaJar', libreria).replace(':documentoPdf', pdf); + + return ejecutarComando(comando); +}; + + +module.exports = { + obtenerFirmas, + ejecutarComando, +}; diff --git a/src/lib/html_plantilla/anular.ejs b/src/lib/html_plantilla/anular.ejs new file mode 100644 index 0000000..a0678e9 --- /dev/null +++ b/src/lib/html_plantilla/anular.ejs @@ -0,0 +1,16 @@ + + + + + + + + + ANULADO + + + <%= cite %> + + + + \ No newline at end of file diff --git a/src/lib/html_plantilla/documento.ejs b/src/lib/html_plantilla/documento.ejs new file mode 100644 index 0000000..50928e0 --- /dev/null +++ b/src/lib/html_plantilla/documento.ejs @@ -0,0 +1,1323 @@ + + + + + + + + + + + + <% + if(html) marcaAgua = false; + var codigoSeguridad = typeof codigo ==='undefined'? '': codigo; + %> +
    +
    + <%# Funcion que retorna html de acuerdo al tipo de campo %> + <% + function obtenerCampo(pItem, pDatos, pRuta, pNumeracion, pHost, pFlagHtml,pMarcaAgua, exp, codigoSeguridad){ + var datos = pDatos; + var indiceGuion = 0; + var alineacion = ''; + var claseArriba = 0; + var claseAbajo = 0; + + switch(pItem.type) { + case 'texto': + claseArriba = (!pItem.templateOptions.mTop)? "parrafo-margin-top":""; + claseAbajo = (!pItem.templateOptions.mBot)? "parrafo-margin-bottom":""; + switch(pItem.templateOptions.tipo){ + case 'h1': + indiceGuion = pItem.templateOptions.className.lastIndexOf('-') +1; + alineacion = pItem.templateOptions.className.substr(indiceGuion,pItem.templateOptions.className.length);%> +

    <%= pItem.templateOptions.label %>

    + <%break; + case 'h2': + indiceGuion = pItem.templateOptions.className.lastIndexOf('-') +1; + alineacion = pItem.templateOptions.className.substr(indiceGuion,pItem.templateOptions.className.length);%> +

    <%= pItem.templateOptions.label%>

    + <%break; + case 'h3': + indiceGuion = pItem.templateOptions.className.lastIndexOf('-') +1; + alineacion = pItem.templateOptions.className.substr(indiceGuion,pItem.templateOptions.className.length);%> +

    <%= pItem.templateOptions.label%>

    + <%break; + case 'h4': + indiceGuion = pItem.templateOptions.className.lastIndexOf('-') +1; + alineacion = pItem.templateOptions.className.substr(indiceGuion,pItem.templateOptions.className.length);%> +

    <%= pItem.templateOptions.label%>

    + <%break; + case 'h5': + indiceGuion = pItem.templateOptions.className.lastIndexOf('-') +1; + alineacion = pItem.templateOptions.className.substr(indiceGuion,pItem.templateOptions.className.length);%> +
    <%= pItem.templateOptions.label%>
    + <%break; + case 'h6': + indiceGuion = pItem.templateOptions.className.lastIndexOf('-') +1; + alineacion = pItem.templateOptions.className.substr(indiceGuion,pItem.templateOptions.className.length);%> +
    <%= pItem.templateOptions.label%>
    + <%break; + case 'p': + indiceGuion = pItem.templateOptions.className.lastIndexOf('-') +1; + alineacion = pItem.templateOptions.className.substr(indiceGuion,pItem.templateOptions.className.length);%> +

    <%= pItem.templateOptions.label %>

    + <%break; + } + break; + case 'cite': + var cite = null; + var fecha = null; + if(pDatos[pItem.key] && pDatos[pItem.key]['cite'] && pDatos[pItem.key]['fecha']){ + cite=pDatos[pItem.key]['cite']; + fecha=pDatos[pItem.key]['fecha']; + } + else { + cite=pItem.templateOptions.labelCite; + fecha=pItem.templateOptions.labelFecha; + } + if(pItem.templateOptions.tipoMembrete =='externo'){ %> + + <%} + else if(pItem.templateOptions.tipoMembrete =='legal') { %> + + <%} + else { %> +
    + <%} + break; + case 'lista': %> + + + <% if(pItem.templateOptions.className=='ap-text-center'){ %> + + <% } + if(pItem.templateOptions.className=='ap-text-right'){ %> + + <% }%> + + <% if(pItem.templateOptions.className=='ap-text-center'){ %> + + <% }%> + +
    +

    <%= pItem.templateOptions.label %>

    + <% if(pItem.templateOptions.tipo=='ol'){ %>
      <% }else{ %>
        <% } %> + <% for(var j = 0; j < pItem.templateOptions.options.length; j++){ %> +
      • <%= pItem.templateOptions.options[j] %>
      • + <%}%> + <% if(pItem.templateOptions.tipo=='ol'){ %>
    <% }else{ %> <% } %> +
    + <%break; + case 'documentosRelacionados': + if(pDatos[pItem.key]){ %> +
    + <%= pItem.templateOptions.label %> + <% for(var j = 0; j < pDatos[pItem.key].length; j++){ + var docRel = pDatos[pItem.key][j]; + var fechaOrigen = docRel.fecha.substr(0, docRel.fecha.indexOf('T')); + var fechaAux = (fechaOrigen.split('-')).reverse(); + var fechaProcesada = (fechaAux.toString()).replace(/,/g,'/'); + %> + + <%= docRel.nombre %> + + <% } %> + + <% } + break; + case 'listaContactos': + if(pDatos[pItem.key]) { + var valores = pDatos[pItem.key]; + var indiceContacto = valores.contacto; + var contacto = {}; + if(!indiceContacto) { + for (var ij=0; ij < valores.lista.length; ij++) { + var contactoTemp = valores.lista[ij]; + var nombreCompleto = contactoTemp.nombres; + if(contactoTemp.grado && contactoTemp.grado !== "") { + nombreCompleto = contactoTemp.grado + ' ' + nombreCompleto + ' ' + contactoTemp.apellidos; + } + else { + nombreCompleto = nombreCompleto + ' ' + contactoTemp.apellidos; + + } + %> +
    + Señor(a): +
    +
    <%= nombreCompleto%>
    + <% if(contactoTemp.cargo && contactoTemp.cargo !== "") { %> +
    <%= contactoTemp.cargo %>
    + <%} + if (contactoTemp.entidad.toUpperCase() !== "NINGUNO") { %> +
    <%= contactoTemp.entidad %> <%= contactoTemp.sigla %>
    + + <%}%> +
    <%= contactoTemp.direccion %>
    +
    +
    + <%} + } + else { + for (var ij=0; ij < valores.lista.length; ij++) { + var contactoTemp = valores.lista[ij]; + var nombreCompleto = contactoTemp.nombres; + if(contactoTemp.grado && contactoTemp.grado !== "") { + nombreCompleto = contactoTemp.grado + ' ' + nombreCompleto + ' ' + contactoTemp.apellidos; + } + else { + nombreCompleto = nombreCompleto + ' ' + contactoTemp.apellidos; + } + if(indiceContacto == contactoTemp.id_contacto) { + contacto = contactoTemp; + break; + } + } + %> +
    + Señor(a): +
    +
    <%= nombreCompleto%>
    + <% if(contacto.cargo && contacto.cargo !== "") { %> +
    <%= contacto.cargo %>
    + <%} + if (contactoTemp.entidad.toUpperCase() !== "NINGUNO") {%> +
    <%= contacto.entidad %> <%= contacto.sigla %>
    + <%}%> +
    <%= contacto.direccion %>
    +
    +
    + <% + } + } + + break; + case 'documentosAnular': + if(pDatos[pItem.key]){ %> +
    + <%= pItem.templateOptions.label %> + <% for(var j = 0; j < pDatos[pItem.key].length; j++){ + var docRel = pDatos[pItem.key][j]; %> + <%= docRel.nombre %> + <% } %> + + <% } + break; + case 'datosGenerales': + if(pItem.templateOptions.showItem){ %> + + + <% if(pItem.templateOptions.show.para) { %> + + + + + <% } + if(pItem.templateOptions.show.via) { + if(Array.isArray(pDatos[pItem.key].via)){ + if(pDatos[pItem.key].via.length >0){ %> + + + + + <%} + } + } + if(pItem.templateOptions.show.de) { %> + + + + + <% } if(pItem.templateOptions.show.ref) { %> + + + + + <% } %> + +
    PARA:<%=pDatos[pItem.key].para.nombres%> <%=pDatos[pItem.key].para.apellidos%>
    <%=pDatos[pItem.key].para.cargo%>
    VÍA: + <% for(var j = 0; j < pDatos[pItem.key].via.length; j++){ + var via = pDatos[pItem.key].via[j]; %> + <%= via.nombres %> <%= via.apellidos %> +
    <%=via.cargo%>
    + <%} %> +
    DE: + <% for(var j = 0; j < pDatos[pItem.key].de.length; j++){ + var de = pDatos[pItem.key].de[j]; %> + <%= de.nombres %> <%= de.apellidos %> +
    <%=de.cargo%>
    + <%}%> +
    <%= pItem.templateOptions.labelRef %><%=pDatos[pItem.key].ref%>

    + <%} + break; + case 'encabezado': %> + + + <% if(pItem.templateOptions.show.para) { + if(Array.isArray(pDatos[pItem.key].para)){ %> + + + + + <%} + } + if(pItem.templateOptions.show.via) { + if(Array.isArray(pDatos[pItem.key].via)){ + if(pDatos[pItem.key].via.length >0){ %> + + + + + <%} + } + } + if(pItem.templateOptions.show.de) { %> + + + + + <% } + if(pItem.templateOptions.show.ref) { %> + + + + + <% } %> + +
    PARA: + <% for(var z = 0; z < pDatos[pItem.key].para.length; z++){ + var para =pDatos[pItem.key].para[z]; %> + <%=para.nombres%> <%=para.apellidos%>
    + <% if(para.mostrar_cargo){ %> + <%=para.cargo%>
    + <%} + }%> +
    VÍA: + <% for(var j = 0; j < pDatos[pItem.key].via.length; j++){ + var via = pDatos[pItem.key].via[j]; %> + <%= via.nombres %> <%= via.apellidos %>
    + <% if(via.mostrar_cargo){ %> + <%=via.cargo%>
    + <%} + } %> +
    DE: + <% for(var j = 0; j < pDatos[pItem.key].de.length; j++){ + var de = pDatos[pItem.key].de[j]; %> + <%= de.nombres %> <%= de.apellidos %>
    + <% if(de.mostrar_cargo){ %> + <%=de.cargo%>
    + <%} + }%> +
    <%= pItem.templateOptions.labelRef %><%=pDatos[pItem.key].ref%>

    + <%break; + case undefined: + if(pItem.fieldGroup){ %> +
    + <% for(var j = 0; j < pItem.fieldGroup.length; j++){ + var itemHijo=pItem.fieldGroup[j]; %> +
    <%= obtenerCampo(itemHijo, datos)%>
    + <%}%> +
    <% + } + break; + case 'input': + if(pItem.templateOptions.label.length > 0) { %> + <%= pItem.templateOptions.label %>
    + <% } %> +

    <%= datos[pItem.key]%>

    + <%break; + case 'radio': %> + <%= pItem.templateOptions.label %>
    +
    + <% for(var k = 0; k < pItem.templateOptions.options.length; k++){ + var opcion=pItem.templateOptions.options[k] + if(pItem.templateOptions.vertical){ %> + + <%} + else{ %> +
    + <%} + + }%> +
    + <%break; + case 'select': + var itemsM=pItem.templateOptions.options + if(pItem.templateOptions.multiple){ %> +
    <%= pItem.templateOptions.label%>
    + <% var vector = datos[pItem.key]; + for(var m = 0; m < itemsM.length; m++){ + var flag=true; + if(vector) { + for(var z = 0; z < vector.length; z++) { + if(vector[z] == itemsM[m].id) { + flag = false; %> + + <%} + } + } + if(flag){%> + + <%} + } + } + else { + if(pItem.templateOptions.showItem === undefined) { %> +
    <%= pItem.templateOptions.label%> : <%= pDatos[pItem.key]%> + <%} + else if(pItem.templateOptions.showItem === true) { %> +
    <%= pItem.templateOptions.label%> : <%= pDatos[pItem.key]%> + <%} + } + break; + case 'textarea': + var interlineado = pItem.templateOptions.interlineado || false; + if(pItem.templateOptions.label.length > 0) {%> + <%if(pNumeracion && pRuta){%>
    <%}%> + <%= pItem.templateOptions.label %> + <% } + var pes = datos[pItem.key]; + if(datos[pItem.key]) pes = datos[pItem.key].split('\n'); + if(pNumeracion && pRuta) { + if(datos[pItem.key]){ + if(interlineado){ %> +

    + <% for(var s = 0 ; s < pes.length; s++ ){ %> +

    <% if(pes[s]==''){ %>
    <% }else{ %> <%= pes[s] %> <% } %>
    + <%} %> +

    + <%} else { + for(var s = 0 ; s < pes.length; s++ ){ %> +

    <%= pes[s] %>

    + <%} + } + } + } + else { + if(datos[pItem.key]){ + if(interlineado){ %> +

    + <%for(var s = 0 ; s < pes.length; s++ ){ %> +

    <% if(pes[s]==''){ %>
    <% }else{ %> <%= pes[s] %> <% } %>
    + <%}%> +

    + <%} + else { + for(var s = 0 ; s < pes.length; s++ ){ %> +

    <%= pes[s] %>

    + <%} + } + } + } + break; + case 'ccArchivo': + if(datos[pItem.key]){ + var vectorDatos = datos[pItem.key].split('\n') || []; + var htmlDatos = ""; + for(var s = 0; s < vectorDatos.length; s++) { + if(s-1 === vectorDatos.length) htmlDatos += ""+ vectorDatos[s]+""; + else htmlDatos += ""+ vectorDatos[s]+"
    "; + } + %> +
    <%- htmlDatos%>
    + + <%} + break; + case 'checkbox': %> + + <%break; + case 'datepicker': + var fechaMostrar = 'SIN FECHA!!!'; + if(datos[pItem.key] !== null && datos[pItem.key] !== undefined){ + var fecha = datos[pItem.key].substr(0,datos[pItem.key].indexOf('T')) + var aux = (fecha.split('-')).reverse(); + fechaMostrar = (aux.toString()).replace(/,/g,'/'); + } %> +
    + <%= pItem.templateOptions.label %> +

    <%= fechaMostrar %>

    +
    + <%break; + case 'switch':%> +
    <%= pItem.templateOptions.label %>

    +
    + <%break; + case 'chips': + var chips=datos[pItem.key]%> +
    + <%for(var c = 0; c < chips.length; c++){ %> +
    <%= chips[c] %>
    + <%}%> +

    + <%break; + case 'slider': + var inicio= pItem.templateOptions.min; + var final= pItem.templateOptions.max; + var actual = datos[pItem.key]; + var progreso = (actual*100)/final + %> +
    <%= pItem.templateOptions.label%>
    + <%= actual%> +
    +
    +
    + <%break; + case 'editorTexto': + if(pDatos[pItem.key]){ + pDatos[pItem.key] = pDatos[pItem.key].replace('',''); + pDatos[pItem.key] = pDatos[pItem.key].replace('',''); + pDatos[pItem.key] = pDatos[pItem.key].replace('',''); + pDatos[pItem.key] = pDatos[pItem.key].replace('',''); + %> +
    + <%- pDatos[pItem.key] %> +
    + <%} + break; + case 'inputt': + var valorAsunto = pDatos[pItem.key] || ''; + if(pDatos[pItem.key]){ + valorAsunto = pDatos[pItem.key].replace(/\n/g, '
    ') + } + var alineacionAsunto = 'right'; + if(pItem.templateOptions.alineacion){ + var indiceGuionAsunto = pItem.templateOptions.alineacion.lastIndexOf('-') +1; + alineacionAsunto = pItem.templateOptions.alineacion.substr(indiceGuionAsunto,pItem.templateOptions.alineacion.length); + } + var mod5= parseInt(pItem.templateOptions.labelw)%5; + var anchoAsunto= (mod5 == 0)?parseInt(pItem.templateOptions.labelw) : 0; + if(valorAsunto != ''){ %> + + + + + +
    + <%= pItem.templateOptions.labelx%> + + <%- valorAsunto %> +
    + <%} + break; + case 'vacio': + var alto = 1 + var esCm = 28; + if(pItem.templateOptions){ + alto = pItem.templateOptions.height; + if(pItem.templateOptions.style && (pItem.templateOptions.style.height || 'cm').indexOf('px') !== -1){ + esCm = 1; + } + } %> +
    + <%break; + case 'archivo': + var documentos = pDatos[pItem.key]; + if(documentos){ + if(Array.isArray(documentos)){ %> + Documentos adjuntos:
    + <%for(var j = 0; j +
    + <%= documentos[j].nombre_publico%> +
    + <%} + } else { %> + Documentos adjuntos +
    + <%= documentos.nombre_publico%> +
    + <%} + } else{%> + Documentos adjuntos +
    + No hay documentos adjuntos. +
    + <%} + break; + case 'cajachica': + if (pDatos[pItem.key]) { + var partidas = pDatos[pItem.key].rows || []; + var certificacion = pDatos[pItem.key].certificacion || undefined; + var tipo = pDatos[pItem.key].tipo || ''; + var monto_total = pDatos[pItem.key].monto_total; + if(Array.isArray(partidas) && partidas.length>0 && tipo!=''){ + var existe_multiple = 0; %> + + + + <%if (tipo=='PAGADO'){%> <%}%> + + + <%if (tipo=='PAGADO'){%> <%}%> + + + + + <%for(var j = 0; j + <% if (partidas[j].pago_multiple) existe_multiple++; + var row=partidas[j]; %> + + <%if (tipo=='PAGADO'){%> <%}%> + + + <%if (tipo=='PAGADO'){%> <%}%> + + + <%}%> + + <% if(monto_total){ %> + + + <%if (tipo=='PAGADO'){%> <%}%> + + <%if (tipo=='PAGADO'){%> <%}%> + + + + + <% } %> +
    Cite Partida <%= (tipo=='COMPROMETIDO' || tipo=='PAGADO')? 'Detalle':'Descripción'%> Comprometido <%= (tipo=='PAGADO')? 'Pagado':'Monto'%>
    <%=row.cite.nombre%> <%= (tipo=='INICIAL')? row.partida : row.partida.num_des%> <%= row.pago_multiple? '(*)':''%> <%=row.descripcion%> <%=row.comprometido%> <%=row.monto%>
    Total <%=monto_total%>
    + <%if (existe_multiple>0) {%> +
    + <%if (tipo=='PAGADO') {%> + <%if (existe_multiple==1) {%> + Nota.- El detalle de la fila marcada con (*), hace referencia a que el pago es a un comprometido de varias cuotas. + <%} else {%> + Nota.- Los detalles de las filas marcadas con (*), hacen referencia a que el pago es a un comprometido de varias cuotas. + <%}%> + <%} else if (tipo=='COMPROMETIDO') {%> + <%if (existe_multiple==1) {%> + Nota.- El detalle de la fila marcada con (*), hace referencia a que el comprometido se pagara en varias cuotas. + <%} else {%> + Nota.- Los detalles de las filas marcadas con (*), hacen referencia a que el comprometido se pagara en varias cuotas. + <%}%> + <%}%> +
    + <%}%> + <%} + + if(tipo = 'COMPROMETIDO' && certificacion!= undefined) { %> + + + + + + + + + + + <% + for (var item in certificacion) { %> + + + + + + + <%} + %> + +
    PartidaSaldo inicialMonto comprometidoSaldo final
    <%= item %> v<%= certificacion[item].saldoInicial %><%= certificacion[item].montoComprometido %><%= certificacion[item].saldoFinal %>
    + <% + + } + } else {%> + <%} + break; + case 'certificacionComprometido': + if (pDatos[pItem.key]) { + %> + + + + + + + + + + + + <% + for (var item in pDatos[pItem.key]) { %> + + + + + + + <%}%> + +
    PartidaSaldo inicialMonto comprometidoSaldo final
    + <%= item %> + <%= pDatos[pItem.key][item].saldoInicial %> + + <%= pDatos[pItem.key][item].montoComprometido %> + + <%= pDatos[pItem.key][item].saldoFinal %> +
    + <%} + break; + case 'consultaAlmacen': + %> + + + + + + + + + + + <% + var itemsAlmacen = pDatos[pItem.key].filas; + for (var indiceAlmacen in itemsAlmacen ) { %> + + + + + + + <% }%> + +
    Código Descripción Unidad Cantidad
    <%= itemsAlmacen[indiceAlmacen].codigo %> <%= itemsAlmacen[indiceAlmacen].descripcion %> <%= itemsAlmacen[indiceAlmacen].unidad %> <%= itemsAlmacen[indiceAlmacen].cantidad %>
    + <% + break; + case 'recuperarEntregaAlmacen': + %> + + + + + + + + + + + + <% + var itemsEntrega = pDatos[pItem.key].filas; + for (var indiceEntrega in itemsEntrega ) { %> + + + + + + + + <% }%> + +
    Código Descripción Unidad Cantidad solicitada Cantidad entregada
    <%= itemsEntrega[indiceEntrega].codigo %> <%= itemsEntrega[indiceEntrega].descripcion %> <%= itemsEntrega[indiceEntrega].unidad %> <%= itemsEntrega[indiceEntrega].solicitado %> <%= itemsEntrega[indiceEntrega].cantidad %>
    +
    +
    Solicitado por: <%= pDatos[pItem.key].solicitado_por.nombre_completo %>
    +
    Entregado por: <%= pDatos[pItem.key].entregado_por.nombre_completo %>
    +
    Fecha de entrega: <%= pDatos[pItem.key].fecha_entrega %>
    +
    + <% + break; + case 'ingresoAlmacen': + %> +
    Nro. de Factura: <%= pDatos[pItem.key].factura_numero%>
    +
    Fecha Factura: <%= pDatos[pItem.key].factura_fecha%>
    +
    Nro. Autorizacion: <%= pDatos[pItem.key].factura_autorizacion%>
    +
    C31: <%= pDatos[pItem.key].c31%>
    +
    Fecha C31: <%= pDatos[pItem.key].c31_fecha%>
    +
    Proveedor: <%= pDatos[pItem.key].proveedor.nombre%> <%= pDatos[pItem.key].proveedor.nit%>
    + + + + + + + + + + + + + <% + var itemsIngreso = pDatos[pItem.key].items; + for (var indiceIngreso in itemsIngreso ) { %> + + + + + + + + + <% }%> + + + + + + + + + + + + + + + + + + + + + + + + + +
    Código Unidad Detalle Cantidad Precio Precio Total
    <%= itemsIngreso[indiceIngreso].codigo %> <%= itemsIngreso[indiceIngreso].unidad %> <%= itemsIngreso[indiceIngreso].descripcion %> <%= itemsIngreso[indiceIngreso].cantidad %> <%= itemsIngreso[indiceIngreso].precio %> <%= itemsIngreso[indiceIngreso].total %>
    SubTotal<%=pDatos[pItem.key].subtotal%>
    Descuento<%=pDatos[pItem.key].descuento%>
    Total<%=pDatos[pItem.key].total%>
    + <% + break; + case 'consultaActivo': + %> + + + + + + + + + + + <% + var itemsActivos = pDatos[pItem.key].filas; + for (var indiceActivos in itemsActivos ) { %> + + + + + + + <% }%> + +
    ID Código de barras Descripción Cantidad
    <%= itemsActivos[indiceActivos].id %> <%= itemsActivos[indiceActivos].barcode %> <%= itemsActivos[indiceActivos].description %> <%= itemsActivos[indiceActivos].cantidad %>
    + <% + break; + case 'asignacionActivo': + %> + + + + + + + + + + + <% + var itemsActivos = pDatos[pItem.key].filas; + for (var indiceActivos in itemsActivos ) { %> + + + + + + + <% }%> + +
    ID Código de barras Descripción Cantidad
    <%= itemsActivos[indiceActivos].id %> <%= itemsActivos[indiceActivos].barcode %> <%= itemsActivos[indiceActivos].description %> <%= itemsActivos[indiceActivos].cantidad %>
    + <% + break; + case 'devolucionActivo': + %> + + + + + + + + + + + <% + var itemsActivos = pDatos[pItem.key].filas; + for (var indiceActivos in itemsActivos ) { %> + + + + + + + <% }%> + +
    ID Código de barras Descripción Cantidad
    <%= itemsActivos[indiceActivos].id %> <%= itemsActivos[indiceActivos].barcode %> <%= itemsActivos[indiceActivos].description %> <%= itemsActivos[indiceActivos].cantidad %>
    + <% + break; + case 'tablaActivos': + %> + <% if(pDatos[pItem.key].citeBusqueda) { %> +

    CITE del solicitante: <%= pDatos[pItem.key].citeBusqueda %>

    + <%}%> + + <% if(pDatos[pItem.key].usuario_ci) { %> +

    CI del usuario asignado: <%= pDatos[pItem.key].usuario_ci %>

    + <%}%> + + + + + + + + + + + + <% + var itemsActivos = pDatos[pItem.key].filas; + for (var indiceActivos in itemsActivos ) { %> + + + + + + + <% }%> + +
    Código Descripción Cantidad
    <%= itemsActivos[indiceActivos].barcode %> <%= itemsActivos[indiceActivos].description %> <%= itemsActivos[indiceActivos].cantidad %>
    + + + + <% + break; + }; + }; + + var items = form_actual + + + for (var i = 0; i< items.length; i++){ %> +
    + <%= obtenerCampo(items[i], model_actual,ruta, numeracion,host, html, marcaAgua, exp, codigoSeguridad) %> +
    + <% } %> +
    + + + + + diff --git a/src/lib/html_plantilla/presupuesto.ejs b/src/lib/html_plantilla/presupuesto.ejs new file mode 100644 index 0000000..f15172d --- /dev/null +++ b/src/lib/html_plantilla/presupuesto.ejs @@ -0,0 +1,86 @@ + + + + + + + + + + + +
    + +

    Presupuesto <%= presupuesto.gestion %>

    +
    + + + + <% for(var j = 0; j < presupuesto.cabecera.length; j++){ %> + + <% } %> + + + + <% for(var j = 0; j < presupuesto.filas.length; j++){ %> + + <% if(presupuesto.filas[j].numero){ %> + + <% } %> + <% if(presupuesto.filas[j].descripcion){ %> + + <% } %> + <% if(presupuesto.filas[j].inicial){ %> + + <% } %> + <% if(presupuesto.filas[j].comprometido){ %> + + <% } %> + <% if(presupuesto.filas[j].pagado){ %> + + <% } %> + <% if(presupuesto.filas[j].modificado){ %> + + <% } %> + <% if(presupuesto.filas[j].vigente){ %> + + <% } %> + <% if(presupuesto.filas[j].saldo){ %> + + <% } %> + + <% } %> + +
    <%= presupuesto.cabecera[j] %>
    <%= isNaN(parseInt(presupuesto.filas[j].numero)) ? presupuesto.filas[j].numero : parseInt(presupuesto.filas[j].numero) %><%= presupuesto.filas[j].descripcion %><%= presupuesto.filas[j].inicial %><%= presupuesto.filas[j].comprometido %><%= presupuesto.filas[j].pagado %><%= presupuesto.filas[j].modificado %><%= presupuesto.filas[j].vigente %><%= presupuesto.filas[j].saldo %>
    + +
    + + + + diff --git a/src/lib/logger.js b/src/lib/logger.js new file mode 100644 index 0000000..3f4e1bb --- /dev/null +++ b/src/lib/logger.js @@ -0,0 +1,37 @@ +const winston = require("winston"); +const fs = require("fs"); +winston.emitErrs = true; + +const LOG_TO_FILE = process.env.LOG_TO_FILE || false; + +if (!fs.existsSync("logs") && LOG_TO_FILE) { +fs.mkdirSync("logs"); +} + +let transportList = [ + new winston.transports.Console({ + level: 'debug', + handleExceptions: true, + json: false, + colorize: true, + }) +] + +if (LOG_TO_FILE) { + transportList.push(new winston.transports.File({ + level: 'info', + filename: './logs/all-logs.log', + handleExceptions: true, + json: true, + maxsize: 5242880, //5MB + maxFiles: 5, + colorize: false, + })); +} + +const logger = new winston.Logger({ + transports: transportList, + exitOnError: false +}); + +module.exports = logger; diff --git a/src/lib/middlewares.js b/src/lib/middlewares.js new file mode 100644 index 0000000..2e40760 --- /dev/null +++ b/src/lib/middlewares.js @@ -0,0 +1,293 @@ +const bodyParser = require("body-parser"); +const express = require("express"); +const cors = require("cors"); +const morgan = require("morgan"); +const logger = require("./logger"); + +const fileupload = require('express-fileupload'); +const moment = require('moment'); +// Establece la zona horaria, en la libreria moment. +const genFecha = moment().tz('America/La_Paz'); + + +const jwt = require("jwt-simple"); +const helmet = require('helmet'); + + +module.exports = app => { + // Constante que almacena la congfiguracion. + const configuracion = app.src.config.config; + const Usuario = app.src.db.models.usuario; + + // Establece el puerto + app.set("port", configuracion.puerto); + + // Establece la llave secreta + app.set("secretBJA", configuracion.jwtSecret); + // Establece la sesion. + app.set("sesion", {}); + // Establece la sesion de usuarios virtuales. + app.set("virtual", {}); + + // Realiza el uso de morgan para generar logs. + app.use(morgan("common", { + stream: { + write: (message) => { + logger.info(message); + }, + }, + })) + // app.enable('trust proxy'); + // Realiza el uso de la libreria helmet. + app.use(helmet()); + + app.use(bodyParser.json({limit:'100mb'})); + + // Para poder subir archivos. + app.use(fileupload()); + + + // Permite la visualizacion de los test, en entornos distintos a produccion. + app.use((req, res, next) => { + res.locals.showTests = app.get('env') !== 'production' && + req.query.test === '1'; + next(); + }); + + // Establece el uso y configuracion de cors. + app.use(cors({ + // "origin": "*", + "Access-Control-Allow-Origin": "*", + "methods": "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS", + "preflightContinue": true, + "headers": "Cache-Control, Pragma, if-modified-since,Content-Type, Authorization, Content-Length, X-Requested-With, validacion", + "Access-Control-Allow-Headers": "Authorization, Content-Type, X-Content-Type-Options" + + })); + + // Deshabilita la informacion. + app.disable('x-powered-by'); + + // Realiza el uso de "bodyParser" para la recepcion de Json como body. + app.use(bodyParser.json()); + + // Ruta estatica de acceso a la imagen del membrete. + app.use('/public/membrete.png', express.static("public/images/membrete.png")); + app.use('/flibs/pdfjs/pdf.worker.js', express.static("librerias_frontend_extra/pdf.js-viewer/pdf.worker.js")); + + // verifica si hay errores en el formato json + app.use((err, req, res, next) => { + + if (err instanceof SyntaxError) { + res.status(400).json({ + mensaje: "Problemas en el formato JSON" + }); + } else { + res.status(500).send('Error interno!'); + console.error(err.stack); + } + }); + + // Validacion de rutas. + app.use('/', (req,res,next) => { + if(req.method !== 'OPTIONS'){ + const rutas = app.get("ruta"); + const v=rutas[req.method]; + let c=0; + const miRuta= (req.url.indexOf('?')>-1)?req.url.substr(0,req.url.indexOf('?')):req.url; + for (let i = 0; i < v.length; i++) { + if(v[i].test(miRuta)) c++; + } + + (c>0)? next(): res.status(404).send({success:false,message:'Recurso no disponible, intentalo mas tarde.'}); + } + else next() + }) + + if( process.env.NODE_ENV =='test'){ + console.log("Iniciando los test's"); + app.use('/api', (req,res,next) => { + req.body.audit_usuario={ + id_usuario:1, + usuario: 'TEST', + roles:[ + { + fid_rol:1, + rol:{ + peso:0, + nombre:'ADMIN' + } + }, + { + fid_rol:2, + rol:{ + peso:0, + nombre:'JEFE' + } + }, + { + fid_rol:3, + rol:{ + peso:0, + nombre:'OPERADOR' + } + }, + { + fid_rol:4, + rol:{ + peso:0, + nombre:'SECRETARIA' + } + }, + { + fid_rol:5, + rol:{ + peso:0, + nombre:'CONFIGURADOR' + } + }, + { + fid_rol:6, + rol:{ + peso:0, + nombre:'CORRESPONDENCIA' + } + }, + + ] + }; + next(); + }) + } + else { + // Verifica si el usuario se ha autenticado, para lo cual usa el token como llave. + app.use('/api',(req,res,next) => { + // console.log("Verificando las rutas API"); + let flag = false; + + // Si el metodo de peticion es distinto a 'OPTIONS'. + if(req.method != 'OPTIONS'){ + + // Si existe la autorizacion en la cabecera. + if(req.headers.authorization){ + + // Almacena el token limpio. + var token = req.headers.authorization.split(" ")[1]; + + // Si existe el token. + if(token){ + + // Decodifica el token. + var tokenDecodificado = jwt.decode(token, app.get('secretBJA')); + + // Si existe el token decodificado. + if(tokenDecodificado){ + + const sesion = app.get("sesion"); + + if(!sesion[tokenDecodificado.id_usuario]) + return res.status(403).send({success:false,message:'La sesion finalizo.'}) + + if(token !== sesion[tokenDecodificado.id_usuario].token){ + if(sesion[tokenDecodificado.id_usuario].backup !== null){ + if(token == sesion[tokenDecodificado.id_usuario].backup){ + let fechaActual = moment().tz('America/La_Paz').format(); + if(sesion[tokenDecodificado.id_usuario].fecha.format() < fechaActual) return res.status(403).send({success:false,message:'Siga participando.'}) + } else return res.status(403).send({success:false,message:'Siga participando.'}) + } + } + // Busca al usuario con su estado 'ACTIVO'. + Usuario.findOne({ + where:{ + id_usuario:tokenDecodificado.id_usuario, + estado:'ACTIVO' + }, + }) + .then(pUsuario => { + // Verifica si existe el usuario, si es el mismo usuario del token. + if(pUsuario && pUsuario.usuario == tokenDecodificado.usuario){ + // Verifica si existe el campo "secret". + if(tokenDecodificado.secret){ + const secreto = jwt.decode(tokenDecodificado.secret, app.get('secretBJA')); + + // Verifica si los minutos calculados sean menor a los minutos configurados(expiracion del token). + if(genFecha.format() <= secreto.fecha) { + // otorga el acceso al sistema. + req.body.audit_usuario={ + id_usuario: tokenDecodificado.id_usuario, + usuario: tokenDecodificado.usuario, + roles:tokenDecodificado.roles + }; + + return next(); + + // Si el token ya expiro. + } else throw new Error("Siga participando...! EXPIRE"); + + // Si el token no contiene el campo cifrado. + } else throw new Error("Siga participando...!NOT FOUND") + + // Si usuario no existe o no es el mismo del token. + } else throw new Error("Usuario invalido."); + + }) + + .catch(pError => res.status(403).send({success:false,message:'Usuario no valido'})) + + } + // Si no existe el token decodificado. + else{ + return res.status(403).send({ + success: false, + message: 'Fallo la auntenticacion del token.' + }); + } + } + // Si no existe el token. + else{ + return res.status(403).send({ + success:false, + message:'Fallo la autenticacion.' + }); + } + } + // Si no existe la autorizacion. + else{ + return res.status(403).send({ + success: false, + message: ' Fallo la autenticación.', + }); + } + } + // Si es igual a 'OPTIONS'. + else{ + next(); + } + }); + + + app.use('/pdfVerificado', (req, res, next) => { + if (req.method == 'OPTIONS') return next(); + try { + if(!req.body.token) throw Error('No existe la cabecera necesaria'); + const token = req.body.token; + jwt.decode(token, app.get('secretBJA')); + } catch (error) { + console.log('Revisando el error en el midleware', error); + return res.status(403).send({ + success: false, + message: 'El token de acceso no es valido.', + }); + + } + // authorization + next(); + + }); + } + + + + + +}; diff --git a/src/lib/notificacion.js b/src/lib/notificacion.js new file mode 100644 index 0000000..67b7103 --- /dev/null +++ b/src/lib/notificacion.js @@ -0,0 +1,279 @@ +const Promise = require('bluebird'); +const Client = require('node-rest-client').Client; +const config = require('../../src/config/config')(); +const nodemailer = require('nodemailer'); +const smtpTransport = require('nodemailer-smtp-transport') + +const cn=config.notificacion; +const configCorreoLocal=config.correo; +const cliente = new Client(); + +const transporte = nodemailer.createTransport(smtpTransport(configCorreoLocal)); +let usuarioOrigen=null; +let fechaEnvio= null; + +function enviar(pModelos, pDocumento, pEntorno, pTr){ + + let id_1 = pDocumento._usuario_creacion; + let id_2 = pDocumento.via_actual; + if(pEntorno=='derivado'){ + id_1=pDocumento.via_actual; + id_2=pDocumento._usuario_modificacion; + } + if(pEntorno == 'aprobado'){ + id_2=pDocumento._usuario_modificacion; + } + return new Promise((resolve, reject) => { + if(process.env.NODE_ENV =='test') resolve(); + return pModelos.conf_notificacion.findOne({ + // return pModeloConfiguracion.findOne({ + where:{fid_usuario:id_1}, + include:[{ + model:pModelos.usuario, + as:'usuario' + }] + }) + .then(pResultado => { + + if(pResultado!== null){ + usuarioOrigen=pResultado.dataValues; + return pModelos.conf_notificacion.findOne({ + // return pModeloConfiguracion.findOne({ + where:{fid_usuario:id_2}, + include:[{ + model:pModelos.usuario, + as:'usuario' + }] + }) + .then(pRespuestaUsuario => pRespuestaUsuario.dataValues) + } + else throw new Error("Este usuario no tiene la configuracion basica de notificacion") + }) + .then(pDestino => + pModelos.historial_flujo.findOne({ + // pModeloFlujo.findOne({ + attributes:['_fecha_creacion'], + where:{ + id_documento:pDocumento.id_documento, + accion:'ENVIADO' + } + }) + .then(pEnvio => { + fechaEnvio=pEnvio._fecha_creacion; + return pDestino; + }) + + ) + .then(pDestino => { + let mensaje=null; + let asunto = `${pDocumento.nombre_plantilla} - ${pEntorno.toUpperCase()} - Sistema de documentos administrativos`; + let telefonos=[],correos=[]; + let destino = usuarioOrigen; + let origen = pDestino; + let correo = usuarioOrigen.usuario.email; + let telefono = usuarioOrigen.celular; + const mifecha=`${fechaEnvio.getDate()}/${fechaEnvio.getMonth()+1}/${fechaEnvio.getFullYear()}`; + const miHora = `${fechaEnvio.getHours()}:${fechaEnvio.getMinutes()}:${fechaEnvio.getSeconds()}`; + // Retorna un mensaje, telefono y correo, dependiendo del Entorno. + switch (pEntorno) { + case 'observado': + mensaje = `${pDocumento.nombre_plantilla}, enviado el ${mifecha} a horas ${miHora} fue ${pEntorno} por ${pDestino.usuario.nombres} ${pDestino.usuario.apellidos}`; + break; + case 'enviado': + mensaje = `${usuarioOrigen.usuario.nombres} ${usuarioOrigen.usuario.apellidos} te ha enviado un(@): ${pDocumento.nombre_plantilla}, en fecha ${mifecha} a horas ${miHora}.`; + telefono = pDestino.celular; + correo = pDestino.usuario.email; + destino = pDestino; + origen = usuarioOrigen; + break; + case 'derivado': + mensaje= `${pDestino.usuario.nombres} ${pDestino.usuario.apellidos} te ha derivado ${pDocumento.nombre_plantilla} con CITE ${pDocumento.nombre} `; + break; + case 'aprobado': + mensaje= `${pDestino.usuario.nombres} ${pDestino.usuario.apellidos} ha aprobado tu ${pDocumento.nombre_plantilla} con CITE ${pDocumento.nombre} `; + + break; + } + + telefonos.push(telefono); + correos.push(correo); + + if(destino[pEntorno] == true){ + const datos = { + destinatario:destino.usuario.id_usuario, + canal:destino.canal, + _usuario_creacion:origen.usuario.id_usuario, + _fecha_creacion:new Date(), + mensaje, + + } + switch (destino.canal) { + case 'SMS': + + if(destino.usuario.id_usuario !== origen.usuario.id_usuario){ + return enviarSMS(mensaje, telefonos, pModelos.notificacion, datos) + .then(pEnvio => resolve()) + } + else resolve(); + break; + case 'CORREO': + console.log("Enviando el CORREO"); + if(destino.usuario.id_usuario !== origen.usuario.id_usuario){ + return enviarCorreo(asunto, mensaje, correos,pEntorno, pModelos.notificacion, datos,pDocumento.id_documento) + // return enviarCorreoLocal(asunto, mensaje, correos,pEntorno, pModelos.notificacion, datos,pDocumento.id_documento, pTr) + .then(() => resolve()) + }else { + resolve(); + } + + break; + case 'SMS_CORREO': + console.log("Enviando el SMS y CORREO"); + if(destino.usuario.id_usuario !== origen.usuario.id_usuario){ + resolve(); + // return enviarCorreo(asunto, mensaje, correos,pEntorno, pModelos.notificacion, datos,pDocumento.id_documento, pTr) + // .then(pEnvio=>{ + // return enviarSMS(mensaje, telefonos, pModelos.notificacion, datos, pTr) + // .then(pEnvioSms => resolve()); + // }) + // .catch(e => resolve()); + } + else resolve(); + break; + } + + + } + else { + console.log("No requiere notificacion para ", pEntorno); + resolve(); + } + }) + .catch(pError => { + console.log("Error en el envio de la notificacion", pError.message); + resolve(); + }) + }) + +} + +/** + * Función que realiza el envio de SMS, haciendo uso de una API. + * @param {Texto} pMensaje Contiene el mensaje a ser enviado via sms. + * @param {Vector} pTelefono Lista de telefonos destinatarios. + * @param {Objeto} pModeloNotificacion Modelo de base de datos. + * @param {Objeto} pDatos Datos a ser insertados en el modelo de datos. + * @param {Objeto} pTr Transaccion propia de sequelize. + * @return {Promesa} + */ +function enviarSMS(pMensaje,pTelefono,pModeloNotificacion,pDatos,pTr){ + + const args = { + data:{ + mensaje:pMensaje, + telefonos:[pTelefono] + }, + headers:{ + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${cn.sms_token}` + } + } + return new Promise((resolve, reject) => { + + return cliente.post(`${cn.sms_url}`, args, (data, response) => { + + return pModeloNotificacion.create(pDatos,pTr) + .then(() => resolve()) + }) + .on('error', pError => reject(pError)) + + }) + +} + +/** + * Función que realiza el envio de correos de manera local. + * @param {Texto} pMensaje Contiene el mensaje a ser enviado via correo. + * @param {Vector]} pCorreos Lista de destinatarios. + * @param {Texto} pEntorno Entorno de la notificacion. + * @param {Objeto} pModeloNotificacion Modelo de base de datos. + * @param {Objeto} pDatos Datos a ser insertados en el modelo de datos. + * @param {Objeto} pTr Transaccion propia de sequelize. + * @return {Promesa} + */ +function enviarCorreoLocal(pAsunto, pMensaje, pCorreos, pEntorno, pModeloNotificacion, pDatos, pId,pTr){ + let html=`Estimado, el siguiente documento fue ${pEntorno}
    +

    ${pMensaje}

    `; + if(pEntorno=='observado')html+=`Para mas informacion ingresa a aquí! +
    Si el enlace no funciona, prueba a copiar y pegar lo siguiente en tu navegador ${config.front}documento/${pId}` + else html += `Para mas informacion ingresa al sistema aquí! +
    Si el enlace no funciona, prueba a copiar y pegar lo siguiente en tu navegador ${config.front}` + const contenido={ + from:configCorreoLocal.origen, + to:pCorreos, + subject:pAsunto, + html, + } + return new Promise((resolve, reject) => { + transporte.sendMail(contenido,(pError, pInfo) => { + if(pError){ + console.log("Error en el envio de correo",pError); + resolve(); + } else { + console.log("Correo enviado"); + return pModeloNotificacion.create(pDatos,pTr) + .then(() => resolve()) + } + + }) + }) + + +} + +/** +* Función que realiza el envio de correos consumiendo la API.. +* @param {Texto} pMensaje Contiene el mensaje a ser enviado via correo. +* @param {Vector]} pCorreos Lista de destinatarios. +* @param {Texto} pEntorno Entorno de la notificacion. +* @param {Objeto} pModeloNotificacion Modelo de base de datos. +* @param {Objeto} pDatos Datos a ser insertados en el modelo de datos. +* @param {Objeto} pTr Transaccion propia de sequelize. +* @return {Promesa} + */ +function enviarCorreo(pAsunto, pMensaje, pCorreos, pEntorno, pModeloNotificacion, pDatos, pId, pTr){ + let html=`Estimado, el siguiente documento fue ${pEntorno}

    ${pMensaje}

    `; + if(pEntorno=='observado')html+=`Para mas informacion ingresa a aquí!
    Si el enlace no funciona, prueba a copiar y pegar lo siguiente en tu navegador ${config.front}documento/${pId}` + else html += `Para mas informacion ingresa al sistema aquí!
    Si el enlace no funciona, prueba a copiar y pegar lo siguiente en tu navegador ${config.front}`; + + const args={ + data:{ + remitente:configCorreoLocal.remitente, + origen:configCorreoLocal.origen, + asunto:pAsunto, + mensaje:html, + modo:"html", + correos:pCorreos, + }, + headers:{ + 'Content-Type': 'application/json', + 'Authorization':`Bearer ${cn.correo_token}` + } + } + + return new Promise((resolve, reject) => { + return cliente.post(`${cn.correo_url}`, args, (data,response) => { + return pModeloNotificacion.create(pDatos,pTr) + .then(() => resolve()) + }) + .on('error', pError => reject(pError)) + }) +} + + +module.exports={ + enviar, + enviarSMS, + enviarCorreo, + enviarCorreoLocal +} diff --git a/src/lib/util.js b/src/lib/util.js new file mode 100644 index 0000000..a1cd75c --- /dev/null +++ b/src/lib/util.js @@ -0,0 +1,1385 @@ +const http = require('http'); +const hash = require('object-hash'); +const html_pdf = require('html-pdf'); +const html_pdf1 = require('html-pdf'); +const ejs = require("ejs"); +const moment = require('moment'); +const Uuid = require('uuid'); +const config = require('../config/config')(); +const md5File = require('md5-file'); +const fs = require('fs'); +const jwt = require("jwt-simple"); +const Op = require('sequelize').Op; + +console.log("archivo util"); + +const raiz = "./"; +const dirPlantillas = raiz+"public/plantillas/"; +const dirInformes = raiz+"public/informes/"; +const dirDocumento = config.ruta_documentos; + +const funcionCabeceras = (objs) => { + const cabs = []; + for (let i = 0; i < objs.length; i++) { + const obj = objs[i]; + for (const key in obj) { + const attrName = key; + const attrValue = obj[key]; + //Ocultamos el atributo URL, para no ser mostrado en la vista EJS + if (attrName === "url" ) { + } else { + cabs.push(attrName); + } + } + } + return cabs; +}; +/** + * Función que genera una cadena aleatoria. + * @param {Numero} cantidad Numero de caracteres que la cadena aleatoria tendra. + * @param {Texto} combinacion Combinacion para la cadena aleatoria + * @return {Texto} Retorna una cadena aleatoria en base a la cantidad y la combinacion + */ +const generarCodigo = (cantidad, combinacion) => { + let mascara = ''; + if (combinacion.indexOf('a') > -1) mascara += 'abcdefghijklmnopqrstuvwxyz'; + if (combinacion.indexOf('A') > -1) mascara += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + if (combinacion.indexOf('#') > -1) mascara += '0123456789'; + if (combinacion.indexOf('!') > -1) mascara += '~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\'; + let resultado = ''; + for (let i = cantidad; i > 0; --i) resultado += mascara[Math.round(Math.random() * (mascara.length - 1))]; + return resultado; +}; + +const generarUiid = () => Uuid.v4(); +/** +Función que asigna un formato a los mensajes de respuesta para una peticion http. +@param {estado} Estado de la peticion http. +@param {mensaje} Mensaje a retornar. +@param {datos} Datos obtenidos o generados para ser retornados. +@return Retorna un {json} con los datos en el formato establecido. +*/ +const formatearMensaje = (tipoMensaje, mensaje, datos,token) => { + + console.log('[formatearMensaje] mensaje'.red, mensaje); + // Validacion para el parametro mensaje. + let mensajeFinal=mensaje; + // Si el parametro mensaje es un objeto, actualiza el valor del mensaje final. + if(mensaje.message) mensajeFinal=mensaje.message; + + if(process.env.NODE_ENV =='production'){ + if(mensaje.name ){ + if(mensaje.name !== 'Error'){ + mensajeFinal="Ha ocurrido un error al procesar su solicitud."; + } + else { + console.log("El nombre del mensaje es ERROR", mensaje); + } + } + } + // Declara el objeto respuesta. + var respuesta={ + tipoMensaje: tipoMensaje, + mensaje: mensajeFinal, + datos: datos + }; + + + // Esto solo es necesario, en la operacion de autenticación. + if(token)respuesta.token= token; + + + return respuesta; +}; + +/** +Función que verifica un objeto del tipo json, si el objeto es vacio retorna false, si tiene datos true. +@param {pObj} Objeto del tipo json a verificar. +@return Retorna TRUE/FALSE. +*/ +const verificarJSON=(pObj)=>{ + + if(typeof pObj === 'object'){ + for(var i in pObj) return true; + return false; + }else{ + return false; + } + +} + +/** +Función que verifica que sea un vector y que ademas tenga por lo minimo un elemento. +@param {pVector} vector a validar. +@return Retorna un true/false. +*/ +const vectorValido=(pVector)=>{ + + if(Array.isArray(pVector)){ + if(pVector.length>0) return true; + else return false; + }else{ + return false; + } +} + +/** +Función que inserta un vector de objetos. +@param {pVector} Vector que contiene los objetos a insertar. +@param {pModel} Modelo sequelize a usar para la insercion a base de datos. +@param {pUsuarios} Objeto con los usuarios y valores de auditoria. +@param {pLlaves} Objeto con las llaves foraneas y sus respectivos valores. +@return Retorna un vector con los objetos insertados a base de datos. +*/ +const insertarVector =function(pVector, pModel, pProceso,pUsuarios,pLlaves) { + var Promise=require('bluebird'); + var resultado = []; + if(vectorValido(pVector)){ + // Declara el almacenamiento de promesas en un vector. + var promises = pVector.map(function(pItem) { + + if(pUsuarios._usuario_modificacion) pItem._usuario_modificacion=pUsuarios._usuario_modificacion; + else pItem._usuario_creacion=pUsuarios._usuario_creacion; + + // Si existen llaves las asigna al item. + if(pLlaves){ + for(let item in pLlaves){ + pItem[item]=pLlaves[item]; + } + } + + return pModel.create(pItem) + .then(pItemCreado=> { + resultado.push(pItemCreado); + }) + .catch(pErrorItem=> { + return Promise.reject(pErrorItem); + }); + }); + + } + + return Promise.all(promises) + .then(()=> { + return Promise.resolve(resultado); + }) + .catch(err=>{ + if(!promises) return Promise.reject(''); + return Promise.reject(err); + }); +} + +/** +Función que realiza la conversion de un string en objeto. +@param {pObjNombre} Cadena de texto. +@param {pValorOperador} Cadena de texto que contiene operadores logicos usados por el sequelize(caso especifico OR = ','). +@return Retorna un objeto que tiene como valor a un vector de objetos. +@example +ingresa (id_proceso,'1,2,3') +salida {$or:[{id_proceso:1},{id_proceso:2},{id_proceso:3}]}; +*/ +const convertirCadenaOperador=(pObjNombre,pValorOperador)=>{ + + let objNombre=''; + let objRespuesta={}; + // Para coma, OR. + let indiceComa=pValorOperador.indexOf(','); + objNombre='$or' + + let items=[]; + let valorObj=null; + + while(indiceComa>-1){ + let objTemp={} + valorObj=pValorOperador.substring(0,indiceComa); + objTemp[pObjNombre]=valorObj; + items.push(objTemp); + pValorOperador=pValorOperador.substring(indiceComa+1,pValorOperador.length); + indiceComa=pValorOperador.indexOf(','); + } + + if(indiceComa===-1 && pValorOperador.length>0){ + let objTempFinal={}; + valorObj=pValorOperador.substring(pValorOperador.indexOf(",")+1,pValorOperador.length); + objTempFinal[pObjNombre]=valorObj; + items.push(objTempFinal); + } + objRespuesta[objNombre]=items; + + return objRespuesta; +} + +/** +Función que realiza la validacion de una cadena de texto con formato json. +@param {pTextoJson} Cadena de texto que tiene el formato de un json. +@return Retorna un true/false. +@example +ingresa "[{id_usuario:4}]" +salida true/false +*/ +const validarTextoJson=(pTextoJson)=>{ + + if (/^[\],:{}\s]*$/.test(pTextoJson.replace(/\\["\\\/bfnrtu]/g, '@'). + replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). + replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) return true; + else return false; + +} + +/** +Función que realiza la transformacion de una cadena de texto. +@param {pCadena} Cadena de texto que tiene el formato json. +@return Retorna un objeto. +@example +ingresa "[{id_usuario:4},{estado:'ACTIVO'}]" +salida +{ + id_usuario:4, + estado:'ACTIVO' +} +*/ +const transformarVectorTexto=(pCadena)=>{ + + let objRespuesta={}; + pCadena=pCadena.replace("[","").replace("]",""); + let indiceLlaveInicio=pCadena.indexOf("{"); + let indiceLlavefinal=pCadena.indexOf("}"); + let indiceComa=pCadena.indexOf(","); + let llave,valor, indicePuntos=null; + if(pCadena.length>0){ + + while (indiceLlavefinal>-1 && indiceComa>-1) { + + indicePuntos=pCadena.indexOf(":"); + llave=pCadena.substring(indiceLlaveInicio+1,indicePuntos).replace('"','').replace('"',''); + + // TODO: Implementar control para otros operadores logicos. + if(indiceLlaveInicioindiceComa && indiceComa>-1){ + + let valorEnviar=pCadena.substring(indicePuntos+1,indiceLlavefinal).replace('"','').replace('"',''); + valor=convertirCadenaOperador(llave,valorEnviar); + objRespuesta[Op.or]=valor[Op.or]; + pCadena=pCadena.substring(indiceLlavefinal+2,pCadena.length); + + } + + indiceLlaveInicio=pCadena.indexOf("{"); + indiceLlavefinal=pCadena.indexOf("}"); + indiceComa=pCadena.indexOf(","); + + }// Fin while. + + if(indiceComa===-1 && pCadena.length>0){ + indicePuntos=pCadena.indexOf(":"); + llave=pCadena.substring(indiceLlaveInicio+1,indicePuntos).replace('"','').replace('"',''); + valor=pCadena.substring(indicePuntos+1,indiceLlavefinal).replace('"','').replace('"',''); + objRespuesta[llave]=valor; + + + } + } + + return objRespuesta +} + +/** +Función que realiza la transformacion de una cadena de texto en un objeto. +@param {pCondiciones} Objeto que contiene las condiciones. +@return Retorna un objeto. +@example +ingresa { limit:'',order:10, asignacion:"[{fid_usuario:4},{estado:ACTIVO}]"} +salida +{ + limit:'', + order:10, + asignacion:{ + fid_usuario:4, + estado:ACTIVO + } +} +*/ +const transformarConsulta=(pCondiciones)=>{ + let objRespuesta={}; + for(let item in pCondiciones){ + if(pCondiciones[item].indexOf("[")>-1) + if(validarTextoJson(pCondiciones[item])) objRespuesta[item]=transformarVectorTexto(pCondiciones[item]); + else objRespuesta[item]=pCondiciones[item]; + } + return objRespuesta; +}// Fin transformarConsulta + + + +/** + Función que genera el historico de un modelo. + @param {pModelo} Modelo Modelo origen del cual se genera un historico. + @param {pModeloHistorico} Modelo Modelo historico que almacena el dato anterior a la modificacion. + @param {pObjActual} Objeto Datos de actualizacion a insertar. + @param {pObjAntiguo} Objeto Datos a respaldar en el historico. + @return Retorna una promesa. + */ +const historico = (pModelo, pModeloHistorico, pObjActual, pObjAntiguo )=>{ + + var Promise=require('bluebird'); + + // Almacena la llave primaria. + var llavePrimaria = pModelo.primaryKeyAttribute; + let resultado=[]; + + // Si existe el obj actual y es distinto de indefinido. + if(pObjActual && pObjActual!=undefined){ + // Si existe el objAntiguo y es distinto de indefinido. + if(pObjAntiguo && pObjAntiguo!=undefined){ + + let prohibidos = ["_usuario_creacion","_usuario_modificacion","_fecha_creacion","_fecha_modificacion"]; + let antiguoTemp={}; + let actualTemp={}; + + // Elimina los campos de auditoria. + for(let llave in pObjActual){ + if(prohibidos.indexOf(llave)=== -1){ + antiguoTemp[llave]=pObjAntiguo[llave] + actualTemp[llave]=pObjActual[llave] + } + } + + // Si los hashes son distintos. + if(hash(antiguoTemp) !== hash(actualTemp)){ + + + pObjAntiguo["f"+llavePrimaria]=pObjActual[llavePrimaria]; + pObjAntiguo._usuario_creacion=pObjActual._usuario_modificacion; + // Almacena la promesa que crea el historico. + var promesas= pModeloHistorico.create(pObjAntiguo) + .then(pRespuestaHistorico=>{ + let condicion={where:{}} + condicion.where[llavePrimaria] = pObjActual[llavePrimaria]; + // Retorna la promesa que modifica la informacion destino. + return pModelo.update(pObjActual,condicion) + .then(pRespuestaModeloCrear=>{ + resultado=pObjActual; + return resultado; + }) + // Control de error para la modificacion. + .catch(pErrorModeloCrear=>{ + return Promise.reject(pErrorModeloCrear); + }); + }) + // Control de error para la creacion del historico. + .catch(pErrorHistorico=>{ + return Promise.reject(pErrorHistorico); + }) + + // Retorna las promesas. + return promesas; + } + // Si los hashes son iguales. + else{ + // Finaliza la ejecucion de la promesa por correcto. + return Promise.resolve(pObjActual); + } + + } + // Si no existe el objAntiguo. + else{ + + // Almacena la promesa para creacion del datos en el modelo. + var promesas= pModelo.create(pObjActual) + .then(pRespuestaModelo=>{ + resultado=pRespuestaModelo; + return resultado; + }) + // Control de error para creacion de informacion del modelo. + .catch(pErrorModelo=>{ + return Promise.reject(pErrorModelo); + }); + + // Retorna la promesa. + return promesas; + } + } + + + // Ejecuta las promesas almacenadas. + return Promise.all(promesas) + .then(()=>{ + // Finaliza la promesa por correcto. + return Promise.resolve(resultado); + }) + // Control de error para la ejecucion de todas la promesas. + .catch(pError=>{ + + // Si no existen promesas retorna un mensaje personalizado. + if(!promesas) return Promise.reject("No hay promesas") + // Finaliza la promesa por error. + return Promise.reject(pError); + }); + + + +} + +/** + Función que genera el historico para un vector de un mismo modelo. + @param {pVector} Vector Contiene objetos de datos a insertar/modificar. + @param {pObj} Objeto Contiene datos de respaldo(para la modificacion), undefined (si es para insertar). + @param {pModelo} Modelo Modelo origen del cual se genera un historico. + @param {pModeloHistorico} Modelo Modelo historico que almacena el dato anterior a la modificacion. + @param {pIdUsuario} Int Identificador del usuario(campo de auditoria). + + @return Retorna una promesa. + */ +const historicoVector =(pVector,pObj,pModelo,pModeloHis, pIdUsuario)=> { + var Promise=require('bluebird'); + var resultado = []; + let identificador=pModelo.primaryKeyAttribute; + + // if(vectorValido(pVector)){ + if(Array.isArray(pVector)){ + var promises = pVector.map((pItem)=> { + + let antiguo=pObj!=undefined? pObj[pItem[identificador]]:undefined; + + if(antiguo!=undefined) pItem._usuario_modificacion=pIdUsuario; + else pItem._usuario_creacion=pIdUsuario; + + return historico(pModelo,pModeloHis,pItem,antiguo) + .then(pRespuesta=> { + if(antiguo===undefined){ + resultado.push(pRespuesta); + }else{ + return; + } + }) + .catch(pError=> { + // return Promise.resolve(); + return Promise.reject(pError); + }); + }); + + } + + + return Promise.all(promises) + .then(()=> { + return Promise.resolve(resultado); + }) + .catch(err=>{ + if(!promises) return Promise.reject("El vector con datos a modificar no es valido."); + return Promise.reject(err); + }); +} + + + +/** + Función que crea un pdf de la plantilla. + @param {pl} Plantilla objeto plantilla. +*/ +function generarPDF (pl) { + var file = pl.fid_categoria+"-"+pl.fid_subcategoria; + var file = ""; + if(pl.fid_tipo_bien === null && pl.fid_subcategoria === null && pl.fid_categoria !== null){ + file = pl.fid_categoria; + }else if(pl.fid_tipo_bien === null && pl.fid_subcategoria !== null && pl.fid_categoria !== null){ + file = pl.fid_categoria + "-" + pl.fid_subcategoria; + }else if(pl.fid_tipo_bien !== null && pl.fid_subcategoria !== null && pl.fid_categoria !== null){ + file = pl.fid_categoria + "-" + pl.fid_subcategoria + "-" + pl.fid_tipo_bien; + } + file += ".pdf" ; + + // var xdatos = { + // fid_categoria: pl.fid_categoria, + // fid_subcategoria: pl.fid_subcategoria, + // fid_tipo_bien: pl.fid_tipo_bien + // }; + // + // var file = hash(xdatos) + ".pdf"; + var ruta_file = dirPlantillas + file; + var ruta_ejs = __dirname+"/html_plantilla/plantilla.ejs"; + pl.caracteristicas_generales = JSON.parse(pl.caracteristicas_generales); + pl.caracteristicas_especificas = JSON.parse(pl.caracteristicas_especificas); + pl.articulos = JSON.parse(pl.articulos); + for (var i = 0; i < pl.caracteristicas_generales.length; i++) { + if (pl.caracteristicas_generales[i].type == "select") { + if (pl.caracteristicas_generales[i].templateOptions.multiple) { + pl.caracteristicas_generales[i].type = "checkbox"; + }else { + pl.caracteristicas_generales[i].type = "radio"; + } + }else if (pl.caracteristicas_generales[i].type == "checkbox") { + pl.caracteristicas_generales[i].type = "checkbox1"; + } + } + for (var i = 0; i < pl.caracteristicas_especificas.length; i++) { + if (pl.caracteristicas_especificas[i].type == "select") { + if (pl.caracteristicas_especificas[i].templateOptions.multiple) { + pl.caracteristicas_especificas[i].type = "checkbox"; + }else { + pl.caracteristicas_especificas[i].type = "radio"; + } + }else if (pl.caracteristicas_especificas[i].type == "checkbox") { + pl.caracteristicas_especificas[i].type = "checkbox1"; + } + } + // pl.codigo = 'XYZ456'; + ejs.renderFile(ruta_ejs, pl, function (error, resultHTML) { + if (resultHTML) { + var options = { + filename: ruta_file, + format: 'Letter', + orientation: 'portrait', + border: "2cm", + type: "application/pdf", + }; + + html_pdf.create(resultHTML, options).toStream(function(err, stream) { + if (err) { + console.log("hubo un error al generar "+ruta_file+ " fecha:"+genFecha.format()); + console.log("error "+err); + }else { + console.log("Se creo exitosamente el archivo "+ruta_file+ " fecha:"+genFecha.format()); + } + }); + }else { + console.log("hubo un error al generar "+ruta_file+ " fecha:"+genFecha.format()); + console.log("error "+error); + } + }); +} + +function formatearFecha(date,horas=false) { + let resultado = ""; + const fecha = new Date(date); + const mes = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']; + resultado = `${fecha.getDate()} de ${mes[fecha.getMonth()]} de ${fecha.getFullYear()}`; + if (horas===true) resultado = `${resultado} a hrs ${fecha.getHours()}:${fecha.getMinutes()}:${fecha.getSeconds()}.${fecha.getMilliseconds()}`; + return resultado; +} + +const historicoT = (pModelo, pModeloHistorico, pObjActual, pObjAntiguo, pTransaccion ) => { + var Promise=require('bluebird'); + + // Almacena la llave primaria. + var llavePrimaria = pModelo.primaryKeyAttribute; + let resultado=[]; + + // Si existe el obj actual y es distinto de indefinido. + if(pObjActual && pObjActual!=undefined){ + // Si existe el objAntiguo y es distinto de indefinido. + if(pObjAntiguo && pObjAntiguo!=undefined){ + + let prohibidos = ["_usuario_creacion","_usuario_modificacion","_fecha_creacion","_fecha_modificacion"]; + let antiguoTemp={}; + let actualTemp={}; + + // Elimina los campos de auditoria. + for(let llave in pObjActual){ + if(prohibidos.indexOf(llave)=== -1){ + antiguoTemp[llave]=pObjAntiguo[llave]; + actualTemp[llave]=pObjActual[llave]; + } + } + + // Si los hashes son distintos. + if(hash(antiguoTemp) !== hash(actualTemp)){ + pObjAntiguo["f"+llavePrimaria]=pObjActual[llavePrimaria]; + pObjAntiguo._usuario_creacion=pObjActual._usuario_modificacion; + // Almacena la promesa que crea el historico. + var promesas= pModeloHistorico.create(pObjAntiguo, pTransaccion) + .then(pRespuestaHistorico=>{ + let condicion={where:{}}; + condicion.where[llavePrimaria] = pObjActual[llavePrimaria]; + // Retorna la promesa que modifica la informacion destino. + return pModelo.update(pObjActual,condicion, pTransaccion) + .then(pRespuestaModeloCrear=>{ + resultado=pObjActual; + return resultado; + }) + // Control de error para la modificacion. + .catch(pErrorModeloCrear=>{ + console.log("Error al actualizar el modelo", pErrorModeloCrear); + return Promise.reject(pErrorModeloCrear); + }); + }) + // Control de error para la creacion del historico. + .catch(pErrorHistorico=>{ + console.log("Error al crear el historico", pErrorHistorico); + return Promise.reject(pErrorHistorico); + }); + + // Retorna las promesas. + return promesas; + } + // Si los hashes son iguales. + else{ + // Finaliza la ejecucion de la promesa por correcto. + return Promise.resolve(pObjActual); + } + + } + // Si no existe el objAntiguo. + else{ + + // Almacena la promesa para creacion del datos en el modelo. + var promesas= pModelo.create(pObjActual, pTransaccion) + .then(pRespuestaModelo=>{ + resultado=pRespuestaModelo; + return resultado; + }) + // Control de error para creacion de informacion del modelo. + .catch(pErrorModelo=>{ + console.log("Error historicoT", pErrorModelo); + return Promise.reject(pErrorModelo); + }); + + // Retorna la promesa. + return promesas; + } + } + + + // Ejecuta las promesas almacenadas. + return Promise.all(promesas) + .then(()=>{ + // Finaliza la promesa por correcto. + return Promise.resolve(resultado); + }) + // Control de error para la ejecucion de todas la promesas. + .catch(pError=>{ + + // Si no existen promesas retorna un mensaje personalizado. + if(!promesas) return Promise.reject("No hay promesas") + // Finaliza la promesa por error. + return Promise.reject(pError); + }); +} + +function desserializarDeJson(query) { + for (var i in query) { + if (query.hasOwnProperty(i)) { + query[i] = JSON.parse(query[i]); + } + } + return query; +} +function convertirLike(model, query) { + var atributos = model.rawAttributes; + + var xquery = {}; + for (var i in query) { + var tipo_textos = ["STRING","TEXT"]; + if(tipo_textos.indexOf(getTipoAtributo(atributos[i])) !== -1){ + xquery[i] = { + [Op.like]: '%'+query[i]+'%' + }; + }else { + xquery[i] = query[i]; + } + } + return xquery; +} +function getTipoAtributo(atrib) { + return atrib.type.constructor.key; +} + +/** + Función que genera el historico para un vector de un mismo modelo usnado transacciones. + @param {pVector} Vector Contiene objetos de datos a insertar/modificar. + @param {pObj} Objeto Contiene datos de respaldo(para la modificacion), undefined (si es para insertar). + @param {pModelo} Modelo Modelo origen del cual se genera un historico. + @param {pModeloHistorico} Modelo Modelo historico que almacena el dato anterior a la modificacion. + @param {pIdUsuario} Int Identificador del usuario(campo de auditoria). + @param {Objeto} pTransaccion transaccion sequelize. + + @return Retorna una promesa. + */ +const historicoVectorT =(pVector,pObj,pModelo,pModeloHis, pIdUsuario, pTransaccion)=> { + var Promise=require('bluebird'); + var resultado = []; + let identificador=pModelo.primaryKeyAttribute; + + // if(vectorValido(pVector)){ + if(Array.isArray(pVector)){ + var promises = pVector.map((pItem)=> { + + let antiguo=pObj!=undefined? pObj[pItem[identificador]]:undefined; + + if(antiguo!=undefined) pItem._usuario_modificacion=pIdUsuario; + else pItem._usuario_creacion=pIdUsuario; + + return historicoT(pModelo,pModeloHis,pItem,antiguo, pTransaccion) + .then(pRespuesta=> { + if(antiguo===undefined){ + resultado.push(pRespuesta); + }else{ + return; + } + }) + .catch(pError=> { + // return Promise.resolve(); + return Promise.reject(pError); + }); + }); + + } + + return Promise.all(promises) + .then(()=> { + return Promise.resolve(resultado); + }) + .catch(err=>{ + if(!promises) return Promise.reject("El vector con datos a modificar no es valido."); + return Promise.reject(err); + }); +} +const generarDocumento = (pDatos, firma=false) => { + return new Promise((resolve, reject) => { + const nombreDocumento = formatoNombreDoc(pDatos.doc.nombre); + pDatos.nombre=`${nombreDocumento}.pdf`; + const rutaDocumento = `${dirDocumento}${pDatos.nombre}`; + const rutaPlantilla = `${__dirname}/html_plantilla/documento.ejs`; + + let + numeracion = pDatos.form_actual[0].templateOptions.numeracionPagina || false, + membrete = pDatos.form_actual[0].templateOptions.tipoMembrete || 'sin membrete', + tipoHoja = pDatos.form_actual[0].templateOptions.tipoHoja || 'Letter', + alto = 0, + ancho = 0; + switch (tipoHoja) { + case "Letter": + ancho='216mm'; + alto = '279mm'; + break; + case "Oficio": + ancho='216mm'; + alto = '330mm'; + break; + case "A4": + ancho='210mm'; + alto = '297mm'; + break; + case "Externo": + ancho ='210mm'; + alto ='279mm'; + break; + case "Legal": + ancho ='210mm'; + alto ='329mm'; + break; + + + } + // Combinacion de altura carta, ancho A4 + if (membrete == 'externo'){ + ancho ='210mm'; + alto ='279mm'; + } + if (membrete == 'legal'){ + ancho ='210mm'; + alto ='329mm'; + } + + let ruta =__dirname; + ruta = ruta.substr(0,ruta.lastIndexOf('/')); + ruta = ruta.substr(0,ruta.lastIndexOf('/')); + + pDatos.html=false; + pDatos.ruta=ruta; + pDatos.numeracion=numeracion; + pDatos.mensaje="Prohibida la reproducción."; + pDatos.exp = pDatos.grupo; + pDatos.urlVerificar = config.urlVerificar; + + let marcaAgua = true; + const roles = pDatos.audit_usuario.roles; + for (let i = 0; i < roles.length; i++) { + if(roles[i].fid_rol == 4) { + marcaAgua = false; + break; + } + } + + if(firma === true) marcaAgua= false; + pDatos.marcaAgua = marcaAgua; + + pDatos.doc.plantilla= JSON.parse(pDatos.doc.plantilla); + return ejs.renderFile(rutaPlantilla, pDatos, (pError, pHtml) => { + + if(pHtml){ + const configuracion = { + filename: rutaDocumento, + orientation: 'portrait', + height: alto, + width: ancho, + border:{ + top:(membrete=='legal')?"1.7cm":"25mm", + right:(membrete=='externo' || membrete=='legal')?"1.7cm":"2.5cm", + bottom:"2.5cm", + left:"25mm" + }, + type:'application/pdf', + footer: { + height: "8mm", + contents:(numeracion=='true'||numeracion==true)?'
    {{page}}
    ':'' + }, + header: { + height: "25mm" + }, + quality: "100" + }; + + return html_pdf.create(pHtml, configuracion).toFile(rutaDocumento, (pErrorCrear, pStream) => { + if(pErrorCrear) { + console.log('Error en la creacion del documento pdf + ruta', rutaDocumento); + console.log('Error en la creacion del documento pdf', pErrorCrear, pStream); + // return reject((process.env.NODE_ENV == 'production') ? "No se pudo crear el pdf del documento" : errorCrear); + setTimeout(() => { + html_pdf1.create(pHtml, configuracion).toFile(rutaDocumento, (errorCrear, pStream) => { + if(errorCrear) { + console.log('REVISANDO EL SEGUNDO ERROR AL CREAR', errorCrear); + return reject((process.env.NODE_ENV == 'production') ? "No se pudo crear el pdf del documento" : errorCrear); + } + else { + console.log('Retornando'); + return resolve(pDatos); + } + }); + }, 900); + } + else { + return resolve(pDatos); + } + }); + } + else { + console.log('Revisando el error en la generacion del pdf', pError); + return reject((process.env.NODE_ENV == 'production') ? "No se pudo generar el pdf del documento" : pError); + } + + }); + + + }); +} + +const generarAnulador = (pDatos) => { + return new Promise((resolve, reject) => { + const rutaDocumento = `${dirDocumento}${generarCodigo(8,'A')}.pdf`; + const rutaPlantilla = `${__dirname}/html_plantilla/anular.ejs`; + + + ejs.renderFile(rutaPlantilla, pDatos, (pError, pHtml) => { + if (pHtml) { + const configuracion = { + filename: rutaDocumento, + orientation: 'portrait', + height: '279mm', + width: '216mm', + border: { + top: "25mm", + right: "2.5cm", + bottom: "2.5cm", + left: "25mm", + }, + type: 'application/pdf', + quality: "100", + }; + + return html_pdf.create(pHtml, configuracion) + .toBuffer((pErrorCrear, pBuffer) => { + if (!pErrorCrear) return resolve(pBuffer); + else { + console.log('Error en la generacion del buffer', pErrorCrear); + return reject((process.env.NODE_ENV == 'production') ? "No se pudo crear el buffer del anulador" : pErrorCrear); + } + }); + } else reject((process.env.NODE_ENV == 'production') ? "No se pudo generar el anulador del documento" : pError); + + }); + + + }); +} + + + +/** Función que elimina caracteres especiales de una cadena de texto. + @param {Texto} pCadena Cadena de texto con caracteres especiales + @return {Texto} Retorna una cadena de texto sin caracteres especiales + */ +const formatoNombreDoc = (pCadena) => { + pCadena = pCadena.replace(/ /gi,"_"); + + const acentos = "ÃÀÁÄÂÈÉËÊÌÍÏÎÒÓÖÔÙÚÜÛãàáäâèéëêìíïîòóöôùúüûÑñÇç"; + const original = "AAAAAEEEEIIIIOOOOUUUUaaaaaeeeeiiiioooouuuuNncc"; + for (var i=0; i { + console.log('FILTRANDO FILTER') + const attributes = req.query.fields.split(',') || null; + if(req.query.filter !== undefined ){ + pModelo.describe().then( fields => { + const xfilter = []; + for(let i in fields){ + let field = fields[i]; + const obj = {}; + let x = null; + var buscar = (attributes==null)? true : attributes.indexOf(i)!=-1; + if(buscar) { + let tipo = field.type; + if (tipo.indexOf('CHARACTER VARYING') > -1) tipo = 'CHARACTER VARYING'; + switch (tipo) { + case 'INTEGER': + x = parseInt(req.query.filter); + if(!isNaN(x) && req.query.filter.indexOf("/") == -1){ + obj[i] = x; + xfilter.push(obj); + } + break; + case 'USER-DEFINED': + x = req.query.filter; + for (var j in field.special) { + if(field.special[j].toLowerCase().indexOf(x.toLowerCase()) == 0){ + obj[i] = field.special[j]; + xfilter.push(obj); + } + } + break; + case 'TIMESTAMP WITH TIME ZONE': + // Busqueda de fechas del tipo: 2016-10-20, 2016/10/20, 20-10-2016, 20/10/2016. + var consulta=procesarFecha(req.query.filter); + if(consulta!=false){ + obj[i]=procesarFecha(req.query.filter); + xfilter.push(obj); + } + break; + case 'CHARACTER VARYING': + obj[i] = { [Op.iLike]:"%"+req.query.filter+"%" }; + xfilter.push(obj); + break; + case 'TEXT': + obj[i] = { [Op.iLike]:"%"+req.query.filter+"%" }; + xfilter.push(obj); + break; + default: + obj[i] = req.query.filter; + xfilter.push(obj); + + } + } + + } + req.xfilter=xfilter; + next(); + }) + + } + // else { + // next(); + // } + + + + +} + +/** + Función que procesa una cadena, verifica si tiene el formato de una fecha. + @param {pCadena} Cadena de texto con formato de fecha. + @return Retorna: + EXITO -> un objeto de consulta con formato sequelize. + FALLO -> false. +*/ +function procesarFecha(pCadena){ + + var fecha=new Date(pCadena); + var anio=null, inicio=null, fin=null; + + // Identifica el operador usando en la cadena para separar los datos. + var operador=pCadena.indexOf('-')>-1? '-': pCadena.indexOf('/')>-1?'/':null; + + // Si existe un operador valido en la cadena. + if(operador!=null){ + + // Si la cadena no es valida como fecha, se la invierte. + if(fecha == 'Invalid Date') { + fecha =new Date(((pCadena.split(operador)).reverse()).join("-")); + } + // Obtine el año. + anio=fecha.getFullYear(); + + // Si existe el año. + if(anio!=null){ + var vector=pCadena.split(operador) + + // Si la longitud del vector es igual a 3. + if(vector.length==3){ + var indice=vector.indexOf(anio.toString()); + + // Si el año existe dentro del vector de la cadena. + if(indice>-1){ + + // Armado de la fecha inicio y fecha fin. + if(indice==0){ + inicio=vector[0]+"-"+vector[1]+"-"+vector[2]; + fin=vector[0]+"-"+vector[1]+"-"+(parseInt(vector[2])+1); + } + else if(indice==2) { + inicio=vector[2]+"-"+vector[1]+"-"+vector[0]; + fin=vector[2]+"-"+vector[1]+"-"+(parseInt(vector[0])+1); + } + + // Armado de la respuesta a retornar. + var respuesta={ + [Op.gte]: inicio, + [Op.lt]: fin + }; + return respuesta; + } + else return false; // Fin condicional indice. + } + else return false; // Fin condicional longitud vector. + } + else return false; // Fin condicional existencia año. + } + else return false; // Fin condicional existencia operador. +} +const generarHtml = (pDatos) => { + return new Promise((resolve,reject)=>{ + const nombreDocumento = formatoNombreDoc(pDatos.doc.nombre) + pDatos.nombre=`${nombreDocumento}.pdf`; + const rutaDocumento = `${dirDocumento}${pDatos.nombre}`; + const rutaPlantilla = `${__dirname}/html_plantilla/documento.ejs`; + + let numeracion = pDatos.form_actual[0].templateOptions.numeracionPagina || false; + let membrete = pDatos.form_actual[0].templateOptions.tipoMembrete || 'sin membrete'; + let tipoHoja = pDatos.form_actual[0].templateOptions.tipoHoja || 'Letter'; + let alto=0, ancho =0; + switch (tipoHoja) { + case "Letter": + ancho='216mm'; + alto = '279mm'; + break; + case "Oficio": + ancho='216mm'; + alto = '330mm'; + break; + case "A4": + ancho='210mm'; + alto = '297mm'; + break; + case "Externo": + ancho ='210mm'; + alto ='279mm'; + break; + case "Legal": + ancho ='210mm'; + alto ='329mm'; + break; + + + } + // Combinacion de altura carta, ancho A4 + if (membrete == 'externo'){ + ancho ='210mm'; + alto ='279mm'; + } + if (membrete == 'legal'){ + ancho ='210mm'; + alto ='329mm'; + } + + let ruta =__dirname; + ruta = ruta.substr(0,ruta.lastIndexOf('/')); + ruta = ruta.substr(0,ruta.lastIndexOf('/')); + + pDatos.html=true; + pDatos.ruta=ruta; + pDatos.numeracion=numeracion; + pDatos.mensaje="Prohibida la reproducción."; + pDatos.exp = pDatos.grupo || ''; + pDatos.doc.plantilla= JSON.parse(pDatos.doc.plantilla) + + ejs.renderFile(rutaPlantilla, pDatos, (pError, pHtml) => { + + if(pHtml){ + const configuracion = { + filename: rutaDocumento, + orientation: 'portrait', + height: alto, + width: ancho, + border:{ + top:(membrete=='legal')?"1.7cm":"25mm", + right:(membrete=='externo' || membrete=='legal')?"1.7cm":"2.5cm", + bottom:"2.5cm", + left:"25mm" + }, + type:'application/pdf', + footer: { + height: "8mm", + contents:(numeracion=='true'||numeracion==true)?'
    {{page}}
    ':'' + }, + header: { + height: "18mm" + }, + quality: "100" + }; + pHtml = pHtml.replace('',''); + pHtml = pHtml.replace('',''); + pHtml = pHtml.replace('',''); + pHtml = pHtml.replace('',''); + pHtml = pHtml.replace('',''); + pHtml = pHtml.replace('',''); + pHtml = pHtml.replace('',''); + pHtml = pHtml.replace('',''); + pDatos.html=pHtml; + resolve(pDatos) + + + } + else reject((process.env.NODE_ENV=='production')? "No se pudo generar el html del documento":pError); + }); + }); +} + +const generarPresupuestoPDF = (pDatos) => { + return new Promise((resolve,reject)=>{ + const rutaDocumento = './public/documentos/Presupuesto.pdf'; + const rutaPlantilla = `${__dirname}/html_plantilla/presupuesto.ejs`; + + let + numeracion = true, + membrete = 'sin membrete', + tipoHoja = 'Letter', + ancho='279mm', + alto = '216mm'; + + let ruta =__dirname; + ruta = ruta.substr(0,ruta.lastIndexOf('/')); + ruta = ruta.substr(0,ruta.lastIndexOf('/')); + + //pDatos.html=false; + pDatos.ruta=ruta; + pDatos.numeracion=numeracion; + pDatos.mensaje="Prohibida la reproducción."; + + ejs.renderFile(rutaPlantilla, pDatos, (pError, pHtml) => { + + if(pHtml){ + const configuracion = { + filename: rutaDocumento, + orientation: 'landscape', + height: alto, + width: ancho, + border:{ + top:(membrete=='legal')?"1.7cm":"20mm", + right:(membrete=='externo' || membrete=='legal')?"1.7cm":"2cm", + bottom:"2cm", + left:"20mm" + }, + type:'application/pdf', + footer: { + height: "8mm", + contents:(numeracion=='true'||numeracion==true)?'
    {{page}}
    ':'' + }, + header: { + height: "18mm" + }, + quality: "100" + }; + + html_pdf.create(pHtml, configuracion).toFile(rutaDocumento, (pErrorCrear, pStream) => { + if(pErrorCrear) reject((process.env.NODE_ENV=='production')? "No se pudo crear el pdf del documento":pError); + else resolve(pDatos); + }); + } + else reject((process.env.NODE_ENV=='production')? "No se pudo generar el pdf del documento":pError); + + }); + + + }); +}; +const dataToView = (data, model) => { + var elem; + var form = []; + var keys = {}; // variable para controlar que no existan keys iguales + for (var i = 0; i < data.length; i++) { + if (data[i].type=="layout") { + var fg = parse(data[i]); + var clase = " flex-"+parseInt(100/fg.elementAttributes['num-cols']); + delete fg.type; + delete fg.elementAttributes['num-cols']; + fg.fieldGroup = []; + for (var j = 0; j < data[i].fieldGroup.length; j++) { + elem = getConfigItem(data[i].fieldGroup[j]); + elem.className += clase; + changeElement(elem, keys, model); + fg.fieldGroup.push(elem); + } + form.push(fg); + }else { + elem = getConfigItem(data[i]); + changeElement(elem, keys, model); + form.push(elem); + } + } + return form; +}; +const parse = (data) => { + return JSON.parse(JSON.stringify(data)); +}; + +const getConfigItem = (item) => { + if(item.type=='layout') return parse(item); + var obj = { + type: item.type, + key: item.key, + templateOptions: parse(item.templateOptions), + }; + return obj; +}; + +const changeElement = (elem, keys, model) => { + if(keys[elem.type] === undefined){ + keys[elem.type] = 1; + elem.key = elem.type + "-0"; + } else { + elem.key = elem.type +"-"+ keys[elem.type]; + keys[elem.type]++; + } + if(elem.type === "radio"){ + elem.templateOptions.className = "layout layout-wrap"; + } + if(elem.type === "datepicker" && model !== undefined && model[elem.key] !== undefined){ + model[elem.key] = new Date(model[elem.key]); + } + if(elem.type === "textarea"){ + elem.templateOptions.grow = true; + } + if(elem.templateOptions){ + var validation = {messages:{}}; + if(elem.templateOptions.required){ + validation.messages.required = '"Debe llenar este campo."'; + } + if( elem.type==="input"){ + var idx = { + '([a-zA-Zñáéíóú]+ ?)+': '"El campo debe contener solo palabras separadas por un espacio."', + '\\d+': '"El campo debe contener solo números."', + '([a-zA-Z0-9ñáéíóú]+ ?)+': '"El campo debe contener palabras y números separadas por un espacio."', + '^(([^<>()\\[\\]\\\\.,;:\\s@"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$': '"El campo debe ser un email válido."', + '^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$':'"El campo debe ser una hora en formato hh:mm (ej. 08:47)"' + }; + if(elem.templateOptions.pattern) validation.messages.pattern = idx[elem.templateOptions.pattern]; + validation.show = true; + elem.validation = validation; + } + } +}; +const existePdf = (nombre) => { + const nombreDocumento = formatoNombreDoc(nombre); + const rutaDocumento = `${dirDocumento}${nombreDocumento}.pdf`; + const documentoExiste = fs.existsSync(rutaDocumento); + return documentoExiste; +}; + +const obtenerHash = (rutaDocumento) => { + const hashPdf = md5File.sync(`${dirDocumento}${rutaDocumento}.pdf`); + return hashPdf; +}; + +const rutaDocumentos = () => { + return dirDocumento; +}; + +const obtenerArchivo = (cite) => { + const existeDocumento = existePdf(cite); + const rutaDocumento = `${dirDocumento}${formatoNombreDoc(cite)}.pdf`; + return new Promise((resolve,reject) => { + if(!existeDocumento || existeDocumento === false ) return reject('El Documento no existe'); + fs.readFile(rutaDocumento, (err, data) => { + if(err) return reject(err); + return resolve(data); + }); + }); +}; + +const generarTokenVerificacion = () => { + const fechaActual = moment().tz('America/La_Paz').format(); + const fechaExp = moment(fechaActual).add(30, 's').valueOf(); + const expFinal = fechaExp / 1000; + return jwt.encode({ + payload: { + fecha: moment().format(), + }, + iat: fechaExp, + exp: expFinal, + clave: generarCodigo(8,'a#A'), + key: generarCodigo(8,'a#A'), + }, config.jwtSecret); +}; + +const validarContactos = (req, res, next) => { + console.log('Iniciando la validacion'); + console.log('roles', req.body.audit_usuario.roles); + + const roles =req.body.audit_usuario.roles; + let cont = 0; + for (let i = 0; i < roles.length; i++) { + if (roles[i].rol.nombre == "CONTACTOS") cont++; + } + console.log('Revisando el contador', cont); + + if(cont > 0) return next(); + else return res.status(412).send(formatearMensaje('ERROR', 'Usted no esta autorizado.')) +} + +module.exports = { + funcionCabeceras, + generarCodigo, + formatearMensaje, + verificarJSON, + insertarVector, + vectorValido, + transformarConsulta, + transformarVectorTexto, + historico, + generarPDF, + historicoVector, + historicoT, + historicoVectorT, + desserializarDeJson, + convertirLike, + generarDocumento, + generarHtml, + consulta, + procesarFecha, + generarPresupuestoPDF, + formatoNombreDoc, + dataToView, + parse, + getConfigItem, + changeElement, + formatearFecha, + existePdf, + obtenerHash, + rutaDocumentos, + obtenerArchivo, + generarAnulador, + generarTokenVerificacion, + generarUiid, + validarContactos +}; diff --git a/src/migrations/00000001-addEstadoHistorial.js b/src/migrations/00000001-addEstadoHistorial.js new file mode 100644 index 0000000..e04efef --- /dev/null +++ b/src/migrations/00000001-addEstadoHistorial.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.sequelize.query(`ALTER TYPE enum_historial_flujo_accion ADD VALUE 'ANULADO';`); + }, + down: (queryInterface, Sequelize) => {} +}; diff --git a/src/migrations/00000003-crearFirma.js b/src/migrations/00000003-crearFirma.js new file mode 100644 index 0000000..c98e500 --- /dev/null +++ b/src/migrations/00000003-crearFirma.js @@ -0,0 +1,39 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('firma', { + id_firma: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true + }, + fid_documento: { + type: Sequelize.INTEGER, + allowNull: false + }, + hash: { + type: Sequelize.TEXT + }, + codigo: { + type: Sequelize.STRING(10), + allowNull: false + }, + _usuario_creacion: { + type: Sequelize.INTEGER, + allowNull: false + }, + _usuario_modificacion: { + type: Sequelize.INTEGER + }, + _fecha_creacion: { + type: Sequelize.DATE, + allowNull: false + }, + _fecha_modificacion: { + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => {}, +}; diff --git a/src/migrations/00000005-crearContacto.js b/src/migrations/00000005-crearContacto.js new file mode 100644 index 0000000..b78fc9f --- /dev/null +++ b/src/migrations/00000005-crearContacto.js @@ -0,0 +1,66 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('contacto', { + id_contacto: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + grado: { + type: Sequelize.STRING(150), + }, + nombres: { + type: Sequelize.STRING(150), + allowNull: false, + }, + apellidos: { + type: Sequelize.STRING(150), + allowNull: false, + }, + cargo: { + type: Sequelize.STRING(250), + }, + entidad: { + type: Sequelize.STRING(250), + }, + tipo_entidad: { + type: Sequelize.STRING(250), + }, + sigla: { + type: Sequelize.STRING(80), + }, + direccion: { + type: Sequelize.TEXT, + }, + telefono: { + type: Sequelize.TEXT, + }, + departamento: { + type: Sequelize.STRING(50), + }, + estado: { + type: Sequelize.ENUM('ACTIVO', 'INACTIVO'), + allowNull: false, + defaultValue: 'ACTIVO', + }, + _usuario_creacion: { + type: Sequelize.INTEGER, + allowNull: false, + }, + _usuario_modificacion: { + type: Sequelize.INTEGER, + }, + _fecha_creacion: { + type: Sequelize.DATE, + allowNull: false, + }, + _fecha_modificacion: { + type: Sequelize.DATE, + }, + } + ); + }, + down: (queryInterface, Sequelize) => {}, +}; diff --git a/src/migrations/00000006-addMenu.js b/src/migrations/00000006-addMenu.js new file mode 100644 index 0000000..952164f --- /dev/null +++ b/src/migrations/00000006-addMenu.js @@ -0,0 +1,23 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + const contactos = [ + { + nombre: 'CONTACTOS', + descripcion: 'Bandeja de contactos', + orden: 1, + ruta: 'contactos', + icono: 'user', + estado: 'ACTIVO', + _fecha_creacion: new Date(), + _fecha_modificacion: new Date(), + _usuario_creacion: 1, + _usuario_modificacion: 1, + fid_menu_padre: 1, + }, + ]; + return queryInterface.bulkInsert('menu', contactos, {}); + }, + down: (queryInterface, Sequelize) => {}, +}; diff --git a/src/migrations/00000006-crearVirtual.js b/src/migrations/00000006-crearVirtual.js new file mode 100644 index 0000000..6c7203e --- /dev/null +++ b/src/migrations/00000006-crearVirtual.js @@ -0,0 +1,47 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('virtual', { + id_virtual: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + fid_usuario_titular: { + type: Sequelize.INTEGER, + allowNull: false, + }, + fid_usuario_virtual: { + type: Sequelize.INTEGER, + allowNull: false, + }, + // fecha_inicio: { + // type: Sequelize.DATE, + // allowNull: false, + // }, + // fecha_fin: { + // type: Sequelize.DATE, + // }, + estado: { + type: Sequelize.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + }, + _usuario_creacion: { + type: Sequelize.INTEGER, + allowNull: false + }, + _usuario_modificacion: { + type: Sequelize.INTEGER + }, + _fecha_creacion: { + type: Sequelize.DATE, + allowNull: false + }, + _fecha_modificacion: { + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => {}, +}; diff --git a/src/migrations/00000008-crearVirtualHis.js b/src/migrations/00000008-crearVirtualHis.js new file mode 100644 index 0000000..673d7f4 --- /dev/null +++ b/src/migrations/00000008-crearVirtualHis.js @@ -0,0 +1,44 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('virtual_his', { + id_virtual_his: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + fid_virtual: { + type: Sequelize.INTEGER, + allowNull: false, + }, + id_titular: { + type: Sequelize.INTEGER, + allowNull: false, + }, + id_virtual: { + type: Sequelize.INTEGER, + allowNull: false, + }, + accion: { + type: Sequelize.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + }, + _usuario_creacion: { + type: Sequelize.INTEGER, + allowNull: false, + }, + _usuario_modificacion: { + type: Sequelize.INTEGER, + }, + _fecha_creacion: { + type: Sequelize.DATE, + allowNull: false, + }, + _fecha_modificacion: { + type: Sequelize.DATE, + } + }); + }, + down: (queryInterface, Sequelize) => {}, +}; diff --git a/src/migrations/00000009-crearCatalogo.js b/src/migrations/00000009-crearCatalogo.js new file mode 100644 index 0000000..ab2ccd8 --- /dev/null +++ b/src/migrations/00000009-crearCatalogo.js @@ -0,0 +1,41 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('catalogo', { + id_catalogo: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + nombre: { + type: Sequelize.TEXT, + allowNull: false, + }, + descripcion: { + type: Sequelize.TEXT, + allowNull: false, + }, + estado: { + type: Sequelize.ENUM('ACTIVO', 'INACTIVO', 'ELIMINADO'), + allowNull: false, + defaultValue: 'ACTIVO', + }, + _usuario_creacion: { + type: Sequelize.INTEGER, + allowNull: false, + }, + _usuario_modificacion: { + type: Sequelize.INTEGER, + }, + _fecha_creacion: { + type: Sequelize.DATE, + allowNull: false, + }, + _fecha_modificacion: { + type: Sequelize.DATE, + } + }); + }, + down: (queryInterface, Sequelize) => {}, +}; diff --git a/src/migrations/00000010-crearCatalogoDocumento.js b/src/migrations/00000010-crearCatalogoDocumento.js new file mode 100644 index 0000000..ca85bc0 --- /dev/null +++ b/src/migrations/00000010-crearCatalogoDocumento.js @@ -0,0 +1,49 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('catalogo_documento', { + id_catalogo_documento: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + fid_catalogo: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'catalogo', + key: 'id_catalogo', + }, + }, + fid_documento: { + type: Sequelize.INTEGER, + allowNull: false, + }, + descripcion: { + type: Sequelize.TEXT, + allowNull: false, + }, + estado: { + type: Sequelize.ENUM('ACTIVO', 'INACTIVO', 'ELIMINADO'), + allowNull: false, + defaultValue: 'ACTIVO', + }, + _usuario_creacion: { + type: Sequelize.INTEGER, + allowNull: false, + }, + _usuario_modificacion: { + type: Sequelize.INTEGER, + }, + _fecha_creacion: { + type: Sequelize.DATE, + allowNull: false, + }, + _fecha_modificacion: { + type: Sequelize.DATE, + } + }); + }, + down: (queryInterface, Sequelize) => {}, +}; diff --git a/src/migrations/00000011-crearCatalogoUsuario.js b/src/migrations/00000011-crearCatalogoUsuario.js new file mode 100644 index 0000000..d969027 --- /dev/null +++ b/src/migrations/00000011-crearCatalogoUsuario.js @@ -0,0 +1,60 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('catalogo_usuario', { + id_catalogo_usuario: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + fid_catalogo: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'catalogo', + key: 'id_catalogo', + }, + }, + fid_usuario: { + type: Sequelize.INTEGER, + allowNull: false, + }, + lectura: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: true, + }, + escritura: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: true, + }, + eliminar: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: true, + }, + estado: { + type: Sequelize.ENUM('ACTIVO', 'INACTIVO', 'ELIMINADO'), + allowNull: false, + defaultValue: 'ACTIVO', + }, + _usuario_creacion: { + type: Sequelize.INTEGER, + allowNull: false, + }, + _usuario_modificacion: { + type: Sequelize.INTEGER, + }, + _fecha_creacion: { + type: Sequelize.DATE, + allowNull: false, + }, + _fecha_modificacion: { + type: Sequelize.DATE, + } + }); + }, + down: (queryInterface, Sequelize) => {}, +}; diff --git a/src/migrations/00000012-addMenusCatalogo.js b/src/migrations/00000012-addMenusCatalogo.js new file mode 100644 index 0000000..d258e7e --- /dev/null +++ b/src/migrations/00000012-addMenusCatalogo.js @@ -0,0 +1,52 @@ +'use strict'; +const Menu = require('../models/seguridad/menu'); // '../models/Platform'; +module.exports = { + up: (queryInterface, Sequelize) => { + const padre = { + nombre: 'CATALOGOS', + descripcion: 'Bandeja de catalogos', + orden: 1, + ruta: '', + icono: 'folder', + estado: 'ACTIVO', + _fecha_creacion: new Date(), + _fecha_modificacion: new Date(), + _usuario_creacion: 1, + _usuario_modificacion: 1, + } + return queryInterface.bulkInsert('menu', [padre], {}) + .then(() => queryInterface.sequelize.query(`SELECT id_menu from menu where nombre like '${padre.nombre}';`)) + .then(resp => { + const menus = [ + { + nombre: 'MIS CATALOGOS', + descripcion: 'Bandeja de mis catalogos', + orden: 1, + ruta: 'catalogos', + icono: 'folder', + estado: 'ACTIVO', + _fecha_creacion: new Date(), + _fecha_modificacion: new Date(), + _usuario_creacion: 1, + _usuario_modificacion: 1, + fid_menu_padre: resp[0][0].id_menu, + }, + { + nombre: 'COMPARTIDOS', + descripcion: 'Bandeja de catalogos compartidos', + orden: 1, + ruta: 'compartidos', + icono: 'user', + estado: 'ACTIVO', + _fecha_creacion: new Date(), + _fecha_modificacion: new Date(), + _usuario_creacion: 1, + _usuario_modificacion: 1, + fid_menu_padre: resp[0][0].id_menu, + }, + ] + return queryInterface.bulkInsert('menu', menus, {}); + }); + }, + down: (queryInterface, Sequelize) => {}, +}; diff --git a/src/models/monitoreo/monitor.js b/src/models/monitoreo/monitor.js new file mode 100644 index 0000000..9c3f9bb --- /dev/null +++ b/src/models/monitoreo/monitor.js @@ -0,0 +1,69 @@ + +module.exports = (sequelize, DataType) => { + const monitor = sequelize.define("monitor", { + id_monitor: { + type:DataType.INTEGER, + primaryKey:true, + autoIncrement:true, + xlabel:'ID', + }, + fid_usuario:{ + type:DataType.INTEGER, + allowNull:false, + xlabel:'Usuario', + }, + fid_documento:{ + type:DataType.INTEGER, + allowNull:false, + xlabel:'Documento', + }, + fecha_visita:{ + type:DataType.DATEONLY, + allowNull:false, + xlabel:'Fecha de visita', + }, + ip:{ + type:DataType.TEXT, + allowNull: false, + xlabel:'Direccion IP', + }, + mac:{ + type:DataType.TEXT, + xlabel:'Direccion MAC', + }, + contador:{ + type:DataType.INTEGER, + allowNull: false, + xlabel:'Direccion IP', + }, + relacionado:{ + type: DataType.BOOLEAN, + defaultValue:false, + xlabel: 'Tiene relacion', + }, + cite:{ + type: DataType.BOOLEAN, + defaultValue:false, + xlabel: 'Tiene cite', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt:'_fecha_creacion', + updatedAt:'_fecha_modificacion', + freezeTableName:true, + classMethods:{ + associate:(models) => { + + }, + }, + }); + return monitor; +}; diff --git a/src/models/notificacion/conf_notificacion.js b/src/models/notificacion/conf_notificacion.js new file mode 100644 index 0000000..11a192d --- /dev/null +++ b/src/models/notificacion/conf_notificacion.js @@ -0,0 +1,80 @@ +/** + * Modelo para tabla de configuracion de notificaciones. + * @param {type} sequelize + * @param {type} DataType + * @returns unidad + */ +module.exports = (sequelize, DataType) => { + const conf_notificacion = sequelize.define("conf_notificacion", { + id_conf_notificacion: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + fid_usuario: { + type: DataType.INTEGER, + allowNull:false, + unique:true, + references:{ + model:'usuario', + key:'id_usuario', + }, + xlabel: 'Usuario', + }, + celular: { + type: DataType.STRING(10), + allowNull:true, + xlabel: 'Celular', + }, + canal: { + type: DataType.ENUM('SMS', 'CORREO','SMS_CORREO'), + defaultValue: 'CORREO', + xlabel: 'Canal', + }, + enviado: { + type: DataType.BOOLEAN, + defaultValue:false, + xlabel: 'Enviados', + }, + observado: { + type: DataType.BOOLEAN, + defaultValue:true, + xlabel: 'Observaciones', + }, + aprobado: { + type: DataType.BOOLEAN, + defaultValue:false, + xlabel: 'Aprobados', + }, + derivado: { + type: DataType.BOOLEAN, + defaultValue:false, + xlabel: 'Derivados', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => { + conf_notificacion.belongsTo(models.usuario, {as: 'usuario', foreignKey: 'fid_usuario'}); + }, + }, + }); + return conf_notificacion; +}; diff --git a/src/models/notificacion/notificacion.js b/src/models/notificacion/notificacion.js new file mode 100644 index 0000000..4ac0bf0 --- /dev/null +++ b/src/models/notificacion/notificacion.js @@ -0,0 +1,55 @@ +/** + * Modelo para tabla de notificaciones. + * @param {type} sequelize + * @param {type} DataType + * @returns unidad + */ +module.exports = (sequelize, DataType) => { + const notificacion = sequelize.define("notificacion", { + id_notificacion: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + destinatario: { + type: DataType.INTEGER, + allowNull:false, + xlabel: 'Usuario', + }, + canal: { + type: DataType.ENUM('SMS','CORREO','SMS_CORREO'), + allowNull: false, + xlabel: 'Nombre', + }, + mensaje: { + type: DataType.TEXT, + allowNull: false, + xlabel: 'Mensaje', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => { + + }, + }, + }); + return notificacion; +}; diff --git a/src/models/plantillasFormly/catalogo.js b/src/models/plantillasFormly/catalogo.js new file mode 100644 index 0000000..154d275 --- /dev/null +++ b/src/models/plantillasFormly/catalogo.js @@ -0,0 +1,46 @@ +module.exports = (sequelize, DataType) => { + const catalogo = sequelize.define('catalogo', { + id_catalogo: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + nombre: { + type: DataType.TEXT, + allowNull: false, + xlabel: 'Nombre', + }, + descripcion: { + type: DataType.TEXT, + allowNull: false, + xlabel: 'Descripción', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO', 'ELIMINADO'), + allowNull: false, + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + }, { + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + }); + + catalogo.associate = (models) => { + catalogo.hasMany(models.catalogo_usuario, {as: 'catalogo_usuario', foreignKey: 'fid_catalogo'}); + catalogo.hasMany(models.catalogo_documento, {as: 'catalogo_documento', foreignKey: 'fid_catalogo'}); + } + + return catalogo; +}; \ No newline at end of file diff --git a/src/models/plantillasFormly/catalogo_documento.js b/src/models/plantillasFormly/catalogo_documento.js new file mode 100644 index 0000000..2b37737 --- /dev/null +++ b/src/models/plantillasFormly/catalogo_documento.js @@ -0,0 +1,49 @@ +module.exports = (sequelize, DataType) => { + const catalogo_documento = sequelize.define('catalogo_documento', { + id_catalogo_documento: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + fid_catalogo: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Catalogo', + }, + fid_documento: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Documento', + }, + descripcion: { + type: DataType.TEXT, + allowNull: false, + xlabel: 'Lectura', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO', 'ELIMINADO'), + allowNull: false, + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + }, { + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + + }, + }); + + return catalogo_documento; +}; \ No newline at end of file diff --git a/src/models/plantillasFormly/catalogo_usuario.js b/src/models/plantillasFormly/catalogo_usuario.js new file mode 100644 index 0000000..4dd07a0 --- /dev/null +++ b/src/models/plantillasFormly/catalogo_usuario.js @@ -0,0 +1,62 @@ +module.exports = (sequelize, DataType) => { + const catalogo_usuario = sequelize.define('catalogo_usuario', { + id_catalogo_usuario: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + fid_catalogo: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Catalogo', + }, + fid_usuario: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario', + }, + lectura: { + type: DataType.BOOLEAN, + allowNull: false, + defaultValue: true, + xlabel: 'Lectura', + }, + escritura: { + type: DataType.BOOLEAN, + allowNull: false, + defaultValue: false, + xlabel: 'Escritura', + }, + eliminar: { + type: DataType.BOOLEAN, + allowNull: false, + defaultValue: false, + xlabel: 'Eliminar', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO', 'ELIMINADO'), + allowNull: false, + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + }, { + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + }); + + catalogo_usuario.associate = (models) => { + catalogo_usuario.belongsTo(models.catalogo, { as:'catalogo', foreignKey:'fid_catalogo' }); + } + return catalogo_usuario; +}; \ No newline at end of file diff --git a/src/models/plantillasFormly/contacto.js b/src/models/plantillasFormly/contacto.js new file mode 100644 index 0000000..432c4b9 --- /dev/null +++ b/src/models/plantillasFormly/contacto.js @@ -0,0 +1,79 @@ + + +module.exports = (sequelize, DataType) => { + const contacto = sequelize.define('contacto', { + id_contacto: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + grado: { + type: DataType.STRING(150), + allowNull: true, + xlabel: 'Grado', + }, + nombres: { + type: DataType.STRING(150), + allowNull: false, + xlabel: 'Nombres', + }, + apellidos: { + type: DataType.STRING(150), + allowNull: false, + xlabel: 'Apellidos', + }, + cargo: { + type: DataType.STRING(250), + xlabel: 'Cargo', + }, + entidad: { + type: DataType.STRING(250), + xlabel: 'Entidad', + }, + tipo_entidad: { + type: DataType.STRING(250), + xlabel: 'Tipo entidad', + }, + sigla: { + type: DataType.STRING(80), + xlabel: 'Sigla', + }, + direccion: { + type: DataType.TEXT, + xlabel: 'Dirección', + }, + telefono: { + type: DataType.TEXT, + xlabel: 'Teléfono', + }, + departamento: { + type: DataType.STRING(50), + xlabel: 'departamento', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + allowNull: false, + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + }, { + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => {}, + }, + }); + + return contacto; +}; \ No newline at end of file diff --git a/src/models/plantillasFormly/correlativo.js b/src/models/plantillasFormly/correlativo.js new file mode 100644 index 0000000..59ed6a1 --- /dev/null +++ b/src/models/plantillasFormly/correlativo.js @@ -0,0 +1,55 @@ +/** + * Modelo para tabla de Documentos + * @param {type} sequelize + * @param {type} DataType + * @returns correlativo + */ +module.exports = (sequelize, DataType) => { + const correlativo = sequelize.define("correlativo", { + id_correlativo: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + abreviacion: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nombre', + }, + valor: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Plantilla', + }, + anio: { + type: DataType.STRING(4), + allowNull: false, + xlabel: 'Plantilla', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => { + + }, + }, + }); + return correlativo; +}; diff --git a/src/models/plantillasFormly/documento.js b/src/models/plantillasFormly/documento.js new file mode 100644 index 0000000..f6d83bf --- /dev/null +++ b/src/models/plantillasFormly/documento.js @@ -0,0 +1,138 @@ +/** + * Modelo para tabla de Documentos + * @param {type} sequelize + * @param {type} DataType + * @returns documento + */ +module.exports = (sequelize, DataType) => { + const documento = sequelize.define("documento", { + id_documento: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + nombre: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nombre', + }, + plantilla: { + type: DataType.TEXT, + allowNull: false, + xlabel: 'Plantilla', + }, + plantilla_valor: { + type: DataType.TEXT, + allowNull: false, + xlabel: 'Valores', + }, + nombre_plantilla: { + type: DataType.TEXT, + allowNull: true, + xlabel: 'Tipo de documento', + }, + abreviacion: { + type: DataType.STRING, + allowNull: true, + xlabel: 'Abreviación', + }, + de: { + type: DataType.TEXT, + allowNull: true, + xlabel: 'De:', + }, + para: { + type: DataType.TEXT, + allowNull: true, + xlabel: 'Para:', + }, + via: { + type: DataType.TEXT, + allowNull: true, + xlabel: 'Via', + }, + via_actual: { + type: DataType.INTEGER, + allowNull: true, + xlabel: 'Via', + }, + firmado: { + type: DataType.BOOLEAN, + xlabel: 'Firmado', + defaultValue: false, + }, + firmante_actual: { + type: DataType.INTEGER, + xlabel: 'firmante actual', + }, + firmaron: { + type: DataType.ARRAY(DataType.INTEGER), + xlabel: 'Firmaron', + }, + referencia: { + type: DataType.TEXT, + allowNull: true, + xlabel: 'Ref.:', + }, + fecha: { + type: DataType.DATE, + allowNull: true, + xlabel: 'Fecha', + }, + observaciones: { + type: DataType.TEXT, + allowNull: true, + xlabel: 'Observaciones', + }, + impreso: { + type: DataType.ENUM('SI', 'NO'), + allowNull: true, + defaultValue: 'NO', + xlabel: 'Impreso', + }, + anulado: { + type: DataType.BOOLEAN, + defaultValue: false, + xlabel: 'Anulado', + }, + documento_padre: { + type: DataType.INTEGER, + xlabel: 'Derivado de', + }, + grupo: { + type: DataType.INTEGER, + xlabel: 'Grupo', + }, + multiple: { + type: DataType.TEXT, + xlabel: 'Código multiple', + }, + estado: { + type: DataType.ENUM('NUEVO', 'ENVIADO', 'APROBADO', 'RECHAZADO','DERIVADO','CERRADO','ELIMINADO'), + defaultValue: 'NUEVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + + }, + }); + + documento.associate = (models) => { + documento.hasOne(models.firma, {as:'firma', foreignKey:'fid_documento'}); + }; + return documento; +}; diff --git a/src/models/plantillasFormly/historial_flujo.js b/src/models/plantillasFormly/historial_flujo.js new file mode 100644 index 0000000..6bc0f07 --- /dev/null +++ b/src/models/plantillasFormly/historial_flujo.js @@ -0,0 +1,53 @@ +/** + * Modelo para tabla de Documentos + * @param {type} sequelize + * @param {type} DataType + * @returns historial_flujo + */ +module.exports = (sequelize, DataType) => { + const historial_flujo = sequelize.define("historial_flujo", { + id_historial_flujo: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + id_documento: { + type: DataType.INTEGER, + xlabel: 'ID_DOCUMENTO', + }, + accion: { + type: DataType.ENUM('ENVIADO', 'APROBADO','RECHAZADO','DERIVADO','CERRADO','CREADO','ELIMINADO', 'FIRMO'), + xlabel: 'Accion', + }, + observacion: { + type: DataType.STRING, + xlabel: 'Observación', + }, + estado: { + type: DataType.ENUM('INACTIVO', 'ACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + allowNull: true, + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => {}, + }, + + }); + + return historial_flujo; +}; diff --git a/src/models/plantillasFormly/plantilla_formly.js b/src/models/plantillasFormly/plantilla_formly.js new file mode 100644 index 0000000..d7cb2a7 --- /dev/null +++ b/src/models/plantillasFormly/plantilla_formly.js @@ -0,0 +1,60 @@ +/** + * Modelo para tabla de Plantilla Formly + * @param {type} sequelize + * @param {type} DataType + * @returns plantilla + */ +module.exports = (sequelize, DataType) => { + const plantillaFormly = sequelize.define("plantilla_formly", { + id_plantilla_formly: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + nombre: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nombre', + }, + abreviacion: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Abreviación', + }, + plantilla: { + type: DataType.TEXT, + allowNull: false, + xlabel: 'Plantilla', + }, + plantilla_valor: { + type: DataType.TEXT, + allowNull: true, + xlabel: 'Valores', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => { + + }, + }, + }); + return plantillaFormly; +}; diff --git a/src/models/presupuesto/partida.js b/src/models/presupuesto/partida.js new file mode 100644 index 0000000..d04a6d1 --- /dev/null +++ b/src/models/presupuesto/partida.js @@ -0,0 +1,91 @@ +/** + * Modelo para tabla de Menus + * @param {type} DataType + * @returns partida + */ +module.exports = (sequelize, DataType) => { + const partida = sequelize.define("partida", { + id_partida: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + cite_ref: { + type: DataType.STRING(100), + allowNull: true, + xlabel: 'Cite', + }, + cite: { + type: DataType.STRING(100), + allowNull: true, + xlabel: 'Cite', + }, + numero: { + type: DataType.STRING(50), + allowNull: false, + xlabel: 'Código', + }, + descripcion: { + type: DataType.TEXT, + allowNull: true, + xlabel: 'Descripción', + }, + monto: { + type: DataType.DECIMAL(15,2), + xlabel: 'Valor inicial', + }, + fid_partida: { + type: DataType.INTEGER, + xlabel: 'Id de la partida ligada', + }, + multiple: { + type: DataType.INTEGER, + xlabel: 'Id de la partida a quien pertenece el pago multiple', + }, + gestion: { + type: DataType.STRING(5), + allowNull: false, + xlabel: 'Gestión', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + allowNull: false, + defaultValue: 'ACTIVO', + validate: { + isIn:{args:[['ACTIVO', 'INACTIVO']], msg:"Debe seleccionar una opcion de estado."}, + }, + xlabel: 'Estado', + }, + tipo: { + type: DataType.ENUM('INICIAL', 'MODIFICADO', 'COMPROMETIDO', 'PAGADO', 'REVERTIDO'), + allowNull: false, + validate: { + isIn:{args:[['INICIAL', 'MODIFICADO', 'COMPROMETIDO', 'PAGADO', 'REVERTIDO']], msg:"Debe seleccionar una opción de tipo."}, + }, + xlabel: 'Tipo', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => { + // partida.belongsTo(models.partida, {as: 'menu_padre', foreignKey: 'fid_menu_padre'}); + // partida.hasMany(models.partida, {as: 'submenu', foreignKey: 'fid_menu_padre'}); + // partida.hasMany(models.rol_menu, {as: 'rol_menu', foreignKey: 'fid_menu'}); + }, + }, + }); + + return partida; +}; diff --git a/src/models/seguridad/auth.js b/src/models/seguridad/auth.js new file mode 100644 index 0000000..63e9613 --- /dev/null +++ b/src/models/seguridad/auth.js @@ -0,0 +1,41 @@ +/** + * auth + * + * @module + * + **/ + +module.exports = (sequelize, DataType) => { + const auth = sequelize.define('auth', { + state: { + type: DataType.STRING(100), + allowNull: false, + unique: 'uniqueSelectedItem', + }, + parametros: { // nonce + type: DataType.JSONB, + allowNull: true, + }, + tokens: { // id_token, access_token, refresh_token + type: DataType.JSONB, + allowNull: true, + }, + id_usuario: { // id_usuario + type: DataType.STRING(20), + allowNull: true, + }, + estado: { + type: DataType.STRING(30), + allowNull: false, + defaultValue: 'INICIO', + validate: { + isIn: { args: [['INICIO', 'ACTIVO', 'ELIMINADO']], msg: 'Estado no permitido.' }, + }, + }, + }, { + timestamps: true, + classMethods: {}, + tableName: 'auth', + }); + return auth; +}; diff --git a/src/models/seguridad/auth_user.js b/src/models/seguridad/auth_user.js new file mode 100644 index 0000000..8a25312 --- /dev/null +++ b/src/models/seguridad/auth_user.js @@ -0,0 +1,109 @@ +/** + * Modelo para datos de usuario (del sistema de control de personal) + * + **/ +module.exports = (sequelize, DataType) => { + const auth_user = sequelize.define("auth_user", { + id: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + password: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Contraseña', + }, + last_login: { + type: DataType.DATE, + allowNull: true, + xlabel: 'Fecha', + }, + is_superuser: { + type: DataType.BOOLEAN, + allowNull: false, + xlabel: 'Superusuario', + }, + username: { + type: DataType.STRING, + allowNull: false, + unique: true, + xlabel: 'Nombre de usuario', + }, + first_name: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nombre(s)', + }, + last_name: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Apellidos', + }, + email: { + type: DataType.STRING, + allowNull: false, + validate: { + isEmail: true, + }, + xlabel: 'Correo electrónico', + }, + is_staff: { + type: DataType.BOOLEAN, + allowNull: false, + xlabel: 'Staff', + }, + is_active: { + type: DataType.BOOLEAN, + allowNull: false, + xlabel: 'Activo', + }, + date_joined: { + type: DataType.DATE, + allowNull: false, + xlabel: 'Fecha ingreso', + }, + cargo: { + type: DataType.STRING, + xlabel: 'Cargo', + allowNull: true, + }, + ci: { + type: DataType.STRING, + xlabel: 'CI', + allowNull: true, + }, + habilitado_marcar: { + type: DataType.BOOLEAN, + allowNull: false, + xlabel: 'Habilitado marcar', + }, + cas: { + type: DataType.INTEGER, + allowNull: true, + xlabel: 'Habilitado', + }, + fecha_asignacion: { + type: DataType.DATE, + allowNull: true, + xlabel: 'Fecha de asignación', + }, + nro_item: { + type: DataType.INTEGER, + allowNull: true, + xlabel: 'Nro Item', + }, + unidad_dependencia: { + type: DataType.STRING, + xlabel: 'Unidad', + allowNull: true, + }, + + },{ + freezeTableName: true, + timestamps: false, + }); + + return auth_user; +}; diff --git a/src/models/seguridad/firma.js b/src/models/seguridad/firma.js new file mode 100644 index 0000000..1cbbb94 --- /dev/null +++ b/src/models/seguridad/firma.js @@ -0,0 +1,39 @@ +module.exports = (sequelize, DataType) => { + const firma = sequelize.define('firma', { + id_firma: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID' + }, + hash: { + type: DataType.TEXT, + xlabel: 'hash' + }, + codigo: { + type: DataType.STRING(10), + allowNull: false, + xlabel: 'Código' + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación' + }, + _usuario_modificacion: { + type: DataType.INTEGER + } + }, { + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + + } + }); + + firma.associate= (models) => { + firma.belongsTo(models.documento, {as: 'documento', foreignKey:'fid_documento'}); + }; + return firma; +}; diff --git a/src/models/seguridad/menu.js b/src/models/seguridad/menu.js new file mode 100644 index 0000000..241303f --- /dev/null +++ b/src/models/seguridad/menu.js @@ -0,0 +1,118 @@ +/** + * Modelo para tabla de Menus + * @param {type} DataType + * @returns menu + */ +module.exports = (sequelize, DataType) => { + const menu = sequelize.define("menu", { + id_menu: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + fid_menu_padre: { + type: DataType.INTEGER, + allowNull: true, + references: { + model: 'menu', + key: 'id_menu', + onDelete: 'cascade', + xchoice:'nombre', + }, + xlabel:'Menú padre', + }, + nombre: { + type: DataType.STRING(100), + allowNull: false, + unique: true, + xlabel: 'Nombre', + }, + descripcion: { + type: DataType.STRING(150), + allowNull: true, + xlabel: 'Descripción', + }, + orden: { + type: DataType.INTEGER, + xlabel: 'Orden', + }, + ruta: { + type: DataType.STRING(100), + allowNull: true, + xlabel: 'Ruta', + }, + icono: { + type: DataType.STRING(100), + allowNull: true, + xlabel: 'Ícono', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + allowNull: false, + defaultValue: 'ACTIVO', + validate: { + isIn:{args:[['ACTIVO', 'INACTIVO']], msg:"Debe seleccionar una opcion de estado."}, + }, + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + + buscarMenusSubmenus: () => menu.findAll({ + attributes: ["id_menu", "nombre", "descripcion", "orden", "ruta", "icono", "estado", "fid_menu_padre"], + where: {estado: 'ACTIVO', fid_menu_padre: null}, + include: [ + { + model: sequelize.models.menu, + join: 'left', + attributes: ["id_menu", "nombre", "descripcion", "orden", "ruta", "icono", "estado", "fid_menu_padre"], + as: 'submenu', + where: {estado: 'ACTIVO'}, + paranoid: false, + required: false, + order: 'orden ASC', + }, + ], + order: 'orden ASC', + }), + buscarPorId: (id_menu) => menu.findById(id_menu, { + attributes: ["id_menu", "nombre", "descripcion", "orden", "ruta", "icono", "estado", "fid_menu_padre"], + }), + }, + }); + menu.associate= (models) => { + menu.belongsTo(models.menu, {as: 'menu_padre', foreignKey: 'fid_menu_padre'}); + menu.hasMany(models.menu, {as: 'submenu', foreignKey: 'fid_menu_padre'}); + menu.hasMany(models.rol_menu, {as: 'rol_menu', foreignKey: 'fid_menu'}); + }; + menu.beforeCreate((menu, options) => { + if (menu.nombre == undefined) { + throw new Error("El campo nombre menú es obligatorio."); + } + if(menu.nombre != null) + menu.nombre = menu.nombre.toUpperCase(); + }); + + menu.beforeUpdate((menu, options) => { + if (menu.nombre == undefined) { + throw new Error("El campo nombre menú es obligatorio."); + } + if(menu.nombre != null) + menu.nombre = menu.nombre.toUpperCase(); + }); + + return menu; +}; diff --git a/src/models/seguridad/rol.js b/src/models/seguridad/rol.js new file mode 100644 index 0000000..58a5c7c --- /dev/null +++ b/src/models/seguridad/rol.js @@ -0,0 +1,62 @@ +/** + * Módulo que mapea los ROLES. + * + * @module + * + **/ + +module.exports = (sequelize, DataType) => { + const rol = sequelize.define("rol", { + id_rol: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + nombre: { + type: DataType.STRING(100), + allowNull: false, + xlabel: 'Nombre', + }, + descripcion: { + type: DataType.STRING, + allowNull: true, + xlabel: 'Descripción', + }, + peso: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Peso', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + buscar: (condicion) => rol.findAll({ + attributes: ["id_rol", "nombre", "descripcion", "peso", "estado"], + where: condicion, + order: 'fecha_creacion ASC', + }), + }, + }); + rol.associate = (models) => { + rol.hasMany(models.rol_menu, {as: 'rol_menu',foreignKey: 'fid_rol'}); + rol.hasMany(models.usuario_rol, {as: 'usuario_rol',foreignKey: 'fid_rol'}); + }; + return rol; +}; diff --git a/src/models/seguridad/rol_menu.js b/src/models/seguridad/rol_menu.js new file mode 100644 index 0000000..4e167c0 --- /dev/null +++ b/src/models/seguridad/rol_menu.js @@ -0,0 +1,69 @@ +/** + * Módulo que mapea los ROLES_MENUS. + * + * @module + * + **/ + +module.exports = (sequelize, DataType) => { + const rol_menu = sequelize.define("rol_menu", { + id_rol_menu: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'Id rol menú', + }, + fid_rol: { + type: DataType.INTEGER, + allowNull: false, + references: { + model: 'rol', + key: 'id_rol', + onDelete: 'cascade', + }, + xchoice:'rol', + unique: 'compositeIndex', + }, + fid_menu: { + type: DataType.INTEGER, + allowNull: false, + references: { + model: 'menu', + key: 'id_menu', + onDelete: 'cascade', + }, + xchoice:'menu', + unique: 'compositeIndex', + }, + estado: { + type: DataType.STRING(30), + allowNull: false, + defaultValue: 'ACTIVO', + validate: { + isIn: {args: [['ACTIVO', 'INACTIVO', 'ELIMINADO']], msg: "El campo estado sólo permite valores: ACTIVO, INACTIVO o ELIMINADO."}, + }, + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + + }, + }); + rol_menu.associate = (models) => { + rol_menu.belongsTo(models.rol, {as: 'rol', foreignKey: 'fid_rol'}); + rol_menu.belongsTo(models.menu, {as: 'menu', foreignKey: 'fid_menu'}); + }; + return rol_menu; +}; diff --git a/src/models/seguridad/unidad.js b/src/models/seguridad/unidad.js new file mode 100644 index 0000000..ee81944 --- /dev/null +++ b/src/models/seguridad/unidad.js @@ -0,0 +1,50 @@ +/** + * Modelo para tabla de Unidades organizacionales + * @param {type} sequelize + * @param {type} DataType + * @returns unidad + */ +module.exports = (sequelize, DataType) => { + const unidad = sequelize.define("unidad", { + id_unidad: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + nombre: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nombre', + }, + abreviacion: { + type: DataType.TEXT, + allowNull: false, + xlabel: 'Abreviación', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => { + + }, + }, + }); + return unidad; +}; diff --git a/src/models/seguridad/usuario.js b/src/models/seguridad/usuario.js new file mode 100644 index 0000000..1ea24c2 --- /dev/null +++ b/src/models/seguridad/usuario.js @@ -0,0 +1,110 @@ +/** + * Modelo para Usuarios del sistema + * + **/ +const crypto = require("crypto"); + + +module.exports = (sequelize, DataType) => { + const usuario = sequelize.define("usuario", { + id_usuario: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + fid_unidad: { + type: DataType.INTEGER, + allowNull: true, + references: { + model: 'unidad', + key: 'id_unidad', + }, + xchoice:'abreviacion', + }, + usuario: { + type: DataType.STRING, + allowNull: false, + unique: true, + xlabel: 'Nombre de usuario', + }, + contrasena: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Contraseña', + }, + numero_documento: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nro documento de identidad', + }, + nombres: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nombre(s)', + }, + apellidos: { + type: DataType.STRING, + xlabel: 'Apellidos', + allowNull: false, + }, + cargo: { + type: DataType.STRING, + xlabel: 'Cargo', + allowNull: false, + }, + email: { + type: DataType.STRING, + allowNull: false, + validate: { + isEmail: true, + }, + xlabel: 'Correo electrónico', + }, + virtual: { + type: DataType.BOOLEAN, + xlabel: 'virtual', + defaultValue: false, + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + + + }); + usuario.associate= (models) => { + usuario.hasMany(models.usuario_rol, {as: 'usuario_rol', foreignKey: 'fid_usuario'}); + usuario.belongsTo(models.unidad, {as: 'unidad', foreignKey: 'fid_unidad'}); + usuario.hasOne(models.conf_notificacion, {as: 'configuracion', foreignKey: 'fid_usuario'}); + }; + + //Hash password usuario MD5 para eventos de actualizacion y creacion + const hashPasswordHook = (instance) => { + if (!instance.changed('contrasena')) return false; + const contrasena = instance.get('contrasena'); + const password = crypto.createHash("md5").update(contrasena).digest("hex"); + instance.set('contrasena', password); + }; + usuario.beforeCreate((usuario, options) => { + hashPasswordHook(usuario); + usuario.usuario = usuario.usuario.toLowerCase(); + }); + + // usuario.beforeUpdate(hashPasswordHook); + return usuario; +}; diff --git a/src/models/seguridad/usuario_his.js b/src/models/seguridad/usuario_his.js new file mode 100644 index 0000000..31df9bb --- /dev/null +++ b/src/models/seguridad/usuario_his.js @@ -0,0 +1,83 @@ +/** + * Modelo para Usuarios del sistema + * + **/ + + +module.exports = (sequelize, DataType) => { + const usuario = sequelize.define("usuario_his", { + id_usuario_his: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + fid_usuario: { + type: DataType.INTEGER, + allowNull:false, + references:{ + model:'usuario', + key:'id_usuario', + }, + xlabel: 'Usuario', + }, + usuario: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nombre de usuario', + }, + contrasena: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Contraseña', + }, + numero_documento: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nro documento de identidad', + }, + nombre: { + type: DataType.STRING, + allowNull: false, + xlabel: 'Nombre(s)', + }, + apellido: { + type: DataType.STRING, + xlabel: 'Apellidos', + allowNull: false, + }, + cargo: { + type: DataType.STRING, + xlabel: 'Cargo', + allowNull: false, + }, + email: { + type: DataType.STRING, + allowNull: false, + validate: { + isEmail: true, + }, + xlabel: 'Correo electrónico', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + + }); + return usuario; +}; diff --git a/src/models/seguridad/usuario_rol.js b/src/models/seguridad/usuario_rol.js new file mode 100644 index 0000000..b208dd2 --- /dev/null +++ b/src/models/seguridad/usuario_rol.js @@ -0,0 +1,65 @@ +/** + * Módulo que mapea los USUARIOS_ROLES. + * + * @module + * + **/ + +module.exports = (sequelize, DataType) => { + const usuario_rol = sequelize.define("usuario_rol", { + id_usuario_rol: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'Id usuario rol', + }, + fid_usuario: { + type: DataType.INTEGER, + allowNull: false, + references: { + model: 'usuario', + key: 'id_usuario', + onDelete: 'cascade', + }, + xchoice:'usuario', + }, + fid_rol: { + type: DataType.INTEGER, + allowNull: false, + references: { + model: 'rol', + key: 'id_rol', + onDelete: 'cascade', + }, + xchoice:'rol', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + allowNull: false, + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + },{ + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + + }, + }); + + usuario_rol.associate= (models) => { + usuario_rol.belongsTo(models.usuario, {as: 'usuario_rol',foreignKey: 'fid_usuario'}); + usuario_rol.belongsTo(models.rol, {as: 'rol',foreignKey: 'fid_rol'}); + }; + return usuario_rol; +}; diff --git a/src/models/seguridad/virtual.js b/src/models/seguridad/virtual.js new file mode 100644 index 0000000..047a5fd --- /dev/null +++ b/src/models/seguridad/virtual.js @@ -0,0 +1,42 @@ +module.exports = (sequelize, DataType) => { + const virtual = sequelize.define("virtual", { + id_virtual: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + fid_usuario_titular: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Titular', + }, + fid_usuario_virtual: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Descripción', + }, + estado: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Estado', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + }, { + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => {}, + }, + }); + return virtual; +}; diff --git a/src/models/seguridad/virtual_his.js b/src/models/seguridad/virtual_his.js new file mode 100644 index 0000000..16fc3dc --- /dev/null +++ b/src/models/seguridad/virtual_his.js @@ -0,0 +1,47 @@ +module.exports = (sequelize, DataType) => { + const virtual_his = sequelize.define("virtual_his", { + id_virtual_his: { + type: DataType.INTEGER, + primaryKey: true, + autoIncrement: true, + xlabel: 'ID', + }, + fid_virtual: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'origen', + }, + id_virtual: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'titular', + }, + id_titular: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Descripción', + }, + accion: { + type: DataType.ENUM('ACTIVO', 'INACTIVO'), + defaultValue: 'ACTIVO', + xlabel: 'Accion', + }, + _usuario_creacion: { + type: DataType.INTEGER, + allowNull: false, + xlabel: 'Usuario de creación', + }, + _usuario_modificacion: { + type: DataType.INTEGER, + xlabel: 'Usuario de modificación', + }, + }, { + createdAt: '_fecha_creacion', + updatedAt: '_fecha_modificacion', + freezeTableName: true, + classMethods: { + associate: (models) => {}, + }, + }); + return virtual_his; +}; diff --git a/src/openid.js b/src/openid.js new file mode 100644 index 0000000..99ca0fc --- /dev/null +++ b/src/openid.js @@ -0,0 +1,22 @@ +const Issuer = require('openid-client').Issuer; +let client = null; +let issuer = null; + +module.exports = async (app) => { + if (!client) { + const config = app.src.config.config; + + async function discovery() { + if (!issuer) { + issuer = await Issuer.discover(config.issuer); + } + return issuer; + } + + issuer = await discovery(); + // inicializamos datos de registro del cliente + client = new issuer.Client(app.src.config.config.client); + client.CLOCK_TOLERANCE = 5; + } + return client; +}; diff --git a/src/routes/almacenActivos/activosRT.js b/src/routes/almacenActivos/activosRT.js new file mode 100644 index 0000000..633d342 --- /dev/null +++ b/src/routes/almacenActivos/activosRT.js @@ -0,0 +1,101 @@ +const _ = require('lodash'); +const moment = require('moment'); + +const util = require('../../lib/util'); +const libActivos = require('../../lib/activos'); +module.exports = app => { + const modelos = app.src.db.models; + const Op = app.src.db.Sequelize.Op; + + app.get('/api/v1/activos/consulta', (req, res) => { + return libActivos.consultar(req.query.filter) + .then(resp => res.status(200).send(util.formatearMensaje('EXITO', 'Consulta exitosa', resp))) + .catch(error => { + console.log('[activosRT] Error: ', error); + return res.status(400).send(util.formatearMensaje('ERROR', error.message ? error.message : error)); + }); + }); + + app.get('/api/v1/activos/consulta/usuario/:ci', (req, res) => { + return libActivos.consultarPorUsuario(req.params.ci) + .then(resp => res.status(200).send(util.formatearMensaje('EXITO', 'Consulta exitosa', resp))) + .catch(error => { + console.log('[activosRT] Error: ', error); + return res.status(400).send(util.formatearMensaje('ERROR', error.message ? error.message : error)); + }); + }); + + app.post('/api/v1/activos/asignacion', (req, res) => { + return libActivos.asignar(req.body) + .then(resp => res.status(200).send(util.formatearMensaje('EXITO', 'Consulta exitosa', resp))) + .catch(error => { + console.log('[activosRT] Error: ', error); + return res.status(400).send(util.formatearMensaje('ERROR', error.message ? error.message : error)); + }); + }); + + app.post('/api/v1/activos/devolucion', (req, res) => { + return libActivos.devolver(req.body) + .then(resp => res.status(200).send(util.formatearMensaje('EXITO', 'Consulta exitosa', resp))) + .catch(error => { + console.log('[activosRT] Error: ', error); + return res.status(400).send(util.formatearMensaje('ERROR', error.message ? error.message : error)); + }); + }); + + app.post('/api/v1/activos/recuperar', (req, res) => { + const Documento = modelos.documento; + return Documento.findOne({ + fields: ['id_documento', 'plantilla', 'estado', 'plantilla_valor', 'anulado'], + where: { + nombre: { + [Op.like]: req.body.cite, + }, + }, + }) + .then(docResp => { + if (!docResp) throw new Error('No existe el documento solicitado'); + + const datosPlantilla = JSON.parse(docResp.plantilla_valor); + let listaActivosSolicitados = null; + let tipoFormulario = null; + + let documentoDe = { nombre: null, cargo: null }; + let documentoPara = { nombre: null, cargo: null }; + + for (const key in datosPlantilla) { + if (key.indexOf('tablaActivos-') > -1) { + listaActivosSolicitados = datosPlantilla[key].filas; + tipoFormulario = datosPlantilla[key].tipoFormulario; + // solicitadoPor = datosPlantilla[key].solicitadoPor; + // entregadoPor = datosPlantilla[key].entregadoPor; + // devueltoPor = datosPlantilla[key].devueltoPor; + } + if (key.indexOf('datosGenerales-') > -1) { + documentoDe = datosPlantilla[key].de[0]; + documentoPara = datosPlantilla[key].para; + } + } + + if (!tipoFormulario || tipoFormulario !== 'SOLICITUD') { + throw new Error('Debe ingresar el CITE de un documento de tipo SOLICITUD de activos fijos.'); + } + + // if (tipoFormulario === 'SOLICITUD') { + // solicitadoPor = documentoDe; + // entregadoPor = documentoPara; + // devueltoPor = documentoPara; + // } + const cabecera = { + documentoDe, + documentoPara, + }; + return { items: listaActivosSolicitados, cabecera }; + }) + .then(resp => res.status(200).send(util.formatearMensaje('EXITO', 'Consulta exitosa', resp))) + .catch(error => { + console.log('[activosRT] Error: ', error); + return res.status(400).send(util.formatearMensaje('ERROR', error.message ? error.message : error)); + }); + }); +}; diff --git a/src/routes/almacenActivos/almacenRT.js b/src/routes/almacenActivos/almacenRT.js new file mode 100644 index 0000000..96b21a2 --- /dev/null +++ b/src/routes/almacenActivos/almacenRT.js @@ -0,0 +1,51 @@ +require('colors'); +const _ = require('lodash'); +const libAlmacen = require('../../lib/almacen'); + +module.exports = app => { + const util = require('../../lib/util'); + const modelos = app.src.db.models; + const Op = app.src.db.Sequelize.Op; + app.get('/api/v1/almacen/consulta', (req,res) => { + return libAlmacen.consultar(req.query.filter || '', req.query.todos || 0) + .then(resp => res.status(200).send(util.formatearMensaje('EXITO', 'Consulta exitosa', resp))) + .catch(error => res.status(412).send(util.formatearMensaje('ERROR', error))); + }); + + app.get('/api/v1/almacen/proveedor', (req,res) => libAlmacen.consultarProveedores(req.query.filter || '') + .then(resp => res.status(200).send(util.formatearMensaje('EXITO', 'Consulta exitosa', resp))) + .catch(error => res.status(412).send(util.formatearMensaje('ERROR', error)))); + + app.post('/api/v1/almacen/recuperar', (req,res) => { + const Documento = modelos.documento; + let solicitante; + let idSolicitud = null; + return Documento.findOne({ + fields: ['id_documento', 'plantilla_valor', 'estado', 'plantilla_valor', 'anulado'], + where: { + nombre: { + [Op.like]: req.body.cite, + }, + }, + }) + .then(docResp => { + const datosPlantilla = JSON.parse(docResp.plantilla_valor); + for (const key in datosPlantilla) { + if (key.indexOf('consultaAlmacen-') > -1) { + idSolicitud = datosPlantilla[key].solicitud; + } + if (key.indexOf('datosGenerales-') > -1) { + solicitante = `${datosPlantilla[key].de[0].nombres} ${datosPlantilla[key].de[0].apellidos}`; + } + } + return libAlmacen.recuperar(idSolicitud); + }) + .then(respItems => { + respItems.cabecera.solicitado_por = solicitante; + respItems.cite_sms = req.body.cite; + respItems.id_solicitud = idSolicitud; + return res.status(200).send(util.formatearMensaje('EXITO', 'Recuperacion exitosa de la entrega.', respItems)); + }) + .catch(error => res.status(412).send(util.formatearMensaje('ERROR', error))); + }); +}; \ No newline at end of file diff --git a/src/routes/monitoreo/documentosUsuarioEstadoRT.js b/src/routes/monitoreo/documentosUsuarioEstadoRT.js new file mode 100644 index 0000000..63bc3ee --- /dev/null +++ b/src/routes/monitoreo/documentosUsuarioEstadoRT.js @@ -0,0 +1,98 @@ + +module.exports = app => { + const partida = app.src.db.models.partida; + const documento = app.src.db.models.documento; + const util = require('../../lib/util'); + const moment = require('moment'); + //const sequelize = require('sequelize'); + const Promise = require('bluebird'); + + const config = app.src.config.config; + const sequelize = app.src.db.sequelize; + // final = moment(`${req.query.final}`, 'YYYY-MM-DD').tz('America/La_Paz').format(), + +/** + @apiVersion 2.0.0 + @apiGroup Monitoreo + @apiName Get estados + @api {get} /api/v1/monitoreo/estados?fechaInicial=&fechaFinal= Obtiene lista de estados de documento por usuario + + @apiDescription Get estados, Obtiene la lista de documentos por estado y usuario desde una fecha inicial a otra final + + @apiParam (Query) {Texto} fechaInicial Fecha y hora desde la que se desea el reporte + @apiParam (Query) {Texto} fechaFinal Fecha y hora hasta la que se desea el reporte + + @apiSuccess (Respuesta) {Texto} _usuario_creacion Usuario + @apiSuccess (Respuesta) {Texto} nombres Nombres del usuario + @apiSuccess (Respuesta) {Texto} apellidos Apellios del usuario + @apiSuccess (Respuesta) {Texto} CREADO Total creados + @apiSuccess (Respuesta) {Texto} ENVIADO Total enviados + @apiSuccess (Respuesta) {Texto} DERIVADO Total derivados + @apiSuccess (Respuesta) {Texto} APROBADO Total aprobados + @apiSuccess (Respuesta) {Texto} RECHAZADO Total rechazados + @apiSuccess (Respuesta) {Texto} CERRADO Total cerrados + @apiSuccess (Respuesta) {Texto} ELIMINADO Total eliminados + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Obtención de datos exitosa.", + "datos": [ + { + "_usuario_creacion": 4, + "nombres": "Juana", + "apellidos": "Arco", + "CREADO": null, + "ENVIADO": 2, + "DERIVADO": null, + "APROBADO": null, + "RECHAZADO": null, + "CERRADO": null, + "ELIMINADO": null + }, + { + "_usuario_creacion": 3, + "nombres": "Juan", + "apellidos": "Perez", + "CREADO": null, + "ENVIADO": 1, + "DERIVADO": null, + "APROBADO": null, + "RECHAZADO": null, + "CERRADO": null, + "ELIMINADO": null + } + ... + ] + } + @apiSampleRequest off +*/ + + app.get('/api/v1/monitoreo/estados', (req, res) => { + var fechaInicial = new Date(req.query.fechaInicial); + var fechaFinal = new Date(req.query.fechaFinal); + + var qry = "select * from crosstab($$ " + + "select h._usuario_creacion, u.nombres , u.apellidos, h.accion, count(h.accion) " + + "from historial_flujo h, usuario u " + + "where u.id_usuario = h._usuario_creacion and u.estado = 'ACTIVO' and h._fecha_creacion between :fechaInicial and :fechaFinal " + + "GROUP BY h._usuario_creacion, u.nombres , u.apellidos, h.accion " + + "order by u.nombres , u.apellidos " + + "$$ , $$VALUES ('CREADO'::text), ('ENVIADO'::text), ('DERIVADO'::text), ('APROBADO'::text), ('RECHAZADO'::text), ('CERRADO'::text), ('ELIMINADO'::text) $$) " + + 'as historial("_usuario_creacion" int, "nombres" text, "apellidos" text, "CREADO" int, "ENVIADO" int, "DERIVADO" int, "APROBADO" int, "RECHAZADO" int, "CERRADO" int, "ELIMINADO" int)'; + + sequelize.query(qry, { replacements: { fechaInicial: fechaInicial, fechaFinal: fechaFinal}, type: sequelize.QueryTypes.SELECT }) + .then(resultado => { + if (resultado){ + res.status(200).send(util.formatearMensaje("EXITO", "Obtención de datos exitosa.", resultado)); + }else{ + res.status(200).send(util.formatearMensaje("INFORMACION", "No existen resultados.")); + } + }).catch(pError => { + res.status(412).send(util.formatearMensaje('ERROR', pError)); + }); + }); + + function toFloat(string) { return parseFloat(parseFloat(string).toFixed(2)); } +}; diff --git a/src/routes/monitoreo/monitorRT.js b/src/routes/monitoreo/monitorRT.js new file mode 100644 index 0000000..18f0a55 --- /dev/null +++ b/src/routes/monitoreo/monitorRT.js @@ -0,0 +1,642 @@ +const {ModelHandler} = require("sequelize-handlers"); +const sequelizeFormly = require("sequelize-formly"); +const _ = require("lodash"); +const moment = require('moment'); + +module.exports = app => { + const monitor = app.src.db.models.monitor; + const usuario = app.src.db.models.usuario; + const documento = app.src.db.models.documento; + const config = app.src.config.config; + const sequelize = app.src.db.sequelize; + const Op = app.src.db.Sequelize.Op; + const util = require('../../lib/util'); + const sequelizeHandlers = new ModelHandler(monitor); + + /** + @apiVersion 2.0.0 + @apiGroup Monitoreo + @apiName Get monitoreo/global/ + @api {get} /api/v1/monitoreo/global/ Obtiene lista de gestiones de las que se tengan datos + + @apiDescription Get monitoreo/global/, obtiene lista de gestiones de las que se tengan datos + + @apiParam (Query) {Texto} anio Año del que se desea la información. + @apiParam (Query) {Texto} mes Mes del que se desea la información, expresado como un entero. Ejemplo: 1 para enero. + + @apiSuccess (Respuesta) {Array} nombres Array de nombres de los puntos a graficarse + @apiSuccess (Respuesta) {Array} global Array de puntos + @apiSuccess (Respuesta) {Array} relacionado Array de puntos relacionados + @apiSuccess (Respuesta) {Array} no_relacionado Array de puntos no relacionados + @apiSuccess (Respuesta) {Numérico} total Cantidad total de puntos a graficar + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Obtención de datos exitoso", + "datos": { + "nombres": ["1-1-2020", "2-1-2020", "3-1-2020", ....., "31-1-2020"], + "global": [0, 3, 1, 0, .......], + "relacionado": [0, 3, 1, 0, .......], + "no_relacionado": [0, 0, 0, 0, .......], + "total": 31 + } + } + */ + + app.get('/api/v1/monitoreo/global/', (req,res) => { + const + dm = moment(`${req.query.anio}-${req.query.mes}`,'YYYY-MM').daysInMonth(), + inicio = moment(`${req.query.anio}-${req.query.mes}-1`, 'YYYY-MM').tz('America/La_Paz').format('YYYY-MM-DD'), + final = moment(inicio).tz('America/La_Paz').add(dm-1,'days').format('YYYY-MM-DD'), + total = new Array(dm), + relacionado = new Array(dm), + noRel = new Array(dm), + nombres = []; + let + f, + v, + tot; + total.fill(0,0); + relacionado.fill(0,0); + noRel.fill(0,0); + for (let i = 1; i <= dm; i++) { + nombres.push(`${i}-${req.query.mes}-${req.query.anio}`); + } + + const opcionesMonitor = { + attributes: [ 'fecha_visita','relacionado', [sequelize.fn('SUM', sequelize.col('contador')), 'suma'] ], + where:{ + fecha_visita:{ + [Op.between]:[`${inicio}T04:00:00.000Z`,`${final}T04:00:00.000Z`], + }, + }, + group: ['fecha_visita', 'relacionado'], + order:[['fecha_visita']], + }; + if(req.query.relacion) opcionesMonitor.where.relacionado=req.query.relacion; + + monitor.findAll(opcionesMonitor) + .then( pLog => { + + pLog.forEach((pItem, pIndice) => { + const f=moment(pItem.fecha_visita).tz('America/La_Paz').format('DD-MM-YYYY'); + const d = parseInt(moment(f,'DD').tz('America/La_Paz').format('DD')) -1; + + total[d]+=parseInt(pItem.dataValues.suma); + if(pItem.dataValues.relacionado === true){ + + relacionado[d]= parseInt(pItem.dataValues.suma); + } else { + noRel[d]= parseInt(pItem.dataValues.suma); + } + if( pIndice == pLog.length-1 ) return; + }); + + }) + .then(() => { + + res.status(200).send(util.formatearMensaje('EXITO', 'Obtencion de datos exitoso', { nombres, global:total,relacionado,no_relacionado:noRel, total:dm})); + + }) + .catch(pError => { + console.log("Error en la busqueda", pError); + res.status(412).send(util.formatearMensaje('ERROR', pError)); + }); + }); + + /** + @apiVersion 2.0.0 + @apiGroup Monitoreo + @apiName Get monitoreo/usuario/ + @api {get} /api/v1/monitoreo/usuario/?anio=&mes= Obtiene datos de los usuario por mes y año + + @apiDescription Get monitoreo/usuario/, obtiene datos de los usuario por mes y año. + + @apiParam (Petición) {Texto} anio Gestión de la que se requiere el gráfico + @apiParam (Petición) {Texto} mes Mes de la que se requiere el gráfico + + @apiSuccess (Respuesta) {Array} global Conjunto de puntos a graficar + @apiSuccess (Respuesta) {Array} relacionado Conjunto de puntos a graficar + @apiSuccess (Respuesta) {Array} no_relacionado Conjunto de puntos a graficar + @apiSuccess (Respuesta) {Array} nombres Conjunto de nombres a usarse en el gráfico + @apiSuccess (Respuesta) {Numérico} total Cantidad de puntos para la gráfica + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Obtencion de datos exitoso", + "datos": { + "global": ["21", "5", ...], + "relacionado": ["20", "4", ...], + "no_relacionado": [1, 1, ...], + "nombres": ["jperez", "jarco", ...], + "total": 5 + } + } + */ + + app.get('/api/v1/monitoreo/usuario/', (req,res) => { + const dm = moment(`${req.query.anio}-${req.query.mes}`,'YYYY-MM').daysInMonth(), + inicio = moment(`${req.query.anio}-${req.query.mes}-1`, 'YYYY-MM').tz('America/La_Paz').format('YYYY-MM-DD'), + final = moment(inicio).tz('America/La_Paz').add(dm-1,'days').format('YYYY-MM-DD'), + page = (req.query.page-1)*20 || 0; + + const + res1 = [], + res2 = [], + res3 = [], + arr = [], + ids_usuarios = [], + v = {}; + let + tot, + opcionesMonitor = { + attributes: ['fid_usuario', [sequelize.fn('SUM', sequelize.col('contador')), 'suma'] ], + where:{ + fecha_visita:{ + [Op.between]:[`${inicio}T04:00:00.000Z`,`${final}T04:00:00.000Z`], + }, + }, + group: ['fid_usuario'], + order:[['suma','DESC']], + limit: 20, + offset: page, + }; + if(req.query.relacion) opcionesMonitor.where.relacionado=req.query.relacion; + monitor.findAndCountAll(opcionesMonitor) + .then( pResp => { + tot = pResp.count.length; + pResp.rows.forEach( it => { + res1.push(it.dataValues.suma); + res2.push(0);res3.push(it.dataValues.suma); + v[it.fid_usuario] = res1.length-1; + ids_usuarios.push(it.fid_usuario); + arr.push(new Promise((resolve, reject) => + usuario.findByPk(it.fid_usuario).then( r => resolve(r.usuario)) + )); + }); + opcionesMonitor = { + attributes: ['fid_usuario', [sequelize.fn('SUM', sequelize.col('contador')), 'suma'] ], + where:{ + fecha_visita:{ + [Op.between]:[`${inicio}T04:00:00.000Z`,`${final}T04:00:00.000Z`], + }, + fid_usuario: { [Op.in]: ids_usuarios }, + relacionado: true, + }, + group: ['fid_usuario'], + }; + return monitor.findAll(opcionesMonitor); + }) + .then( pResp => { + pResp.forEach( it => { + v.i = v[it.fid_usuario]; + res2[v.i]=it.dataValues.suma; + res3[v.i]=parseInt(res3[v.i])-parseInt(res2[v.i]); + }); + return Promise.all(arr); + }) + .then( pResp => { + res.status(200).send(util.formatearMensaje('EXITO', 'Obtencion de datos exitoso', { global: res1, relacionado: res2, no_relacionado: res3, nombres: pResp, total: tot})); + }) + .catch(pError => { + console.log("Error en la busqueda", pError); + res.status(412).send(util.formatearMensaje('ERROR', pError)); + }); + }); + + /** + @apiVersion 2.0.0 + @apiGroup Monitoreo + @apiName Get monitoreo/documento/ + @api {get} /api/v1/monitoreo/documento/?anio=&mes= Obtiene datos de los documentos por mes y año + + @apiDescription Get monitoreo/documento/, obtiene datos de los documentos por mes y año. + + @apiParam (Petición) {Texto} anio Gestión de la que se requiere el gráfico + @apiParam (Petición) {Texto} mes Mes de la que se requiere el gráfico + + @apiSuccess (Respuesta) {Array} global Conjunto de puntos a graficar + @apiSuccess (Respuesta) {Array} relacionado Conjunto de puntos a graficar + @apiSuccess (Respuesta) {Array} no_relacionado Conjunto de puntos a graficar + @apiSuccess (Respuesta) {Array} nombres Conjunto de nombres a usarse en el gráfico + @apiSuccess (Respuesta) {Numérico} total Cantidad de puntos para la gráfica + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Obtencion de datos exitoso", + "datos": { + "global": ["21", "5", ...], + "relacionado": ["20", "4", ...], + "no_relacionado": [1, 1, ...], + "nombres": ["jperez", "jarco", ...], + "total": 5 + } + } + */ + + app.get('/api/v1/monitoreo/documento/', (req,res) => { + console.log("Iniciando la nueva busqueda", req.query); + const dm=moment(`${req.query.anio}-${req.query.mes}`,'YYYY-MM').daysInMonth(), + inicio = moment(`${req.query.anio}-${req.query.mes}-1`, 'YYYY-MM').tz('America/La_Paz').format('YYYY-MM-DD'), + final = moment(inicio).tz('America/La_Paz').add(dm-1,'days').format('YYYY-MM-DD'), + page = (req.query.page-1)*20 || 0; + console.log("Revisando la fecha inicio",inicio ); + console.log("Revisando la fecha final", final); + + const + res1 = [], + res2 = [], + res3 = [], + arr = [], + ids_usuarios = [], + v = {}; + let + tot, + opcionesMonitor = { + attributes: ['fid_documento', [sequelize.fn('SUM', sequelize.col('contador')), 'suma'] ], + where:{ + fecha_visita:{ + [Op.between]:[`${inicio}T04:00:00.000Z`,`${final}T04:00:00.000Z`], + }, + }, + group: ['fid_documento'], + order:[['suma','DESC']], + limit: 20, + offset: page, + }; + monitor.findAndCountAll(opcionesMonitor) + .then( pResp => { + tot = pResp.count.length; + pResp.rows.forEach( it => { + res1.push(it.dataValues.suma); + res2.push(0);res3.push(it.dataValues.suma); + v[it.fid_documento] = res1.length-1; + ids_usuarios.push(it.fid_documento); + arr.push(new Promise((resolve, reject) => + documento.findByPk(it.fid_documento).then( r => resolve( r === null? 's/n': r.nombre)) + )); + }); + opcionesMonitor = { + attributes: ['fid_documento', [sequelize.fn('SUM', sequelize.col('contador')), 'suma'] ], + where:{ + fecha_visita:{ + [Op.between]:[`${inicio}T04:00:00.000Z`,`${final}T04:00:00.000Z`], + }, + fid_documento: { $in: ids_usuarios }, + relacionado: true, + }, + group: ['fid_documento'], + }; + return monitor.findAll(opcionesMonitor); + }) + .then( pResp => { + pResp.forEach( it => { + v.i = v[it.fid_documento]; + res2[v.i]=it.dataValues.suma; + res3[v.i]=parseInt(res3[v.i])-parseInt(res2[v.i]); + }); + return Promise.all(arr); + }) + .then( pResp => { + res.status(200).send(util.formatearMensaje('EXITO', 'Obtencion de datos exitoso', { global: res1, relacionado: res2, no_relacionado: res3, nombres: pResp, total: tot})); + }) + .catch(pError => { + console.log("Error en la busqueda", pError); + res.status(412).send(util.formatearMensaje('ERROR', pError)); + }); + }); + + /** + @apiVersion 2.0.0 + @apiGroup Monitoreo + @apiName Get monitoreo/:id/documento + @api {get} /api/v1/monitoreo/:id/documento?anio=&mes= Obtiene datos de documentos relacionados a un usuario + + @apiDescription Get monitoreo/:id/documento, obtiene informacion de documentos con CITE relacionados o no a un usuario en especifico. + + @apiParam (Parámetro) {Numérico} id Identificador del usuario + + @apiSuccess (Respuesta) {Array} global Conjunto de puntos a graficar + @apiSuccess (Respuesta) {Array} relacionado Conjunto de puntos relacionados a graficar + @apiSuccess (Respuesta) {Array} no_relacionado Conjunto de puntos no relacionados a graficar + @apiSuccess (Respuesta) {Array} nombres Conjunto de nombres a usarse en el gráfico + @apiSuccess (Respuesta) {Numérico} total Cantidad de puntos para la gráfica + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Obtencion de datos exitoso", + "datos": { + "global": ["21", "5", ...], + "relacionado": ["20", "4", ...], + "no_relacionado": [1, 1, ...], + "nombres": ["jperez", "jarco", ...], + "total": 5 + } + } + */ + + // app.get('/:id/documento', (req,res) => { + app.get('/api/v1/monitoreo/:id/documento', (req,res) => { + + const + resultado = [], + arr = [], + nombres = [], + total = [], + relacionado = [], + sinRel = [], + page = (req.query.page-1)*20 || 0; + // page = (req.query.page-1)*5 || 0; + let + tot, + c = 0; + + const opcionesMonitor = { + attributes: ['fid_documento', 'relacionado',[sequelize.fn('SUM', sequelize.col('contador')), 'suma'] ], + where:{ + fid_usuario:req.params.id, + cite:true, + }, + group: ['fid_documento', 'relacionado'], + order : [['suma','DESC']], + limit : 5, + offset : page, + }; + + if(req.query.relacion) opcionesMonitor.where.relacionado=req.query.relacion; + + monitor.findAndCountAll(opcionesMonitor) + .then( pLog => { + c = pLog.count.length; + pLog.rows.forEach( (it, i) => { + console.log("revisando los registros obtenidos", it.dataValues); + resultado.push(it.dataValues.suma); + arr.push(new Promise((resolve, reject) => { + + documento.findOne({ + where:{ + id_documento:it.fid_documento, + nombre:{[Op.like]: `${config.sistema.cite_principal}%/%/%` }, + }, + }) + .then( r => { + + if(r){ + const val = parseInt(it.dataValues.suma); + total.push(val) + nombres.push(r.nombre || 'sin nombre'); + if(it.relacionado==true){ + relacionado.push(val); + sinRel.push(0) + } + else { + sinRel.push(val); + relacionado.push(0) + } + } + else resultado.splice(i,1); + resolve('_'); + } + ) + })) + }) + return Promise.all(arr) + }) + .then( pResp => { + + res.status(200).send(util.formatearMensaje('EXITO', 'Obtencion de datos exitoso', { global:total,relacionado,no_relacionado:sinRel,nombres, total:c })) + }) + .catch(pError => { + console.log("Error en la busqueda", pError); + res.status(412).send(util.formatearMensaje('ERROR', pError)); + }) + }); + +/** + @apiVersion 2.0.0 + @apiGroup Monitoreo + @apiName Get monitor/:id + @api {get} /api/v1/monitoreo/monitor/:id Obtiene un/a monitor + + @apiDescription Get monitor, obtiene un/a monitor + + @apiParam (Parámetro) {Numérico} id Identificador de monitor que se quiere obtener + + @apiSuccess (Respuesta) {Numérico} id_monitor Identificador de monitor + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario modificador + @apiSuccess (Respuesta) {FechaHora} _fecha_creacion Fecha de creación de monitor + @apiSuccess (Respuesta) {FechaHora} _fecha_modificacion Fecha de modificación de monitor + @apiSuccess (Respuesta) {Numérico} fid_usuario Identificador del usuario + @apiSuccess (Respuesta) {Numérico} fid_documento Identificador del documento + @apiSuccess (Respuesta) {Texto} fecha_visita Fecha de la acción + @apiSuccess (Respuesta) {Texto} ip Identificador de la IP desde la cual se realizó la acción + @apiSuccess (Respuesta) {Texto} mac Identificador de la MAC desde la cual se realizó la acción + @apiSuccess (Respuesta) {Numérico} contador Cantidad de veces que se haya visto + @apiSuccess (Respuesta) {Boolean} relacionado Si el documento está o no relacionado con el usuario + @apiSuccess (Respuesta) {Boolean} cite Si el documento ya cuenta o no con cite. + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "id_monitor": "1", + "fid_usuario": 10, + "fid_documento": 78, + "fecha_visita": "2017-04-26T04:00:00.000Z", + "ip": "[\"1\"]", + "mac": null, + "contador": 3, + "relacionado": true, + "cite": true, + "_usuario_creacion": "1", + "_usuario_modificacion": "1", + "_fecha_creacion": " << fecha y hora >> ", + "_fecha_modificacion": " << fecha y hora >> " + } + + } +*/ + app.get('/api/v1/monitoreo/monitor/:id', sequelizeHandlers.get(monitor)); + +/** + @apiVersion 2.0.0 + @apiGroup Monitoreo + @apiName Get monitor + @api {get} /api/v1/monitoreo/monitor/ Obtiene la lista completa de monitor + + @apiDescription Get monitor + + @apiSuccess (Respuesta) {Numérico} id_monitor Identificador de monitor + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario modificador + @apiSuccess (Respuesta) {FechaHora} _fecha_creacion Fecha de creación de monitor + @apiSuccess (Respuesta) {FechaHora} _fecha_modificacion Fecha de modificación de monitor + @apiSuccess (Respuesta) {Numérico} fid_usuario Identificador del usuario + @apiSuccess (Respuesta) {Numérico} fid_documento Identificador del documento + @apiSuccess (Respuesta) {Texto} fecha_visita Fecha de la acción + @apiSuccess (Respuesta) {Texto} ip Identificador de la IP desde la cual se realizó la acción + @apiSuccess (Respuesta) {Texto} mac Identificador de la MAC desde la cual se realizó la acción + @apiSuccess (Respuesta) {Numérico} contador Cantidad de veces que se haya visto + @apiSuccess (Respuesta) {Boolean} relacionado Si el documento está o no relacionado con el usuario + @apiSuccess (Respuesta) {Boolean} cite Si el documento ya cuenta o no con cite. + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "total": 21, + "resultado":[ + { + "id_monitor": "1", + "fid_usuario": 10, + "fid_documento": 78, + "fecha_visita": "2017-04-26T04:00:00.000Z", + "ip": "[\"1\"]", + "mac": null, + "contador": 3, + "relacionado": true, + "cite": true, + "_usuario_creacion": "1", + "_usuario_modificacion": "1", + "_fecha_creacion": " << fecha y hora >> ", + "_fecha_modificacion": " << fecha y hora >> " + }, + { + "id_monitor": "2", + "fid_usuario": 20, + "fid_documento": 87, + "fecha_visita": "2017-04-26T04:00:00.000Z", + "ip": "[\"1\"]", + "mac": null, + "contador": 4, + "relacionado": true, + "cite": true, + "_usuario_creacion": "2", + "_usuario_modificacion": "2", + "_fecha_creacion": " << fecha y hora >> ", + "_fecha_modificacion": " << fecha y hora >> " + }, + ... + ] + + } + +*/ + +/** + @apiVersion 2.0.0 + @apiGroup Monitoreo + @apiName Get monitor/?order=&limit=&page=&filter= + @api {get} /api/v1/monitoreo/monitor/?order=&limit=&page=&filter= Obtiene la lista paginada de monitor + + @apiDescription Get monitor + + @apiParam (Query) {Texto} order Campo por el cual se ordenará el parcial + @apiParam (Query) {Numérico} limit Cantidad de resultados a obtener + @apiParam (Query) {Numérico} page Número de página de resultados + @apiParam (Query) {Texto} filter Texto a buscar en los registros + + @apiSuccess (Respuesta) {Texto} tipoMensaje Tipo del mensaje de respuesta. + @apiSuccess (Respuesta) {Texto} mensaje Mensaje de respuesta. + @apiSuccess (Respuesta) {Objeto} datos Objeto de con los datos de respuesta + @apiSuccess (Respuesta) {Numérico} total Numero de objetos monitor + @apiSuccess (Respuesta) {Array} resultado Array de objetos moonitor + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "total": 21, + "resultado":[ + { + "id_monitor": "1", + "fid_usuario": 10, + "fid_documento": 78, + "fecha_visita": "2017-04-26T04:00:00.000Z", + "ip": "[\"1\"]", + "mac": null, + "contador": 3, + "relacionado": true, + "cite": true, + "_usuario_creacion": "1", + "_usuario_modificacion": "1", + "_fecha_creacion": " << fecha y hora >> ", + "_fecha_modificacion": " << fecha y hora >> " + }, + { + "id_monitor": "2", + "fid_usuario": 20, + "fid_documento": 87, + "fecha_visita": "2017-04-26T04:00:00.000Z", + "ip": "[\"1\"]", + "mac": null, + "contador": 4, + "relacionado": true, + "cite": true, + "_usuario_creacion": "2", + "_usuario_modificacion": "2", + "_fecha_creacion": " << fecha y hora >> ", + "_fecha_modificacion": " << fecha y hora >> " + }, + ... + ] + } + +*/ + app.get('/api/v1/monitoreo/monitor', sequelizeHandlers.query(monitor)); + + +/** + @apiVersion 1.0.0 + @apiGroup Monitoreo + @apiName Options monitor + @api {options} /api/v1/monitoreo/monitor Extrae formly de monitor + + @apiDescription Options de monitor + + @apiSuccess (Respuesta) {Texto} key Llave para el campo + @apiSuccess (Respuesta) {Texto} type Tipo de etiqueta este puede ser input, select, datepicker, etc + @apiSuccess (Respuesta) {Objeto} templateOptions Objeto de opciones para la etiqueta, el cual varia de acuerdo el tipo de etiqueta + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + [ + { + "key": "id_monitor", + "type": "input", + "templateOptions": { + "type": "number", + "label": "Id monitor", + "required": true + }, + }, + { + "key": "campo", + "type": "input", + "templateOptions": { + "type": "text", + "label": "Campo", + "required": true + } + } + ] + + @apiSampleRequest off +*/ + app.options('/api/v1/monitoreo/monitor', sequelizeFormly.formly(monitor, app.src.db.models)); +}; diff --git a/src/routes/monitoreo/pendientesRT.js b/src/routes/monitoreo/pendientesRT.js new file mode 100644 index 0000000..068f542 --- /dev/null +++ b/src/routes/monitoreo/pendientesRT.js @@ -0,0 +1,81 @@ + + +module.exports = app => { + const partida = app.src.db.models.partida; + const documento = app.src.db.models.documento; + const util = require('../../lib/util'); + const moment = require('moment'); + //const sequelize = require('sequelize'); + const Promise = require('bluebird'); + + const config = app.src.config.config; + const sequelize = app.src.db.sequelize; + +/** + @apiVersion 1.0.0 + @apiGroup Monitoreo + @apiName Get pendientes + @api {get} /api/v1/monitoreo/pendientes Obtiene los documentos pendientes por usuario + + @apiDescription Get pendientes + + @apiSuccess (Respuesta) {Texto} via_actual Usuario + @apiSuccess (Respuesta) {Texto} nombres Nombres del usuario + @apiSuccess (Respuesta) {Texto} apellidos Apellios del usuario + @apiSuccess (Respuesta) {Texto} ENVIADO Total enviados + @apiSuccess (Respuesta) {Texto} RECHAZADO Total rechazados + @apiSuccess (Respuesta) {Texto} DERIVADO Total derivados + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Obtención de datos exitosa.", + "datos": [ + { + "_usuario_creacion": 3, + "nombres": "Oso", + "apellidos": "Pardo", + "ENVIADO": null, + "RECHAZADO": null, + "DERIVADO": null + }, + { + "_usuario_creacion": 9, + "nombres": "León", + "apellidos": "Africano", + "ENVIADO": null, + "RECHAZADO": null, + "DERIVADO": null + } + ... + ] + } + +*/ + + app.get('/api/v1/monitoreo/pendientes', (req, res) => { + + var qry = "select * from crosstab($$ " + + "select d.via_actual, u.nombres , u.apellidos, d.estado, count(d.estado) from documento d, usuario u " + + "where d.estado in ('ENVIADO','RECHAZADO','DERIVADO') and u.id_usuario = d.via_actual and u.estado= 'ACTIVO' " + + "group by d.via_actual, d.estado, u.nombres , u.apellidos " + + "order by u.nombres , u.apellidos $$ " + + ", $$VALUES ('ENVIADO'::text), ('RECHAZADO'::text), ('DERIVADO'::text) $$) " + + 'as pendientes("via_actual" int, "nombres" text, "apellidos" text, "ENVIADO" int, "RECHAZADO" int, "DERIVADO" int) '; + + sequelize.query(qry) + .then(resultado => { + if (resultado) { + res.status(200).send(util.formatearMensaje("EXITO", "Obtención de datos exitosa.", resultado)); + } else{ + res.status(200).send(util.formatearMensaje("INFORMACION", "No existen resultados.")); + } + }) + .catch(pError => { + res.status(412).send(util.formatearMensaje('ERROR', pError)); + }); + }); + + function toFloat(string) { return parseFloat(parseFloat(string).toFixed(2)); } +}; diff --git a/src/routes/notificacion/conf_notificacionRT.js b/src/routes/notificacion/conf_notificacionRT.js new file mode 100644 index 0000000..125c183 --- /dev/null +++ b/src/routes/notificacion/conf_notificacionRT.js @@ -0,0 +1,202 @@ +const {ModelHandler} = require("sequelize-handlers"); +const sequelizeFormly = require("sequelize-formly"); + +module.exports = app => { + const conf_notificacion = app.src.db.models.conf_notificacion; + const sequelizeHandlers = new ModelHandler(conf_notificacion); + +/** + @apiVersion 1.0.0 + @apiGroup Notificación + @apiName Get conf_notificacion + @api {get} /api/v1/notificacion/conf_notificacion/ Obtiene la lista completa de conf_notificacion + + @apiDescription Get conf_notificacion + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "total": 21, + "resultado":[ + { + "id_conf_notificacion": "1", + "campo": "xxx", + "_usuario_creacion": "1", + "_fecha_creacion": " << fecha y hora >> ", + "_fecha_modificacion": " << fecha y hora >> " + }, + { + "id_conf_notificacion": "2", + "campo": "zzz", + "_usuario_creacion": "1", + "_fecha_creacion": " << fecha y hora >> ", + "_fecha_modificacion": " << fecha y hora >> " + }, + ... + ] + + } + +*/ + +/** + @apiVersion 1.0.0 + @apiGroup Notificación + @apiName Get configuración_notificacion + @api {get} /api/v1/notificacion/conf_notificacion/?order=&limit=&page=&filter= Obtiene la lista paginada de conf_notificacion + + @apiDescription Get conf_notificacion + + @apiParam (Query) {Texto} order Campo por el cual se ordenará el resultado + @apiParam (Query) {Numérico} limit Cantidad de resultados a obtener + @apiParam (Query) {Numérico} page Número de página de resultados + @apiParam (Query) {Texto} filter Texto a buscar en los registros + + @apiSuccess (Respuesta) {Texto} tipoMensaje Tipo del mensaje de respuesta. + @apiSuccess (Respuesta) {Texto} mensaje Mensaje de respuesta. + @apiSuccess (Respuesta) {Objeto} datos Objeto de con los datos de respuesta + @apiSuccess (Respuesta) {Numérico} total Numero de objetos categoria + @apiSuccess (Respuesta) {Array} resultado Array de objetos categoria + + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "total": 21, + "resultado":[ + { + "id_conf_notificacion": 1, + "codigo": "CI", + "descripcion": "Carnet de identidad", + "estado": "ACTIVO", + "_usuario_creacion": 5, + "_usuario_modificacion": null, + "_fecha_creacion": "2016-08-29T13:59:22.788Z", + "_fecha_modificacion": "2016-08-29T13:59:22.788Z" + }, + { + "id_conf_notificacion": 2, + "codigo": "PAS", + "descripcion": "Pasaporte", + "estado": "ACTIVO", + "_usuario_creacion": 5, + "_usuario_modificacion": null, + "_fecha_creacion": "2016-08-29T14:02:19.060Z", + "_fecha_modificacion": "2016-08-29T14:02:19.060Z" + }, + ... + ] + } + +*/ + app.get('/api/v1/notificacion/conf_notificacion', sequelizeHandlers.query(conf_notificacion)); + +/** + @apiVersion 1.0.0 + @apiGroup Notificación + @apiName Put actualiza + @api {put} /api/v1/notificacion/conf_notificacion/:id Actualiza un/a configuración de notificación + + @apiDescription Put actualiza + + @apiParam (Parámetro) {Numérico} id Identificador de conf_notificacion que se quiere actualizar + + @apiParam (Petición) {Texto} campo Decripción del campo + + @apiParamExample {json} Ejemplo para enviar: + { + "id_conf_notificacion": 65, + "canal": "CORREO", + "enviado": false, + "celular": null, + "observado": true, + "aprobado": true, + "derivado": false, + "email": "mi@correo.dominio" + } + + @apiSuccess (Respuesta) {Numérico} id_conf_notificacion Identificador de conf_notificacion + @apiSuccess (Respuesta) {Numérico} fid_usuario Identificador del usuario + @apiSuccess (Respuesta) {Texto} canal Dato respecto a los canales de notificación elegidos por el usuario + @apiSuccess (Respuesta) {Texto} celular Dato respecto al número de celular al cual se le notificara + @apiSuccess (Respuesta) {Texto} email Dato respecto al correo al cual se le notificara + @apiSuccess (Respuesta) {Boolean} enviado Si el usuario requiere notificación cuando se envia un documento para aprobación + @apiSuccess (Respuesta) {Boolean} derivado Si el usuario requiere notificación cuando se le deriva un documento + @apiSuccess (Respuesta) {Boolean} observado Si el usuario requiere notificación cuando se le observa/rechaza un documento + @apiSuccess (Respuesta) {Boolean} aprobado Si el usuario requiere notificación cuando se le aprueba un documento + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Usuario que crea la configuración de notificación + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Usuario que modifica la configuración de notificación + @apiSuccess (Respuesta) {FechaHora} _fecha_creacion Fecha de creacion de conf_notificacion + @apiSuccess (Respuesta) {FechaHora} _fecha_modificacion Fecha de modificacion de conf_notificacion + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK +{ + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "id_conf_notificacion": 65, + "fid_usuario": 70, + "celular": "77788899", + "canal": "SMS_CORREO", + "enviado": false, + "observado": true, + "aprobado": true, + "derivado": false, + "estado": "ACTIVO", + "_usuario_creacion": 1, + "_usuario_modificacion": null, + "_fecha_creacion": "2017-01-27T14:15:40.000Z", + "_fecha_modificacion": "2020-01-15T12:50:36.579Z" + } +} + + @apiSampleRequest off +*/ + app.put('/api/v1/notificacion/conf_notificacion/:id', sequelizeHandlers.update(conf_notificacion)); + +/** + @apiVersion 1.0.0 + @apiGroup Notificación + @apiName Options conf_notificacion + @api {options} /api/v1/notificacion/conf_notificacion Extrae formly de conf_notificacion + + @apiDescription Options de conf_notificacion + + @apiSuccess (Respuesta) {Texto} key Llave para el campo + @apiSuccess (Respuesta) {Texto} type Tipo de etiqueta este puede ser input, select, datepicker, etc + @apiSuccess (Respuesta) {Objeto} templateOptions Objeto de opciones para la etiqueta, el cual varia de acuerdo el tipo de etiqueta + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + [ + { + "key": "id_conf_notificacion", + "type": "input", + "templateOptions": { + "type": "number", + "label": "Id conf_notificacion", + "required": true + }, + }, + { + "key": "campo", + "type": "input", + "templateOptions": { + "type": "text", + "label": "Campo", + "required": true + } + } + ] + + @apiSampleRequest off +*/ + app.options('/api/v1/notificacion/conf_notificacion', sequelizeFormly.formly(conf_notificacion, app.src.db.models)); +}; diff --git a/src/routes/notificacion/notificacionRT.js b/src/routes/notificacion/notificacionRT.js new file mode 100644 index 0000000..2ea4580 --- /dev/null +++ b/src/routes/notificacion/notificacionRT.js @@ -0,0 +1,4 @@ +module.exports = app => { + const notificacion = app.src.db.models.notificacion; + +}; diff --git a/src/routes/plantillasFormly/catalogoRT.js b/src/routes/plantillasFormly/catalogoRT.js new file mode 100644 index 0000000..fc3e066 --- /dev/null +++ b/src/routes/plantillasFormly/catalogoRT.js @@ -0,0 +1,224 @@ +const options = require('sequelize-formly'); + +module.exports = app => { + const modelos = app.src.db.models; + const Catalogo = modelos.catalogo; + const CatalogoUsuarios = modelos.catalogo_usuario; + const CatalogoDocumentos = modelos.catalogo_documento; + const util = app.src.lib.util; + const sequelize = app.src.db.sequelize; + const Op = app.src.db.Sequelize.Op; + + const bl = require('../../bl/plantillasFormly/catalogoBL'); + + + const filtros = (req, res, next) => { + if (req.query.filter != '' && req.query.filter !== undefined) util.consulta(req, res, next, Catalogo); + else next(); + } + + app.post('/api/v1/plantillasFormly/catalogo', (req, res) => { + req.body._usuario_creacion= req.body.audit_usuario.id_usuario; + const datosCatalogo = JSON.parse(JSON.stringify(req.body)); + const datosUsuarios = datosCatalogo.usuarios || []; + const datosDocumentos = datosCatalogo.documentos || []; + const usuarios = []; + const documentos = []; + delete datosCatalogo.usuarios; + delete datosCatalogo.documentos; + + let catalogo = null; + sequelize.transaction().then(t => { + const tr = { transaction: t }; + + return Catalogo.create(datosCatalogo, tr) + .then(resp => { + catalogo = resp.dataValues; + catalogo.audit_usuario = req.body.audit_usuario; + datosUsuarios.map(item => { + item.fid_catalogo = catalogo.id_catalogo; + item.fid_usuario = item.id_usuario; + item._usuario_creacion = req.body.audit_usuario.id_usuario; + usuarios.push(item.id_usuario); + }); + return CatalogoUsuarios.bulkCreate(datosUsuarios, tr) + }) + .then(respUsuarios => { + const promesas = datosDocumentos.map(item => { + item.fid_catalogo = catalogo.id_catalogo; + item.fid_documento = item.id_documento; + item._usuario_creacion = req.body.audit_usuario.id_usuario + return bl.crearCatalogoDocumento(modelos, item, catalogo, tr) + }); + return Promise.all(promesas) + .then(() => Promise.resolve()) + .catch((error) => Promise.resolve()); + }) + .then(() => { + t.commit(); + res.send(util.formatearMensaje("EXITO", 'Creacion exitosa', { id_catalogo:catalogo.id_catalogo })); + }) + .catch(error => { + t.rollback(); + res.status(412).send(util.formatearMensaje('ERROR', error)); + }); + }); + }); + + app.put('/api/v1/plantillasFormly/catalogo/:id', (req, res) => { + const catalogo = JSON.parse(JSON.stringify(req.body)); + const documentos = catalogo.documentos; + const usuarios = catalogo.usuarios; + delete catalogo.documentos; + delete catalogo.usuarios; + sequelize.transaction().then(t => { + const tr = { transaction: t }; + return Catalogo.findOne({ + where: { + _usuario_creacion: req.body.audit_usuario.id_usuario, + id_catalogo: req.params.id, + }, + }, tr) + .then(respCatalogo => { + if (!respCatalogo) throw Error ('El catalogo a modificar no se encuentra disponible'); + return bl.crearActualizarDocumentos(modelos, documentos, catalogo, tr); + }) + .then(() => bl.crearActualizarUsuarios(modelos, usuarios, catalogo, tr)) + .then(() => { + t.commit(); + res.send(util.formatearMensaje("EXITO", 'Actualización exitosa')); + }) + .catch(error => { + t.rollback(); + res.status(412).send(util.formatearMensaje('ERROR', error)); + }); + }); + }); + + app.get('/api/v1/plantillasFormly/catalogo/:id', (req, res) => { + const datosResp = { + documentos: [], + usuarios: [], + } + const opcionesCatalogo = { + where: { + id_catalogo: req.params.id, + estado: { [Op.ne]: 'ELIMINADO' }, + }, + include: [ + { + model: CatalogoUsuarios, + as: 'catalogo_usuario', + }, + { + model: modelos.catalogo_documento, + as: 'catalogo_documento', + }, + ], + }; + if (req.query.filter && (req.query.filter === 'true' || req.query.filter === true)) { + opcionesCatalogo.include[0].where = {estado: 'ACTIVO'}; + opcionesCatalogo.include[1].where = {estado: 'ACTIVO'}; + } + + return Catalogo.findOne(opcionesCatalogo) + .then(respCatalogo => { + if (!respCatalogo) throw Error('El catalogo solicitado no se encuentra disponible.'); + datosResp.id_catalogo = respCatalogo.id_catalogo; + datosResp.nombre = respCatalogo.nombre; + datosResp.descripcion = respCatalogo.descripcion; + datosResp.estado = respCatalogo.estado; + datosResp._usuario_creacion = respCatalogo._usuario_creacion; + datosResp.catalogo_documento = respCatalogo.catalogo_documento || []; + datosResp.catalogo_usuario = respCatalogo.catalogo_usuario || []; + + if (req.query.filter && (req.query.filter === 'true' || req.query.filter === true)) { + const usuarios = datosResp.catalogo_usuario; + let usuarioValido = false; + for (let i = 0; i < usuarios.length; i++) { + if (usuarios[i].fid_usuario == req.body.audit_usuario.id_usuario) { + usuarioValido = true; + } + } + if (usuarioValido == false) throw Error('Usted no se encuentra autorizado'); + } + else { + if (datosResp._usuario_creacion !== req.body.audit_usuario.id_usuario) { + throw Error('Usted no cuenta con la autorizacion para ver este catalogo'); + } + } + }) + .then(() => bl.obtenerInfoDocumentos(modelos, datosResp.catalogo_documento)) + .then(respDocumentos => { + datosResp.documentos = respDocumentos; + return bl.obtenerInfoUsuarios(modelos, datosResp.catalogo_usuario); + }) + .then(respUsuarios => { + datosResp.usuarios = respUsuarios; + delete datosResp.catalogo_usuario; + delete datosResp.catalogo_documento; + res.send(util.formatearMensaje("EXITO", 'Obtención de catalogo exitosa.', datosResp)); + }) + .catch(error => res.status(412).send(util.formatearMensaje('ERROR', error))); + }); + + app.get('/api/v1/plantillasFormly/catalogo/:id/miscatalogos', filtros, (req,res) => { + const opcionesCatalogo = { + where: { + _usuario_creacion: req.body.audit_usuario.id_usuario, + }, + }; + if (req.query.fields) { + opcionesCatalogo.attributes = req.query.fields.split(','); + opcionesCatalogo.attributes.push('_usuario_creacion'); + } + if (req.query.filter !== '' && req.xfilter) { + opcionesCatalogo.where[Op.or] = req.xfilter; + } + return Catalogo.findAll(opcionesCatalogo) + .then(respCatalogos => res.send(util.formatearMensaje("EXITO", 'Obtención de catalogos exitosa.', { + total: respCatalogos.length, + resultado: respCatalogos, + }))) + .catch(error => res.status(412).send(util.formatearMensaje('ERROR', error))); + }); + + app.get('/api/v1/plantillasFormly/catalogo/:id/compartidos', filtros, (req,res) => { + const opcionesCatUsuario = { + where: { + fid_usuario: req.body.audit_usuario.id_usuario, + estado: 'ACTIVO', + }, + } + const opcionesCatalogo = { + where: { + estado: 'ACTIVO', + }, + }; + const catalogos = []; + return CatalogoUsuarios.findAll(opcionesCatUsuario) + .then(respCatUsu => { + respCatUsu.map(item => { + if(catalogos.indexOf(item.dataValues.fid_catalogo) == -1) catalogos.push(item.dataValues.fid_catalogo); + }); + }) + .then(() => { + opcionesCatalogo.where.id_catalogo = {[Op.in]: catalogos}; + if (req.query.filter !== '' && req.xfilter) { + opcionesCatalogo.where[Op.or] = req.xfilter; + } + return Catalogo.findAll(opcionesCatalogo); + }) + .then(respCatalogos => { + res.send(util.formatearMensaje("EXITO", 'Obtención de catalogos exitosa.', { + total: respCatalogos.length, + resultado: respCatalogos, + })); + }) + .catch(error => res.status(412).send(util.formatearMensaje('ERROR', error))); + }); + + app.route('/api/v1/plantillasFormly/catalogo').options(options.formly(Catalogo, modelos)); + app.route('/api/v1/plantillasFormly/catalogo/:id/miscatalogos').options(options.formly(Catalogo, modelos)); + app.route('/api/v1/plantillasFormly/catalogo/:id/compartidos').options(options.formly(Catalogo, modelos)); +}; \ No newline at end of file diff --git a/src/routes/plantillasFormly/catalogo_documentoRT.js b/src/routes/plantillasFormly/catalogo_documentoRT.js new file mode 100644 index 0000000..27b223e --- /dev/null +++ b/src/routes/plantillasFormly/catalogo_documentoRT.js @@ -0,0 +1,53 @@ +module.exports = app => { + const modelos = app.src.db.models; + const CatalogoDocumento = modelos.catalogo_documento; + const Documento = modelos.documento; + const util = app.src.lib.util; + const Op = app.src.db.Sequelize.Op; + const bl = require('../../bl/plantillasFormly/catalogoBL'); + + + app.put('/api/v1/plantillasFormly/catalogo/documento/:id', (req, res) => { + return CatalogoDocumento.findOne({ + where: { + id_catalogo_documento: req.params.id, + fid_catalogo: req.body.fid_catalogo, + }, + }) + .then(resp => { + if (!resp) throw Error('No existe el recurso solicitado.'); + if (resp._usuario_creacion !== req.body.audit_usuario.id_usuario) throw Error('Usted no esta autorizado para realizar la modificación.'); + return resp.update(req.body.actualizar); + }) + .then(() => res.send(util.formatearMensaje("EXITO", 'Modificación exitosa'))) + .catch(error => res.status(412).send(util.formatearMensaje("ERROR", error))); + }); + + app.post('/api/v1/plantillasFormly/catalogo/documento', (req, res) => { + if (!req.body.cite) return res.status(412).send(util.formatearMensaje("ERROR", 'No existe parametro de busqueda')); + let documento = null; + return Documento.findOne({ + attributes: ['id_documento', 'nombre', '_usuario_creacion', '_usuario_modificacion', 'firmaron', 'via_actual', 'de', 'via', 'para', 'grupo'], + where: { + nombre: { + [Op.iLike]: req.body.cite, + }, + }, + }) + .then(respDocumento => { + if (!respDocumento) throw Error('El documento solicitado no esta disponible en estos momentos'); + documento = respDocumento; + return bl.validarRelacionDocumento(modelos, respDocumento, req.body.audit_usuario); + }) + .then(respValido => { + if (respValido == false ) throw Error('Usted no se encuentra autorizado para ver el documento solicitado.') + const datosResp = { + id_documento: documento.id_documento, + nombre: documento.nombre, + fecha: documento.fecha, + }; + return res.send(util.formatearMensaje("EXITO", 'Obtencion de documento exitosa.', datosResp)); + }) + .catch(error => res.status(412).send(util.formatearMensaje("ERROR", error))); + }); +} \ No newline at end of file diff --git a/src/routes/plantillasFormly/catalogo_usuarioRT.js b/src/routes/plantillasFormly/catalogo_usuarioRT.js new file mode 100644 index 0000000..6343b95 --- /dev/null +++ b/src/routes/plantillasFormly/catalogo_usuarioRT.js @@ -0,0 +1,32 @@ +module.exports = app => { + const modelos = app.src.db.models; + const CatalogoUsuario = modelos.catalogo_usuario; + const Usuario = modelos.Usuario; + const util = app.src.lib.util; + + + app.put('/api/v1/plantillasFormly/catalogo/usuario/:id', (req, res) => { + console.log('Iniciando con la modificacion de un catalogo_usuario', req.body); + + return CatalogoUsuario.findOne({ + where: { + id_catalogo_usuario: req.params.id, + fid_catalogo: req.body.fid_catalogo, + }, + }) + .then(resp => { + if (!resp) throw Error('No existe el recurso solicitado.'); + console.log('Revisando la resp', resp); + if (resp._usuario_creacion !== req.body.audit_usuario.id_usuario) throw Error('Usted no esta autorizado para realizar la modificación.'); + return resp.update(req.body.actualizar); + }) + .then(res.send(util.formatearMensaje("EXITO", 'Modificación exitosa'))) + .catch(error => { + console.log('Error en la modificacion de un catalogo_usuario'); + res.status(412).send(util.formatearMensaje("ERROR", error)); + }) + }); + + + +} \ No newline at end of file diff --git a/src/routes/plantillasFormly/contactoRT.js b/src/routes/plantillasFormly/contactoRT.js new file mode 100644 index 0000000..7fc29a3 --- /dev/null +++ b/src/routes/plantillasFormly/contactoRT.js @@ -0,0 +1,487 @@ + +const options = require('sequelize-formly'); +const {ModelHandler} = require('sequelize-handlers'); +module.exports = app => { + const modelos = app.src.db.models; + const util = app.src.lib.util; + const Op = app.src.db.Sequelize.Op; + const sequelizeHandlers = new ModelHandler(modelos.contacto); + + /** + @apiVersion 2.0.0 + @apiGroup Contactos + @apiName Get plantillasFormly/contactos + @api {get} /api/v1/plantillasFormly/contactos Obtiene la lista de contactos + + @apiDescription Get plantillasFormly/contactos, obtiene la lista de los contactos que fueron almacenados para la generación de documentos por lote + + @apiSuccess (Respuesta) {Numérico} id_contacto Identificador el contacto. + @apiSuccess (Respuesta) {Texto} nombres Nombres del contacto. + @apiSuccess (Respuesta) {Texto} apellidos Apellidos del contacto. + @apiSuccess (Respuesta) {Texto} cargo Cargo que ocupa el contacto en su entidad. + @apiSuccess (Respuesta) {Texto} entidad Entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} sigla Sigla de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} direccion Dirección de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} grado Grado de instrucción del contacto para su referencia. Ejemplo: "Lic.", "Ing.", etc. + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La busqueda de datos fue exitosa.", + "datos": { + "total": 100, + "resultado": [ + { + "id_contacto": 8, + "nombres": "Nombre Test", + "apellidos": "Contacto Prueba", + "cargo": "Director General Ejecutivo", + "entidad": "Instituto Boliviano de Metrología", + "sigla": "IBMETRO", + "direccion": "Av. Camacho N° 1488 - Edificio anexo planta baja", + "grado": "Ing." + }, + { + "id_contacto": 9, + "nombres": "Verónica", + "apellidos": "Barrios", + "cargo": "Directora General Ejecutiva a.i.", + "entidad": "Entidad de prueba", + "sigla": "ENPB", + "direccion": "Av. Camacho N° 1488 - Edificio anexo planta baja", + "grado": null + }, + {...} + ] + } + } + */ + + // app.get('/contacto', (req, res) => { + app.get('/api/v1/plantillasFormly/contactos', (req, res) => { + const consulta = {}; + if(req.query.filter) { + const buscarTexto = req.query.filter; + consulta[Op.or] = [ + { + nombres: { + [Op.iLike]: `%${buscarTexto}%`, + }, + }, + { + apellidos: { + [Op.iLike]: `%${buscarTexto}%`, + }, + }, + { + cargo: { + [Op.iLike]: `%${buscarTexto}%`, + }, + }, + { + entidad: { + [Op.iLike]: `%${buscarTexto}%`, + }, + }, + { + tipo_entidad: { + [Op.iLike]: `%${buscarTexto}%`, + }, + }, + { + sigla: { + [Op.iLike]: `%${buscarTexto}%`, + }, + }, + ]; + } + consulta.estado = 'ACTIVO' + + modelos.contacto.findAndCountAll({ + attributes: ['id_contacto', 'nombres', 'apellidos', 'cargo', 'entidad', 'sigla', 'direccion', 'grado'], + where: consulta, + }) + .then(contactoResp => { + return res.send(util.formatearMensaje('EXITO', 'La busqueda de datos fue exitosa.', { total: contactoResp.count, resultado: contactoResp.rows })); + }) + .catch(error => { + console.log('Error en la busqueda de contactos', error); + return res.status(412).send(util.formatearMensaje('ERROR', error)); + }); + + }); + + /** + @apiVersion 2.0.0 + @apiGroup Contactos + @apiName Get plantillasFormly/contactos/tiposEntidad + @api {get} /api/v1/plantillasFormly/contactos/tiposEntidad Obtiene la lista de tipos de entidad + + @apiDescription Get plantillasFormly/contactos/tiposEntidad, obtiene la lista de todos los tipos de entidad que se tengan registrados + + @apiSuccess (Respuesta) {Texto} tipo_entidad Tipo de entidad registrado + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La obtención de los tipos de entidad fue correcta", + "datos": [ + { + "tipo_entidad": "Autárquica" + }, + { + "tipo_entidad": "Dependencia MEFP" + }, + { + "tipo_entidad": "Descentralizada Departamental" + }, + { + "tipo_entidad": "Descentralizada Municipal" + }, + { + "tipo_entidad": "Empresa Departamental" + }, + { + "tipo_entidad": "Empresa Municipal" + }, + ... + ] + } + */ + + app.get('/api/v1/plantillasFormly/contactos/tiposEntidad', (req,res) => { + const sequelize = app.src.db.sequelize; + modelos.contacto.findAll({ + attributes: [ + [sequelize.literal('DISTINCT ON("contacto"."tipo_entidad") "contacto"."tipo_entidad"'), 'tipo_entidad'], + ], + }) + .then(tiposResp => { + if(!tiposResp) tiposResp = []; + return res.send(util.formatearMensaje('EXITO', 'La obtención de los tipos de entidad fue correcta', tiposResp)); + }) + .catch(error => { + console.log('Error en la obtencion de los tipos de entidad', error); + return res.status(412).send(util.formatearMensaje('ERROR', error)); + }); + }); + + /** + @apiVersion 2.0.0 + @apiGroup Contactos + @apiName Get plantillasFormly/contacto + @api {get} /api/v1/plantillasFormly/contacto/?order=&limit=&page=&filter= Obtiene la lista de todos los contactos en orden, paginado y con filtros + + @apiDescription Get plantillasFormly/contacto, obtiene la lista con datos completos de todos los contactos que fueron almacenados para la generación de documentos por lote + + @apiParam (Query) {Texto} order Campo por el cual se desea ordenar + @apiParam (Query) {Numérico} limit Cantidad de registros a mostrar + @apiParam (Query) {Numérico} page Paginado + @apiParam (Query) {Texto} filter Argumentos de filtro + + @apiSuccess (Respuesta) {Numérico} id_contacto Identificador el contacto. + @apiSuccess (Respuesta) {Texto} nombres Nombres del contacto. + @apiSuccess (Respuesta) {Texto} apellidos Apellidos del contacto. + @apiSuccess (Respuesta) {Texto} cargo Cargo que ocupa el contacto en su entidad. + @apiSuccess (Respuesta) {Texto} entidad Entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} sigla Sigla de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} direccion Dirección de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} grado Grado de instrucción del contacto para su referencia. Ejemplo: "Lic.", "Ing.", etc. + @apiSuccess (Respuesta) {Texto} tipo_entidad Tipo de entidad a la que pertenece el contacto. + @apiSuccess (Respuesta) {Texto} telefono Número de teléfono de la entidad del contacto + @apiSuccess (Respuesta) {Texto} departamento Departamento en el que se encuentra trabajando el contacto. + @apiSuccess (Respuesta) {Texto} estado Estado del registro. + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador del registro. + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario que haya modificado del registro. + @apiSuccess (Respuesta) {Texto} _fecha_creacion Fecha y hora de creación del registro. + @apiSuccess (Respuesta) {Texto} _fecha_modificacion Fecha y hora de modificación del registro. + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La busqueda de datos fue exitosa.", + "datos": { + "total": 100, + "resultado": [ + { + "id_contacto": 8, + "nombres": "Nombre Test", + "apellidos": "Contacto Prueba", + "cargo": "Director General Ejecutivo", + "entidad": "Instituto Boliviano de Metrología", + "sigla": "IBMETRO", + "direccion": "Av. Camacho N° 1488 - Edificio anexo planta baja", + "grado": "Ing.", + "tipo_entidad": "Entidades desconcentradas", + "telefono": "2372046", + "departamento": "LA PAZ", + "estado": "ACTIVO", + "_usuario_creacion": 94, + "_usuario_modificacion": null, + "_fecha_creacion": "2018-11-06T14:41:02.114Z", + "_fecha_modificacion": "2018-11-06T14:41:02.114Z" + }, + { + "id_contacto": 9, + "nombres": "Verónica", + "apellidos": "Barrios", + "cargo": "Directora General Ejecutiva a.i.", + "entidad": "Entidad de prueba", + "sigla": "ENPB", + "direccion": "Av. Camacho N° 1488 - Edificio anexo planta baja", + "grado": null, + "tipo_entidad": "Entidades desconcentradas", + "telefono": "222222", + "departamento": "LA PAZ", + "estado": "ACTIVO", + "_usuario_creacion": 94, + "_usuario_modificacion": null, + "_fecha_creacion": "2018-11-06T14:41:02.114Z", + "_fecha_modificacion": "2018-11-06T14:41:02.114Z" + }, + {...} + ] + } + } + */ + + app.get('/api/v1/plantillasFormly/contacto', util.validarContactos, sequelizeHandlers.query(modelos.contacto)); + + /** + @apiVersion 2.0.0 + @apiGroup Contactos + @apiName Get plantillasFormly/contacto/:id + @api {get} /api/v1/plantillasFormly/contacto/:id Obtiene un contacto específico + + @apiDescription Get plantillasFormly/contacto/:id, obtiene el contacto basado en su identificador único. + + @apiParam (Parámetro) {Numérico} id_contacto Identificador el contacto. + + @apiSuccess (Respuesta) {Numérico} id_contacto Identificador el contacto. + @apiSuccess (Respuesta) {Texto} nombres Nombres del contacto. + @apiSuccess (Respuesta) {Texto} apellidos Apellidos del contacto. + @apiSuccess (Respuesta) {Texto} cargo Cargo que ocupa el contacto en su entidad. + @apiSuccess (Respuesta) {Texto} entidad Entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} sigla Sigla de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} direccion Dirección de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} grado Grado de instrucción del contacto para su referencia. Ejemplo: "Lic.", "Ing.", etc. + @apiSuccess (Respuesta) {Texto} tipo_entidad Tipo de entidad a la que pertenece el contacto + @apiSuccess (Respuesta) {Texto} telefono Número de teléfono de la entidad del contacto + @apiSuccess (Respuesta) {Texto} departamento Departamento en el que se encuentra trabajando el contacto. + @apiSuccess (Respuesta) {Texto} estado Estado del registro. + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador del registro. + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario que haya modificado del registro. + @apiSuccess (Respuesta) {Texto} _fecha_creacion Fecha y hora de creación del registro. + @apiSuccess (Respuesta) {Texto} _fecha_modificacion Fecha y hora de modificación del registro. + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "id_contacto": 8, + "nombres": "Nombre Test", + "apellidos": "Contacto Prueba", + "cargo": "Director General Ejecutivo", + "entidad": "Instituto Boliviano de Metrología", + "sigla": "IBMETRO", + "direccion": "Av. Camacho N° 1488 - Edificio anexo planta baja", + "grado": "Ing.", + "tipo_entidad": "Entidades desconcentradas", + "telefono": "2372046", + "departamento": "LA PAZ", + "estado": "ACTIVO", + "_usuario_creacion": 94, + "_usuario_modificacion": null, + "_fecha_creacion": "2018-11-06T14:41:02.114Z", + "_fecha_modificacion": "2018-11-06T14:41:02.114Z" + } + } + */ + + app.get('/api/v1/plantillasFormly/contacto/:id', util.validarContactos, sequelizeHandlers.get(modelos.contacto)); + + /** + @apiVersion 2.0.0 + @apiGroup Contactos + @apiName Post contacto + @api {post} /api/v1/plantillasFormly/contacto Crear contacto + + @apiDescription Post para contacto, crea un contacto. + + @apiParam (Petición) {Texto} nombres Nombres del contacto. + @apiParam (Petición) {Texto} apellidos Apellidos del contacto. + @apiParam (Petición) {Texto} cargo Cargo que ocupa el contacto en su entidad. + @apiParam (Petición) {Texto} telefono Número de teléfono de la entidad del contacto + @apiParam (Petición) {Texto} tipo_entidad Tipo de entidad a la que pertenece el contacto + @apiParam (Petición) {Texto} entidad Entidad en la que trabaja el contacto. + @apiParam (Petición) {Texto} sigla Sigla de la entidad en la que trabaja el contacto. + @apiParam (Petición) {Texto} direccion Dirección de la entidad en la que trabaja el contacto. + @apiParam (Petición) {Texto} estado Estado del contacto + @apiParam (Petición) {Texto} departamento Departamento en el que se encuentra trabajando el contacto. + @apiParam (Petición) {Texto} grado Grado de instrucción del contacto para su referencia. Ejemplo: "Lic.", "Ing.", etc. + @apiParam (Petición) {Numérico} _usuario_creacion Identificador del usuario creador del registro. + @apiParam (Petición) {Texto} _fecha_creacion Fecha y hora de creación del registro. + @apiParam (Petición) {Texto} _fecha_modificacion Fecha y hora de modificación del registro. + + @apiParamExample {json} Ejemplo para enviar: + { + "nombres":"Mery", + "apellidos":"Meriles", + "cargo":"Profesional", + "telefono":"2123456", + "tipo_entidad":"Empresas Públicas", + "entidad":"Entida de prueba", + "sigla":"EMPB", + "direccion":"Una dirección inventada", + "estado":"ACTIVO", + "departamento":"LA PAZ", + "_usuario_creacion":94, + "_fecha_creacion":"2020-01-10T19:12:24.563Z", + "_fecha_modificacion":"2020-01-10T19:12:24.564Z" + } + + @apiSuccess (Respuesta) {Numérico} id_contacto Identificador el contacto. + @apiSuccess (Respuesta) {Texto} nombres Nombres del contacto. + @apiSuccess (Respuesta) {Texto} apellidos Apellidos del contacto. + @apiSuccess (Respuesta) {Texto} cargo Cargo que ocupa el contacto en su entidad. + @apiSuccess (Respuesta) {Texto} entidad Entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} sigla Sigla de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} direccion Dirección de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} grado Grado de instrucción del contacto para su referencia. Ejemplo: "Lic.", "Ing.", etc. + @apiSuccess (Respuesta) {Texto} tipo_entidad Tipo de entidad a la que pertenece el contacto + @apiSuccess (Respuesta) {Texto} telefono Número de teléfono de la entidad del contacto + @apiSuccess (Respuesta) {Texto} departamento Departamento en el que se encuentra trabajando el contacto. + @apiSuccess (Respuesta) {Texto} estado Estado del registro. + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador del registro. + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario que haya modificado del registro. + @apiSuccess (Respuesta) {Texto} _fecha_creacion Fecha y hora de creación del registro. + @apiSuccess (Respuesta) {Texto} _fecha_modificacion Fecha y hora de modificación del registro. + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "id_contacto": 8, + "nombres":"Mery", + "apellidos":"Meriles", + "cargo":"Profesional", + "telefono":"2123456", + "tipo_entidad":"Empresas Públicas", + "entidad":"Entida de prueba", + "sigla":"EMPB", + "direccion":"Una dirección inventada", + "estado":"ACTIVO", + "departamento":"LA PAZ", + "_usuario_creacion":94, + "_usuario_modificacion": null, + "_fecha_creacion":"2020-01-10T19:12:24.563Z", + "_fecha_modificacion":"2020-01-10T19:12:24.564Z" + + } + } + + @apiSampleRequest off + */ + + app.post('/api/v1/plantillasFormly/contacto', util.validarContactos, sequelizeHandlers.create(modelos.contacto)); + + /** + @apiVersion 1.0.0 + @apiGroup Contactos + @apiName Put contactos/:id + @api {put} /api/v1/plantillasFormly/contacto/:id Actualiza datos contacto + + @apiDescription Put contactos/:id, actualiza los datos de un contacto específico + + @apiParam (Parámetro) {Numérico} id Identificador del contacto + + @apiParam (Petición) {Texto} nombres Nombres del contacto. + @apiParam (Petición) {Texto} apellidos Apellidos del contacto. + @apiParam (Petición) {Texto} cargo Cargo que ocupa el contacto en su entidad. + @apiParam (Petición) {Texto} telefono Número de teléfono de la entidad del contacto + @apiParam (Petición) {Texto} tipo_entidad Tipo de entidad a la que pertenece el contacto + @apiParam (Petición) {Texto} entidad Entidad en la que trabaja el contacto. + @apiParam (Petición) {Texto} sigla Sigla de la entidad en la que trabaja el contacto. + @apiParam (Petición) {Texto} direccion Dirección de la entidad en la que trabaja el contacto. + @apiParam (Petición) {Texto} estado Estado del contacto + @apiParam (Petición) {Texto} departamento Departamento en el que se encuentra trabajando el contacto. + @apiParam (Petición) {Texto} grado Grado de instrucción del contacto para su referencia. Ejemplo: "Lic.", "Ing.", etc. + @apiParam (Petición) {Numérico} _usuario_creacion Identificador del usuario creador del registro. + @apiParam (Petición) {Texto} _fecha_creacion Fecha y hora de creación del registro. + @apiParam (Petición) {Texto} _fecha_modificacion Fecha y hora de modificación del registro. + + @apiParamExample {json} Ejemplo para enviar: + { + "nombres":"Mery Mery", + "apellidos":"Meriles", + "grado": "DOCTORA", + "cargo":"Profesional", + "telefono":"2123456", + "tipo_entidad":"Empresas Públicas", + "entidad":"Entida de prueba", + "sigla":"EMPB", + "direccion":"Una dirección inventada", + "estado":"ACTIVO", + "departamento":"LA PAZ", + "_usuario_creacion":94, + "_fecha_creacion":"2020-01-10T19:12:24.563Z", + "_fecha_modificacion":"2020-01-10T19:12:24.564Z" + } + + @apiSuccess (Respuesta) {Numérico} id_contacto Identificador el contacto. + @apiSuccess (Respuesta) {Texto} nombres Nombres del contacto. + @apiSuccess (Respuesta) {Texto} apellidos Apellidos del contacto. + @apiSuccess (Respuesta) {Texto} cargo Cargo que ocupa el contacto en su entidad. + @apiSuccess (Respuesta) {Texto} entidad Entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} sigla Sigla de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} direccion Dirección de la entidad en la que trabaja el contacto. + @apiSuccess (Respuesta) {Texto} grado Grado de instrucción del contacto para su referencia. Ejemplo: "Lic.", "Ing.", etc. + @apiSuccess (Respuesta) {Texto} tipo_entidad Tipo de entidad a la que pertenece el contacto + @apiSuccess (Respuesta) {Texto} telefono Número de teléfono de la entidad del contacto + @apiSuccess (Respuesta) {Texto} departamento Departamento en el que se encuentra trabajando el contacto. + @apiSuccess (Respuesta) {Texto} estado Estado del registro. + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador del registro. + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario que haya modificado del registro. + @apiSuccess (Respuesta) {Texto} _fecha_creacion Fecha y hora de creación del registro. + @apiSuccess (Respuesta) {Texto} _fecha_modificacion Fecha y hora de modificación del registro. + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "id_contacto": 8, + "nombres":"Mery", + "apellidos":"Meriles", + "cargo":"Profesional", + "grado": "DOCTORA", + "telefono":"2123456", + "tipo_entidad":"Empresas Públicas", + "entidad":"Entida de prueba", + "sigla":"EMPB", + "direccion":"Una dirección inventada", + "estado":"ACTIVO", + "departamento":"LA PAZ", + "_usuario_creacion":94, + "_usuario_modificacion": null, + "_fecha_creacion":"2020-01-10T19:12:24.563Z", + "_fecha_modificacion":"2020-01-10T19:12:24.564Z" + + } + } + + @apiSampleRequest off + */ + app.put('/api/v1/plantillasFormly/contacto/:id', util.validarContactos, sequelizeHandlers.update(modelos.contacto)); + + app.route('/api/v1/plantillasFormly/contacto').options(options.formly(modelos.contacto, modelos)); + +}; \ No newline at end of file diff --git a/src/routes/plantillasFormly/correlativoRT.js b/src/routes/plantillasFormly/correlativoRT.js new file mode 100644 index 0000000..00c927e --- /dev/null +++ b/src/routes/plantillasFormly/correlativoRT.js @@ -0,0 +1,3 @@ +/** + No se generan los servicios para correlativo, porque no son necesarios. +*/ diff --git a/src/routes/plantillasFormly/documentoRT.js b/src/routes/plantillasFormly/documentoRT.js new file mode 100644 index 0000000..8e4b8a5 --- /dev/null +++ b/src/routes/plantillasFormly/documentoRT.js @@ -0,0 +1,1475 @@ +const {ModelHandler} = require("sequelize-handlers"); +const sequelizeFormly = require("sequelize-formly"); +const _ = require('lodash'); +const fs = require("fs"); +const moment = require('moment'); +require('colors'); + +module.exports = app => { + const modelos = app.src.db.models; + const documento = app.src.db.models.documento; + const unidad = app.src.db.models.unidad; + const usuario = app.src.db.models.usuario; + const correlativo = app.src.db.models.correlativo; + const historial_flujo = app.src.db.models.historial_flujo; + const confNotificacion = app.src.db.models.conf_notificacion; + const notificacion = app.src.db.models.notificacion; + const partida = app.src.db.models.partida; + const Op = app.src.db.Sequelize.Op; + const util = require('../../lib/util'); + const correo = require('../../lib/correo'); + const notificar = require('../../lib/notificacion'); + const archivo = require('../../lib/archivos'); + const bl = require('../../bl/plantillasFormly/documentoBL'); + const blm = require('../../bl/monitor/monitorBL'); + const sequelize = app.src.db.sequelize; + const rutaExternos = app.src.config.config.ruta_externos; + const director = app.src.config.config.sistema.director; + const citeGuia = app.src.config.config.sistema.cite_principal; + const citeCeros = app.src.config.config.sistema.cite_ceros; + const prefijo = app.src.config.config.prefijo; + const dirDocumento = app.src.config.config.ruta_documentos; + const sequelizeHandlers = new ModelHandler(documento); + // const Op = app.src.db.sequelize.Op; + +/** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Post documento + @api {post} /api/v1/plantillasFormly/documento Crear documento + + @apiDescription Post para documento + + @apiParam (Petición) {Texto} nombre Nombre del documento + @apiParam (Petición) {Texto} nombre_plantilla Nombre de la planilla usada para el documento + @apiParam (Petición) {Texto} abreviacion Sigla o abreviación del documento + @apiParam (Petición) {Texto} plantilla Plantilla del documento + @apiParam (Petición) {Texto} plantilla_valor Valores de la plantilla + @apiParam (Petición) {Texto} sw Propiedades del documento + @apiParam (Petición) {Numérico} _usuario_creacion Identificador del usuario que esta creando + + @apiParamExample {json} Ejemplo para enviar: + { + "nombre": "INSTRUCTIVO - Juan Perez", + "nombre_plantilla": "INSTRUCTIVO", + "abreviacion": "II", + "plantilla": "[]", + "plantilla_valor": "{}", + "sw": "{"enviado": "false", "enviar": "false", "es_respuesta":"false"}", + "_usuario_creacion": 1 + } + + @apiSuccess (Respuesta) {Numérico} id_documento Identificador de documento + @apiSuccess (Respuesta) {Texto} nombre Nombre del documento + @apiSuccess (Respuesta) {Texto} nombre_planilla Nombre de la planilla usada para el documento + @apiSuccess (Respuesta) {Texto} plantilla Plantilla del documento + @apiSuccess (Respuesta) {Texto} plantilla_valor Valores de la plantilla + @apiSuccess (Respuesta) {Texto} abreviacion Sigla o abreviación de la plantilla + @apiSuccess (Respuesta) {Texto} estado Estado del registro + @apiSuccess (Respuesta) {Boolean} firmado Si el documento ha sido firmado + @apiSuccess (Respuesta) {Boolean} anulado Si el documento ha sido anulado + @apiSuccess (Respuesta) {Texto} impreso Si el documento ha sido impreso + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario modificador + @apiSuccess (Respuesta) {FechaHora} _fecha_creacion Fecha de creación de documento + @apiSuccess (Respuesta) {FechaHora} _fecha_modificacion Fecha de modificación de documento + @apiSuccess (Respuesta) {Texto} de Remitente del documento + @apiSuccess (Respuesta) {Texto} para Destino del documento + @apiSuccess (Respuesta) {Texto} via Usuarios por los que deba pasar del documento antes del desstino + @apiSuccess (Respuesta) {Texto} via_actual Posición del documento actual + @apiSuccess (Respuesta) {Texto} referencia Referencias del documento + @apiSuccess (Respuesta) {Texto} fecha Fecha del documento + @apiSuccess (Respuesta) {Texto} observaciones Observaciones del documento + @apiSuccess (Respuesta) {Texto} documento_padre Documento del cual haya derivado el documento actual + @apiSuccess (Respuesta) {Numérico} grupo Grupo al que pertenezca el documeto + @apiSuccess (Respuesta) {Texto} firmaron Firmantes del documento + @apiSuccess (Respuesta) {Texto} firmante_actual Usuario que debe firmar para proseguir con el flujo + @apiSuccess (Respuesta) {Texto} multiple Copias del documento + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "id_documento": 3, + "nombre": "INSTRUCTIVO", + "nombre_plantilla": "INSTRUCTIVO", + "abreviacion": "II", + "plantilla": "[]", + "plantilla_valor": "{}", + "estado": "ACTIVO", + "firmado": false, + "impreso": "NO", + "anulado": false, + "estado": "NUEVO", + "_usuario_creacion": 1, + "_fecha_modificacion": "2016-12-02T20:16:10.276Z", + "_fecha_creacion": "2016-12-02T20:16:10.276Z", + "_usuario_modificacion": null, + "de": "null", + "para": "null", + "via": "null", + "via_actual": "null", + "referencia": "null", + "fecha": "null", + "observaciones": "null", + "documento_padre": "null", + "grupo": 6082, + "firmaron": "null", + "firmante_actual": "null", + "multiple": "null" + + } + } + + @apiSampleRequest off +*/ + app.post('/api/v1/plantillasFormly/documento', (req, res) => { + let xdoc; + const msg = "La operación se realizó correctamente."; + const sw = req.body.sw; + sw.xenviar = !sw.enviado && sw.enviar; + const model = JSON.parse(req.body.plantilla_valor); + + sequelize.transaction().then(t => { + const tr = { transaction: t }; + bl.verificarExternos(req.body,rutaExternos) + .then(pValores => { + if(pValores) req.body.plantilla_valor=pValores; + return bl.verificarObtenerMultiple(req.body, tr); + }) + .then(multipleResp => { + console.log('Revisando la respuesta de la validacion multiple', multipleResp); + if(multipleResp.esMultiple == true) { + req.body.multiple = multipleResp.multiple; + } + + return documento.create(req.body, tr) + .then( resp => { + xdoc = resp; + return bl.actualizarGrupo(documento, xdoc, tr); + }) + .then( resp => { + if (sw.xenviar){ + return bl.verificarPartidas(partida, model); + } + return + }) + .then( resp => { + if(sw.xenviar && sw.es_respuesta){ + return bl.documento_crear(historial_flujo, xdoc.documento_padre, xdoc._usuario_creacion, tr); + } + return; + }) + .then( resp => { + if(sw.xenviar){ + return bl.documento_enviar(historial_flujo, xdoc, tr, director) + .then(() => t.commit()) + .finally(() => notificar.enviar(modelos, xdoc,'enviado',{})); + } + return; + }); + }) + .then( resp => { + if(!sw.xenviar) t.commit(); + res.send(util.formatearMensaje("EXITO", msg, xdoc)); + }) + .catch(e => { + t.rollback(); + res.status(412).send(util.formatearMensaje("ERROR", e)); + }); + }); + + + }); + +/** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Get documento/:id + @api {get} /api/v1/plantillasFormly/documento/:id Obtiene un/a documento + + @apiDescription Get documento, obtiene un/a documento + + @apiParam (Parámetro) {Numérico} id Identificador de documento que se quiere obtener + + @apiSuccess (Respuesta) {Numérico} id_documento Identificador de documento + @apiSuccess (Respuesta) {Texto} nombre Nombre del documento + @apiSuccess (Respuesta) {Texto} nombre_planilla Nombre de la planilla usada para el documento + @apiSuccess (Respuesta) {Texto} plantilla Plantilla del documento + @apiSuccess (Respuesta) {Texto} plantilla_valor Valores de la plantilla + @apiSuccess (Respuesta) {Texto} abreviacion Sigla o abreviación de la plantilla + @apiSuccess (Respuesta) {Texto} estado Estado del registro + @apiSuccess (Respuesta) {Boolean} firmado Si el documento ha sido firmado + @apiSuccess (Respuesta) {Boolean} anulado Si el documento ha sido anulado + @apiSuccess (Respuesta) {Texto} impreso Si el documento ha sido impreso + @apiSuccess (Respuesta) {Texto} de Remitente del documento + @apiSuccess (Respuesta) {Texto} para Destino del documento + @apiSuccess (Respuesta) {Texto} via Usuarios por los que deba pasar del documento antes del desstino + @apiSuccess (Respuesta) {Texto} via_actual Posición del documento actual + @apiSuccess (Respuesta) {Texto} referencia Referencias del documento + @apiSuccess (Respuesta) {Texto} fecha Fecha del documento + @apiSuccess (Respuesta) {Texto} observaciones Observaciones del documento + @apiSuccess (Respuesta) {Texto} documento_padre Documento del cual haya derivado el documento actual + @apiSuccess (Respuesta) {Numérico} grupo Grupo al que pertenezca el documeto + @apiSuccess (Respuesta) {Texto} firmaron Firmantes del documento + @apiSuccess (Respuesta) {Texto} firmante_actual Usuario que debe firmar para proseguir con el flujo + @apiSuccess (Respuesta) {Texto} multiple Copias del documento + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario modificador + @apiSuccess (Respuesta) {FechaHora} _fecha_creacion Fecha de creación de documento + @apiSuccess (Respuesta) {FechaHora} _fecha_modificacion Fecha de modificación de documento + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "id_documento": 1, + "nombre": "INSTRUCTIVO", + "nombre_plantilla": "INSTRUCTIVO", + "abreviacion": "II", + "estado": "ACTIVO", + "plantilla": "[{\"type\":\"textoh2\",\"key\":\"textoh2\",\"className\":\"ap-text-center\",\"templateOptions\":{\"label\":\"INSTRUCTIVO\"}},{\"type\":\"input\",\"key\":\"inputText\",\"templateOptions\":{\"type\":\"text\",\"label\":\"CITE:\",\"disabled\":false,\"required\":true}},{\"type\":\"input\",\"key\":\"inputText\",\"templateOptions\":{\"type\":\"text\",\"label\":\"A:\",\"disabled\":false,\"required\":true}},{\"type\":\"input\",\"key\":\"inputText\",\"templateOptions\":{\"type\":\"text\",\"label\":\"REF:\",\"disabled\":false,\"required\":true}},{\"type\":\"datepicker\",\"key\":\"inputDatePicker\",\"templateOptions\":{\"label\":\"FECHA:\",\"disabled\":false,\"required\":true}},{\"type\":\"textarea\",\"key\":\"inputTextArea\",\"templateOptions\":{\"label\":\"Contenido:\",\"rows\":6,\"grow\":false,\"required\":true}}]", + "plantilla_valor": "{\"input-0\":\"AGETIC/UAF/002/2016\",\"input-1\":\"Todo el personal de la AGETIC\",\"input-2\":\"SOLICITUD DE VIATICOS\",\"datepicker-0\":\"2016-12-01T04:00:00.000Z\",\"textarea-0\":\"Se comunica al personal de la Agencia de Gobierno Electrónico y Tecnologías de Información y Comunicación que sea declarado en Comisión de Viaje debe realizar los requerimientos de pasajes y viáticos por separado para facilitar el pago:\\n\\nPara pasajes: Señalar los nombres completos de los pasajeros, la cedula de identidad, el lugar, la fecha de ida y de retorno debidamente justificado. Adjuntar la reserva del pasaje con el precio referencial \\n\\nEjemplo: Soila Ana Vaca Rodríguez, C.I. 9999999 L.P. y Juan Carlos Perico Pericon C.I. 8888888 L.P. viajaran a Tarija el 9/02/2015 y regresaran 10/02/2015 para la instalación de la red en el SIN. \\n\\nPara viáticos: Llenar el formulario correspondiente adjuntando el Memorandum y la certificación presupuestaria . Para el calculo de pago de viatico se considera un importe bruto de Bs. 371.- por día sujetos a retencion del 13% RC IVA (Excepto el Director General Ejecutivo)\\n\\nEs cuanto informo para fines consiguientes\\n\\n\\nLa Paz, 1 de diciembre de 2016\"}", + "estado": "ACTIVO", + "firmado": "false", + "impreso": "NO", + "anulado": "false", + "de": "null", + "para": "null", + "via": "null", + "via_actual": "null", + "referencia": "null", + "fecha": "null", + "observaciones": "null", + "documento_padre": "null", + "grupo": 6082, + "firmaron": "null", + "firmante_actual": "null", + "multiple": "null" + "_usuario_creacion": 1, + "_usuario_modificacion": 1, + "_fecha_creacion": "2016-12-01T19:09:18.329Z", + "_fecha_modificacion": "2016-12-01T19:34:14.745Z" + } + } +*/ + app.get('/api/v1/plantillasFormly/documento/:id', Validar, (req,res) => { + console.log("Iniciando con la obtencion del documento"); + + documento.findOne({ + where:{ + id_documento:req.params.id, + estado:{$ne:'ELIMINADO'}, + }, + }) + .then(pDocumento => { + if(pDocumento) + res.status(200).send(util.formatearMensaje("EXITO","La operación se realizó correctamente.", pDocumento)); + else throw new Error("El documento solicitado no esta disponible."); + }) + .catch(pError => res.status(412).send(util.formatearMensaje("ERROR",pError))); + }); + + /** + * Función que realiza el registro de la visita, validando si esta relacionado con el usuario. + * @param {[type]} req [description] + * @param {[type]} res [description] + * @param {Function} next [description] + */ + function Validar(req,res, next){ + // console.log("Iniciando la validacion"); + const usuarioPeticion = req.body.audit_usuario; + let + cite = false, + resultado = null; + + documento.findByPk(req.params.id) + .then(pDocumento => { + if(pDocumento){ + resultado= pDocumento; + + if(pDocumento.estado != 'NUEVO'){ + cite = (pDocumento.estado == 'ENVIADO')? false : true; + return bl.validarPeticionGet(documento, historial_flujo, pDocumento, usuarioPeticion) + .then(pValido => { + req.body.relacionado = pValido; + }); + } + else if (pDocumento.estado == 'NUEVO') { + if(pDocumento._usuario_creacion == usuarioPeticion.id_usuario) req.body.relacionado=true; + else req.body.relacionado=false; + } + else req.body.relacionado=false; + + } + else req.body.relacionado=false; + }) + .then(() => { + const + rmip = req.connection.remoteAddress, + miIp = rmip.substr(rmip.lastIndexOf(':')+1,rmip.length), + log = { + fid_usuario:req.body.audit_usuario.id_usuario, + fid_documento:req.params.id, + ip:[miIp], + relacionado:req.body.relacionado, + cite, + }; + blm.registrarVisita(app.src.db.models,log) + .finally(() => { + next(); + }); + }) + .catch(pError => { + console.log("Error al validar"); + res.status(412).send(util.formatearMensaje("ERROR",pError)); + }); + } + +/** + @apiVersion 1.0.0 + @apiGroup Documento + @apiName Get documento/?order=&limit=&page=&filter= + @api {get} /api/v1/plantillasFormly/documento/?order=&limit=&page=&filter= Obtiene la lista paginada de documentos + + @apiDescription Get documento + + @apiParam (Query) {Texto} order Campo por el cual se ordenará el resultado + @apiParam (Query) {Numérico} limit Cantidad de resultados a obtener + @apiParam (Query) {Numérico} page Número de página de resultados + @apiParam (Query) {Texto} filter Texto a buscar en los registros + + @apiSuccess (Respuesta) {Texto} tipoMensaje Tipo del mensaje de respuesta. + @apiSuccess (Respuesta) {Texto} mensaje Mensaje de respuesta. + @apiSuccess (Respuesta) {Objeto} datos Objeto de con los datos de respuesta + @apiSuccess (Respuesta) {Numérico} total Numero de objetos categoria + @apiSuccess (Respuesta) {Array} resultado Array de objetos categoria + + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "total": 2, + "resultado": [ + { + "id_documento": 1, + "nombre": "INSTRUCTIVO", + "plantilla": "[{\"type\":\"textoh2\",\"key\":\"textoh2\",\"className\":\"ap-text-center\",\"templateOptions\":{\"label\":\"INSTRUCTIVO\"}},{\"type\":\"input\",\"key\":\"inputText\",\"templateOptions\":{\"type\":\"text\",\"label\":\"CITE:\",\"disabled\":false,\"required\":true}},{\"type\":\"input\",\"key\":\"inputText\",\"templateOptions\":{\"type\":\"text\",\"label\":\"A:\",\"disabled\":false,\"required\":true}},{\"type\":\"input\",\"key\":\"inputText\",\"templateOptions\":{\"type\":\"text\",\"label\":\"REF:\",\"disabled\":false,\"required\":true}},{\"type\":\"datepicker\",\"key\":\"inputDatePicker\",\"templateOptions\":{\"label\":\"FECHA:\",\"disabled\":false,\"required\":true}},{\"type\":\"textarea\",\"key\":\"inputTextArea\",\"templateOptions\":{\"label\":\"Contenido:\",\"rows\":6,\"grow\":false,\"required\":true}}]", + "plantilla_valor": "{\"input-0\":\"AGETIC/UAF/002/2016\",\"input-1\":\"Todo el personal de la AGETIC\",\"input-2\":\"SOLICITUD DE VIATICOS\",\"datepicker-0\":\"2016-12-01T04:00:00.000Z\",\"textarea-0\":\"Se comunica al personal de la Agencia de Gobierno Electrónico y Tecnologías de Información y Comunicación que sea declarado en Comisión de Viaje debe realizar los requerimientos de pasajes y viáticos por separado para facilitar el pago:\\n\\nPara pasajes: Señalar los nombres completos de los pasajeros, la cedula de identidad, el lugar, la fecha de ida y de retorno debidamente justificado. Adjuntar la reserva del pasaje con el precio referencial \\n\\nEjemplo: Soila Ana Vaca Rodríguez, C.I. 9999999 L.P. y Juan Carlos Perico Pericon C.I. 8888888 L.P. viajaran a Tarija el 9/02/2015 y regresaran 10/02/2015 para la instalación de la red en el SIN. \\n\\nPara viáticos: Llenar el formulario correspondiente adjuntando el Memorandum y la certificación presupuestaria . Para el calculo de pago de viatico se considera un importe bruto de Bs. 371.- por día sujetos a retencion del 13% RC IVA (Excepto el Director General Ejecutivo)\\n\\nEs cuanto informo para fines consiguientes\\n\\n\\nLa Paz, 1 de diciembre de 2016\"}", + "estado": "ACTIVO", + "_usuario_creacion": 1, + "_usuario_modificacion": 1, + "_fecha_creacion": "2016-12-01T19:09:18.329Z", + "_fecha_modificacion": "2016-12-01T19:34:14.745Z" + }, + { + "id_documento": 2, + "nombre": "CIRCULAR", + "plantilla": "[{\"type\":\"textoh1\",\"key\":\"textoh1\",\"className\":\"ap-text-center\",\"templateOptions\":{\"label\":\"CIRCULAR\"}},{\"type\":\"textoh3\",\"key\":\"textoh3\",\"className\":\"ap-text-center\",\"templateOptions\":{\"label\":\"AGETIC/UAF N°083/2016\"}},{\"type\":\"input\",\"key\":\"inputText\",\"templateOptions\":{\"type\":\"text\",\"label\":\"DE:\",\"disabled\":false,\"required\":true}},{\"type\":\"input\",\"key\":\"inputText\",\"templateOptions\":{\"type\":\"text\",\"label\":\"A:\",\"disabled\":false,\"required\":true}},{\"type\":\"input\",\"key\":\"inputText\",\"templateOptions\":{\"type\":\"text\",\"label\":\"REF:\",\"disabled\":false,\"required\":true}},{\"type\":\"datepicker\",\"key\":\"inputDatePicker\",\"templateOptions\":{\"label\":\"FECHA:\",\"disabled\":false,\"required\":true}},{\"type\":\"parrafo\",\"key\":\"textParrafo\",\"className\":\"ap-text-justify\",\"templateOptions\":{\"label\":\"Dando cumplimiento a lo establecido en el Decreto Supremo N° 21531 de fecha 29 de junio de 1995 y la reglamentación relativa al Régimen Complementario al Impuesto al Valor Agregado (RC-IVA), así como la remisión del formulario 110 RC-IVA dependientes, todos los servidores públicos deben tomar en cuenta:\"}},{\"type\":\"parrafo\",\"key\":\"textParrafo\",\"className\":\"ap-text-justify\",\"templateOptions\":{\"label\":\"1. El formulario RC-IVA 110 debidamente llenado tanto para el pago de sueldos como para refrigerios deben ser presentados desde el 01 hasta el día 15 de cada mes o el siguiente día hábil en caso de ser fin de semana o feriado. \\n2. La elaboración de los formularios debe realizarse en el programa Facilito, el cual está instalado en todos los computadores.\"}},{\"type\":\"parrafo\",\"key\":\"textParrafo\",\"className\":\"ap-text-justify\",\"templateOptions\":{\"label\":\"La Unidad Administrativa Financiera mediante Recursos Humanos se pone a disposición de todos los funcionarios que tengan dudad o requieran mayor información a la presente circular.\"}},{\"type\":\"parrafo\",\"key\":\"textParrafo\",\"className\":\"ap-text-left\",\"templateOptions\":{\"label\":\"Atentamente,\"}}]", + "plantilla_valor": "{\"datepicker-0\":\"2016-12-01T04:00:00.000Z\",\"input-0\":\"Carmen Fedra Valverde\",\"input-1\":\"Todo el personal de planta de la Agencia de Gobierno Electronico y Tecnologías de Información y Comunicación\",\"input-2\":\"FORMULARIOS RC-IVA\"}", + "estado": "ACTIVO", + "_usuario_creacion": 1, + "_usuario_modificacion": null, + "_fecha_creacion": "2016-12-01T19:36:18.489Z", + "_fecha_modificacion": "2016-12-01T19:36:18.489Z" + } + ] + } +} + +*/ + app.get('/api/v1/plantillasFormly/documento', sequelizeHandlers.query(documento)); + + function filtros (req,res,next){ + if(req.query.filter!='') + util.consulta(req,res,next,documento) + else next(); + } + + /** + @apiVersion 2.0.0 + @apiGroup Plantillas_Formly + @apiName Post plantillasFormly/documentoPDF + @api {post} /api/v1/plantillasFormly/documentoPDF Generar el documento PDF en base a una plantillas_formly + + @apiDescription Post del plantillasFormly/documentoPDF para generar el documento en formato PDF en base a una plantilla + + @apiParam (Petición) {Texto} cite Nombre del documento PDF + + @apiParamExample {json} Ejemplo para enviar: + { + "cite":"plantilla_test.pdf" + } + + @apiSuccess (Respuesta) {Base64} Archivo pdf en Base64 + + @apiSuccessExample {Base64} Respuesta del Ejemplo: + HTTP/1.1 200 OK + + JVBERi0xLjQKMSAwIG9iago8PAovVGl0bGUgKP7/.... + + @apiSampleRequest off +*/ + + app.post('/api/v1/plantillasFormly/documentoPDF', (req, res) => { + let dirArch = '.'; + if(req.body.cite && req.body.cite.indexOf('/public/externos/')==0) + dirArch += req.body.cite + else dirArch += `/public/documentos/${req.body.cite}`; + const nombre= req.body.cite.substr(0,req.body.cite.indexOf('.pdf')); + const usuarioPeticion = req.body.audit_usuario; + const msg = "Usted no esta autorizado para ver este documento."; + + fs.readFile(dirArch, (pError, pData) => { + + if(pError){ + pError=(process.env.NODE_ENV=='production')?"No se pudo obtener el documento":pError; + res.status(412).send(util.formatearMensaje("ERROR",pError)); + } + else res.send(pData); + }); + }) + + app.post('/api/v1/plantillasFormly/multiple', (req, res) => { + console.log('Iniciando la busqueda de documentos multiples', req.body.cite); + if (!req.body.cite || req.body.cite == "") { + return res.status(412).send(util.formatearMensaje("ERROR", 'El número de cite no es válido.')); + } + modelos.documento.findOne({ + attributes: ['id_documento', 'nombre', 'multiple'], + where:{ + nombre: req.body.cite, + estado: { + $notIn: ['ELIMINADO', 'ENVIADO'] + } + } + }) + .then(respDocumento => { + if(!respDocumento) throw Error('No existe el documento solicitado.'); + return modelos.documento.findAll({ + attributes:['nombre'], + where: { + multiple: respDocumento.dataValues.multiple, + } + }); + }) + .then(respDocumentos => { + return archivo.obtenerBufferLista(dirDocumento, respDocumentos); + }) + .then(respBuffer => { + res.send(respBuffer); + }) + .catch(error => { + console.log('Error en la busqueda del documento', error); + return res.status(412).send(util.formatearMensaje("ERROR", error)); + }); + + }); + + /** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Get plantillasFormly/documento/:id/misdocumentos/?order=&limit=&page=&filter=&fields= + @api {get} /api/v1/plantillasFormly/documento/:id/misdocumentos/?order=&limit=&page=&filter=&fields= Obtiene lista de los documentos del usuario actual + + @apiDescription Get plantillasFormly/documento/:id/misdocumentos/?order=&limit=&page=&filter=&fields=, obtiene lista de los documentos del usuario actual de acuerdo a las especificaciones de orden, límite, paginación, filtros y campos + + @apiParam (Parámetro) {Numérico} id Identificador del usuario actual + + @apiParam (Query) {Texto} order Campo por el cual se ordenará el resultado + @apiParam (Query) {Numérico} limit Cantidad de resultados a obtener + @apiParam (Query) {Numérico} page Número de página de resultados + @apiParam (Query) {Texto} filter Texto a buscar en los registros + @apiParam (Query) {Texto} fields Campos de la búsqueda a mostrar + + @apiSuccess (Respuesta) {Numérico} total Número de documentos encontrados + @apiSuccess (Respuesta) {Texto} resultado Array de documentos encontrados + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La busqueda fue exitosa", + "datos": { + "total": 1, + "resultado": [ + { + "id_documento": 62, + "nombre": "Instructivo - Juan Perez", + "nombre_plantilla": "Instructivo", + "fecha": null, + "estado": "NUEVO", + "impreso": "NO", + "_fecha_creacion": "2020-01-08T22:21:14.857Z", + "_fecha_modificacion": "2020"-01-08T22:31:14.764Z, + "_usuario_creacion": 3 + } + ] + } + } +*/ + + app.get('/api/v1/plantillasFormly/documento/:id/misdocumentos', filtros, (req, res) => { + if (req.params.id != req.body.audit_usuario.id_usuario) { + return res.status(412).send(util.formatearMensaje("ERROR", 'Usted no tiene la autorización.')); + } + const documentos=[]; + const estFlujo = []; + const estDoc = []; + const xdocs = {}; + const estVal = { + 'nuevo': 'NUEVO', + 'envia': 'ENVIADO', + // 'cerra': 'APROBADO', + 'cerra': 'CERRADO', + 'deriv': 'DERIVADO', + //-------flujo----- + 'aprobe': 'CERRADO', + 'aprobe': 'APROBADO', + 'rechace': 'RECHAZADO', + 'derive': 'DERIVADO', + 'respondi': 'CREADO', + }; + const estKeyFlujo = { + //-------flujo----- + 'APROBADO': 'APROBE', + 'RECHAZADO': 'RECHACE', + 'DERIVADO': 'DERIVE', + 'CREADO': 'RESPONDI', + 'CERRADO': 'APROBE', + 'FIRMO': 'FIRMÉ', + }; + if(req.query.estado){ + req.query.estado.split(',').forEach(it => { + if(['nuevo','envia','recha','cerra','deriv'].indexOf(it)!=-1) estDoc.push(estVal[it]); + else estFlujo.push(estVal[it]); + }); + } + const opcionesFlujo = { + attributes:['id_documento', 'accion'], + where: { _usuario_creacion: req.body.audit_usuario.id_usuario }, + order: [['_fecha_creacion']], + }; + if(req.query.estado) + opcionesFlujo.where.accion = { $in: estFlujo}; + + historial_flujo.findAll(opcionesFlujo) + .then(pRespuesta => { + if(pRespuesta){ + pRespuesta.forEach((pItem) => { + documentos.push(pItem.dataValues.id_documento); + xdocs[pItem.dataValues.id_documento]=pItem; + }); + } + const opcionesDocumento={}; + opcionesDocumento.where={ + $or: [ + { _usuario_creacion:req.params.id }, + { id_documento:{ $in:documentos }}, + ], + estado:{$notIn: ['ELIMINADO','RECHAZADO']}, + }; + + if(req.query.filter!=='' && req.xfilter){ + opcionesDocumento.where.$or[0].$or = req.xfilter; + opcionesDocumento.where.$or[1].$or = req.xfilter; + } + + + if(req.query.fields){ + opcionesDocumento.attributes=req.query.fields.split(','); + opcionesDocumento.attributes.push('_usuario_creacion'); + } + if(req.query.estado) + opcionesDocumento.where.$or[0].estado={$in:estDoc}; + if(req.query.limit) + opcionesDocumento.limit=req.query.limit; + if(req.query.page) + opcionesDocumento.offset=(req.query.limit * ((req.query.page || 1) - 1)) || 0; + let order; + if(req.query.order){ + order = (req.query.order.charAt(0)=='-')? 'DESC': ''; + req.query.order = (req.query.order.charAt(0)=='-')? req.query.order.substring(1,req.query.order.length) : req.query.order; + opcionesDocumento.order = [[req.query.order, order]]; + } + return documento.findAndCountAll(opcionesDocumento); + + }) + .then(pRespuesta => { + if(xdocs){ + pRespuesta.rows.forEach( d => { + if(d._usuario_creacion != req.params.id){ + d.estado = estKeyFlujo[xdocs[d.id_documento].accion]; + } + delete d._usuario_creacion; + }); + } + res.send(util.formatearMensaje("EXITO", "La busqueda fue exitosa", {total:pRespuesta.count,resultado:pRespuesta.rows})); + }) + .catch(pError => { + res.status(412).send(util.formatearMensaje("ERROR", pError)); + }); + }); + + /** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Get plantillasFormly/documento/:id/todo + @api {get} /api/v1/plantillasFormly/documento/:id/todo/?order=&limit=&page=&filter=& Obtiene lista de los documentos pendientes del usuario actual + + @apiDescription Get plantillasFormly/documento/:id/todo/?order=&limit=&page=&filter=&, obtiene lista de los documentos pendientes del usuario actual de acuerdo a las especificaciones de orden, límite, paginación, filtros y campos + + @apiParam (Parámetro) {Numérico} id Identificador del usuario actual + + @apiParam (Query) {Texto} order Campo por el cual se ordenará el resultado + @apiParam (Query) {Numérico} limit Cantidad de resultados a obtener + @apiParam (Query) {Numérico} page Número de página de resultados + @apiParam (Query) {Texto} filter Texto a buscar en los registros + + @apiSuccess (Respuesta) {Numérico} total Número de documentos encontrados + @apiSuccess (Respuesta) {Texto} resultado Array de documentos encontrados + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La busqueda fue exitosa", + "datos": { + "total": 5, + "resultado": [ + { + "id_documento": 62, + "nombre": "Instructivo - Juan Perez", + "nombre_plantilla": "Instructivo", + "fecha": null, + "estado": "ENVIADO", + "_fecha_creacion": "2020-01-08T22:21:14.857Z", + "_fecha_modificacion": "2020"-01-08T22:31:14.764Z + }, + ... + ] + } + } + */ + + app.get('/api/v1/plantillasFormly/documento/:id/todo', filtros,(req, res) => { + const estDoc = ['envia', 'recha', 'deriv']; + const idUsuario = req.body.audit_usuario.id_usuario; + let condiciones = {}; + let opcionesDocumento ={}; + opcionesDocumento.where= { + via_actual: idUsuario, + estado: 'DERIVADO', + }; + opcionesDocumento.attributes = ['id_documento']; + opcionesDocumento.raw=true; + if(req.query.filter!=='' && req.xfilter) opcionesDocumento.where[Op.and] = { [Op.or]:req.xfilter }; + documento.findAll(opcionesDocumento) + .then( pRespuesta => { + const promesas=[]; + pRespuesta.forEach( d => { + promesas.push(new Promise((resolve, reject) => { + documento.findOne({ attributes: ['fecha'], where:{ documento_padre: d.id_documento }, raw:true}) + .then( pResp => { + resolve( pResp==null? d.id_documento : ( (pResp && pResp.fecha===null)? d.id_documento: 0)); + }); + })); + }) + return Promise.all(promesas) + }) + .then( pRespuesta => { + opcionesDocumento={}; + opcionesDocumento.where={ + $or: [], + estado:{$ne: 'ELIMINADO'}, + }; + + condiciones = { + 'envia': { via_actual: idUsuario, estado:'ENVIADO' }, + 'recha': { _usuario_creacion: idUsuario, estado:'RECHAZADO' }, + 'deriv': { id_documento:{$in:pRespuesta || []} }, + }; + + if(req.query.filter!=='' && req.xfilter) opcionesDocumento.where.$and = { $or:req.xfilter }; + if(req.query.fields) opcionesDocumento.attributes=req.query.fields.split(','); + if(req.query.limit) opcionesDocumento.limit=req.query.limit; + if(req.query.page) opcionesDocumento.offset=(req.query.limit * ((req.query.page || 1) - 1)) || 0; + + if(req.query.estado){ + req.query.estado.split(',').forEach(it => { + if (condiciones[it]) opcionesDocumento.where.$or.push(condiciones[it]); + }); + } else { + estDoc.forEach(it => { + if (condiciones[it]) opcionesDocumento.where.$or.push(condiciones[it]); + }); + } + let order; + if(req.query.order){ + order = (req.query.order.charAt(0)=='-')? 'DESC': ''; + req.query.order = (req.query.order.charAt(0)=='-')? req.query.order.substring(1,req.query.order.length) : req.query.order; + opcionesDocumento.order = [[req.query.order, order]]; + } + return documento.findAndCountAll(opcionesDocumento) + }) + .then(pRespuesta => { + console.log('Búsqueda realizada'); + res.send(util.formatearMensaje("EXITO", "La busqueda fue exitosa", {total:pRespuesta.count,resultado:pRespuesta.rows})) + }) + .catch(pError => { + console.log('Error en la búsqueda de documentos'.red); + res.status(412).send(util.formatearMensaje("ERROR", pError)); + }) + }); + + /** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Get plantillasFormly/documento/:id/encurso + @api {get} /api/v1/plantillasFormly/documento/:id/encurso?order=&limit=&page=&filter=&fields= Obtiene lista de los documentos en curso del usuario actual + @apiDescription Get plantillasFormly/documento/:id/encurso?order=&limit=&page=&filter=&fields=, obtiene lista de los documentos en curso del usuario actual de acuerdo a las especificaciones de orden, límite, paginación, filtros y campos + + @apiParam (Parámetro) {Numérico} id Identificador del usuario actual + + @apiParam (Query) {Texto} order Campo por el cual se ordenará el resultado + @apiParam (Query) {Numérico} limit Cantidad de resultados a obtener + @apiParam (Query) {Numérico} page Número de página de resultados + @apiParam (Query) {Texto} filter Parámetros a buscar en los registros + @apiParam (Query) {Texto} fields Campos que se mostrarán en el resultado + + @apiSuccess (Respuesta) {Numérico} total Número de documentos encontrados + @apiSuccess (Respuesta) {Texto} resultado Array de documentos encontrados + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La busqueda fue exitosa", + "datos": { + "total": 2, + "resultado": [ + { + "id_documento": 62, + "nombre": "Instructivo - Juan Perez", + "nombre_plantilla": "Instructivo", + "fecha": , + "estado": "DERIVADO", + "_fecha_creacion": "2020-01-08T22:21:14.857Z", + "_fecha_modificacion": "2020"-01-08T22:31:14.764Z + }, + ... + ] + } + } + */ + + app.get('/api/v1/plantillasFormly/documento/:id/encurso', filtros,(req, res) => { + const opcionesDocumento = {}; + const idUsuario = req.body.audit_usuario.id_usuario; + + opcionesDocumento.where = { $or: [ + { via:{ $like:{ $any:[`%${idUsuario},%`,`%${idUsuario}]`] }} }, + { para:`[${idUsuario}]` }, + ]}; + opcionesDocumento.where.$or[0].estado = { $notIn:['ELIMINADO', 'CERRADO'] }; + opcionesDocumento.where.$or[1].estado = { $notIn:['ELIMINADO', 'CERRADO'] }; + opcionesDocumento.where.$or[0].grupo = { $not:null }; + opcionesDocumento.where.$or[1].grupo = { $not:null }; + opcionesDocumento.attributes = ['grupo']; + + let xdocs; + documento.findAll(opcionesDocumento) + .then(resp => { + xdocs = []; + resp.forEach( (it) => { xdocs.push(it.dataValues.grupo); }) + return documento.findAll({ + attributes: ['grupo', [sequelize.fn('COUNT', sequelize.col('grupo')), 'cant']], + where: { + grupo: { $in:xdocs }, + }, + group:['grupo'], + }) + }) + .then( resp => { + xdocs = []; + resp.forEach( (it) => { if(it.dataValues.cant!=1){ xdocs.push(it.dataValues.grupo); }}) + + if(req.query.filter!=='' && req.xfilter)opcionesDocumento.where.$or = req.xfilter; + if(req.query.fields) opcionesDocumento.attributes=req.query.fields.split(','); + if(req.query.limit) opcionesDocumento.limit=req.query.limit; + if(req.query.page) opcionesDocumento.offset=(req.query.limit * ((req.query.page || 1) - 1)) || 0; + if(req.query.order){ + const order = (req.query.order.charAt(0)=='-')? 'DESC': ''; + req.query.order = (req.query.order.charAt(0)=='-')? req.query.order.substring(1,req.query.order.length) : req.query.order; + opcionesDocumento.order = [[req.query.order, order]]; + } + opcionesDocumento.where.$or[0].grupo = { $in: xdocs }; + opcionesDocumento.where.$or[1].grupo = { $in: xdocs }; + return documento.findAndCountAll(opcionesDocumento) + }) + .then( resp => { + // resp.rows.forEach( (it) => { console.log(it.dataValues);}) + res.send(util.formatearMensaje("EXITO", "La busqueda fue exitosa", {total:resp.count,resultado:resp.rows})) + }) + .catch(pError => { + res.status(412).send(util.formatearMensaje("ERROR", pError)); + }) + }); + + /** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Get plantillasFormly/documento/:id/info + @api {get} /api/v1/plantillasFormly/documento/:id/info Obtiene la información rápida del documento + + @apiDescription Get plantillasFormly/documento/:id/info, obtiene la información rápida del documento, tipo resumen + + @apiParam (Parámetro) {Numérico} id Identificador del documento + + @apiSuccess (Respuesta) {Texto} datos Texto con la información abreviada del documento + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La busqueda fue exitosa", + "datos": "Desclasificado
    Dirigido a
    INSTRUCTIVO DE PRUEBA
    Contenido del instructivo" + } +*/ + + app.get('/api/v1/plantillasFormly/documento/:id/info', (req, res) => { + documento.findOne({ + where:{ + id_documento:req.params.id, + estado:{$ne:'ELIMINADO'}, + }, + }) + .then(pDoc => { + // Si existe el documento. + if(pDoc){ + // Parsea a objeto los valores del documento. + const v = JSON.parse(pDoc.plantilla_valor); + // informacion a retornar. + let inf=null; + // contador de valores a obtener. + let c=0; + // Campos valor a excluir. + const a= ['ccArchivo-0']; + + // Itera los valores. + for (const k in v) { + + // Si el contador es menor a 6. + if(c<6){ + // Si el valor en iteracion no esta en la lista de excluidos. + if(a.indexOf(k) == -1 ){ + // Si el valor es de tipo datosGenerales. + if(k.indexOf('datosGenerales')>-1){ + // Busca la referencia o asunto e incrementa el contador. + if(v[k].ref){ + inf = `${(inf==null)?'':inf}${(inf==null)?'':'
    '}${v[k].ref}`; + c++; + } + } + // Si el valor es de tipo editor de texto. + else if(k.indexOf('editorTexto') > -1){} + // Si el valor es de tipo checkbox. + else if(k.indexOf('checkbox') > -1){} + // Si el valor es de tipo datepicker. + else if(k.indexOf('datepicker') > -1){ + // Genera la fecha actual. + const fecha=moment(v[k]).format("DD/MM/YYYY"); + // Agrega la informacion. + inf = `${(inf==null)?'':inf}${(inf==null)?'':'
    '}${fecha}` + } + // Si el valor es de otro tipo. + else{ + if(typeof v[k] == 'string'){ + /// Agrega la informacion, actualiza el contador. + inf = `${(inf==null)?'':inf}${(inf==null)?'':'
    '}${v[k]}` + c++; + } + } + } + } + } + // Si la variable inf no ha sido modificado. + if(inf !== null){ + // Si la longitud del valor es mayor a 250 caracteres. + if(inf.length>250) inf = `${inf.substring(0,250)} .....`; + } else { + inf ='Sin información.' + } + // Reemplaza todos los saltos de linea. + inf = inf.replace(/\n/g, "
    "); + // Retorna la informacion. + return inf; + } + // Si el documento no existe + else throw new Error("El documento solicitado, no esta disponible.") + }) + .then(pDoc => + // Finaliza la peticion de manera exitosa. + res.send(util.formatearMensaje("EXITO", "La busqueda fue exitosa", pDoc)) + ) + .catch(pError => { + console.log("Error al buscar el documento"); + // Finaliza la peticion, retornando el error. + return res.status(412).send(util.formatearMensaje("ERROR", pError)); + }) + }) +/** + @apiVersion 1.0.0 + @apiGroup Documento + @apiName Delete documento + @api {delete} /api/v1/plantillasFormly/documento/:id Elimina un/a documento + + @apiDescription Delete documento + + @apiParam (Parámetro) {Numérico} id Identificador de documento que se quiere eliminar + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La eliminación fue exitosa." + } +*/ + app.delete('/api/v1/plantillasFormly/documento/:idUs/misdocumentos/:id', (req, res) => { + + if( req.params.idUs == req.body.audit_usuario.id_usuario ){ + + documento.findOne({ + where:{_usuario_creacion:req.params.id}, + }) + bl.eliminarDocumento(req.params.idUs, req.params.id, documento, historial_flujo) + .then(() => res.send(util.formatearMensaje("EXITO", "La eliminación fue exitosa."))) + .catch(pError => res.status(412).send(util.formatearMensaje("ERROR", pError))) + } else { + res.status(412).send(util.formatearMensaje("ERROR", "Usted no tiene la autorizacion.")) + } + }); + +/** + @apiVersion 1.0.0 + @apiGroup Documento + @apiName Delete documento + @api {delete} /api/v1/plantillasFormly/documento/:idUs/todo/:id Elimina un/a documento + + @apiDescription Delete documento + + @apiParam (Parámetro) {Numérico} id Identificador de documento que se quiere eliminar + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + + } + */ + app.delete('/api/v1/plantillasFormly/documento/:idUs/todo/:id', (req, res) => { + + if( req.params.idUs == req.body.audit_usuario.id_usuario ){ + + documento.findOne({ + where:{_usuario_creacion:req.params.id}, + }) + bl.eliminarDocumento(req.params.idUs, req.params.id, documento, historial_flujo) + .then(() => res.send(util.formatearMensaje("EXITO", "La eliminación fue exitosa."))) + .catch(pError => res.status(412).send(util.formatearMensaje("ERROR", pError))) + } else { + res.status(412).send(util.formatearMensaje("ERROR", "Usted no tiene la autorizacion.")) + } + }); + +/** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Put documento + @api {put} /api/v1/plantillasFormly/documento/:id Actualiza un/a documento + + @apiDescription Put documento + + @apiParam (Parámetro) {Numérico} id Identificador de documento que se quiere actualizar + + @apiParam (Petición) {Texto} nombre Nombre del documento + @apiParam (Petición) {Texto} nombre_plantilla Nombre de la planilla usada para el documento + @apiParam (Petición) {Texto} abreviacion Sigla o abreviación del documento + @apiParam (Petición) {Texto} sw Propiedades del documento + @apiParam (Petición) {Texto} plantilla Plantilla del documento + @apiParam (Petición) {Texto} plantilla_valor Valores de la plantilla + @apiParam (Petición) {Numérico} _usuario_modificacion Identificador del usuario que esta modificando + + @apiParamExample {json} Ejemplo para enviar: + { + "nombre": "INSTRUCTIVO", + "nombre_plantilla": "INSTRUCTIVO", + "abreviacion": "II", + "plantilla": "[]", + "plantilla_valor": "{}", + "sw": "{"enviado": false, "enviar": false, "es_respuesta": false}", + "_usuario_modificacion": 1 + } + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + } + + @apiSampleRequest off +*/ + app.put('/api/v1/plantillasFormly/documento/:id', (req, res) => { + let xdoc; + const msg = "La operación se realizó correctamente."; + const sw = req.body.sw || {}; + sw.xenviar = !sw.enviado && sw.enviar || false; + let flag= false; + + sequelize.transaction().then(t => { + + const tr = { transaction: t }; + + // Verifica la existencia de archivos externos, si existen los crea fisicamente en el servidor. + bl.verificarExternos(req.body,rutaExternos) + .then(pValores => { + + // Si existe la respuesta actualiza plantilla_valor. + if(pValores) req.body.plantilla_valor=pValores; + return documento.findByPk(req.params.id) + .then( resp => { + xdoc = resp; + + if(xdoc.estado == 'NUEVO' || xdoc.estado == 'RECHAZADO'){ + if(xdoc._usuario_creacion == req.body.audit_usuario.id_usuario) + return xdoc.update(req.body, tr); + else + throw new Error("Usted no tiene la autorizacion"); + } + else if(xdoc.estado == 'CERRADO' || xdoc.estado == 'DERIVADO'){ + + let flag=false; + const roles = req.body.audit_usuario.roles; + for(let i = 0; i { + if (sw.xenviar){ + return bl.verificarPartidas(partida, JSON.parse(req.body.plantilla_valor)); + } + return + }) + .then( resp => { + if(sw.xenviar && sw.es_respuesta){ + return bl.documento_crear(historial_flujo, xdoc.documento_padre, xdoc._usuario_modificacion, tr) + } + return + }) + .then( resp => { + if(sw.xenviar){ + return bl.documento_enviar(historial_flujo, xdoc, tr, director) + .then(() => { + t.commit(); + flag = true; + return notificar.enviar(modelos, xdoc,'enviado',{}) + .then(() => resp) + }) + } + return resp; + }) + }) + .then( resp => { + if(!flag) t.commit(); + res.send(util.formatearMensaje("EXITO", msg)); + }) + .catch(e => { + console.log('Revisando el error en la modificacion del documento', e); + + t.rollback(); + res.status(412).send(util.formatearMensaje("ERROR", e)); + }) + }) + + }); + + // Servicio rest de envio de documento para su aprobacion + /** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Put documento para aprobacion + @api {put} /api/v1/plantillasFormly/documento/:id/aprobar Aprobacion de un documento pendiente + + @apiDescription Put documento + + @apiParam (Parámetro) {Numérico} id Identificador de documento que se quiere aprobar + + @apiParam (Petición) {Numérico} usuario Identificador del usuario que aprueba. + @apiParam (Petición) {Boolean} derivar Parámetro que define que no es derivación. + @apiParam (Petición) {Numérico} usuario_derivar Identificador del usuario al que se deriva. Solo si derivar es true. + @apiParam (Petición) {Texto} observaciones Parámetro que define que no es derivación. Solo si derivar es true. + + @apiParamExample {json} Ejemplo para Aprobar y cerrar: + { + "usuario":1, + "derivar": false + } + + @apiParamExample {json} Ejemplo para Aprobar y derivar: + { + "usuario":1, + "derivar": true, + "observaciones": "Favor elaborar el informe", + "usuario_derivar": 7 + } + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje" : EXITO, + "mensaje" : El documento se aprobó correctamente, + "datos": {} + } + @apiSampleRequest off + */ + app.put('/api/v1/plantillasFormly/documento/:id/aprobar', (req, res) => { + // TODO: Refactorizar este metodo usando BL's para poder agregar o quitar funcionalidades en la aprobacion. + let documentoBase = null; + let esMultiple = false; + const tr = {}; + // const tr = { transaction: t }; + const idDocumento = req.params.id; + const usuarioModificacion = req.body.audit_usuario.id_usuario; + console.log(`Iniciando la aprobacionn del documento---- usuarioModificacion`, usuarioModificacion); + console.log(`Iniciando la aprobacionn del documento---- idDocumento`, idDocumento); + return modelos.documento.findByPk(idDocumento, tr) + .then(docResp => { + console.log('Revisando la obtencion del documento base para aprobar'); + + if (docResp.estado !== 'ENVIADO') throw Error("Este documento no puede ser modificado."); + if (docResp.via_actual !== usuarioModificacion) throw Error('Usted no esta autorizado para la accion solicitada.'); + documentoBase = docResp; + const para = JSON.parse(documentoBase.para)[0]; + const viaActual = documentoBase.via_actual; + const aprobarPara = (viaActual == para); + const datosAprobacion = { + derivar: req.body.derivar || false, + observaciones: req.body.observaciones || '', + director, + usuarioModificacion, + idDocumento, + viaActual, + auditUsuario: req.body.audit_usuario, + usuarioDerivar: req.body.usuario_derivar, + }; + if (docResp.multiple && docResp.multiple !== null) { + esMultiple = true; + } + if (aprobarPara && esMultiple === false) { + console.log('Es aprobacion SIMPLE'); + return bl.aprobarPara(modelos, documentoBase, datosAprobacion, req); + } + else if (aprobarPara && esMultiple === true) { + console.log('Es aprobacion MULTIPLE'); + return bl.aprobarParaMultiple(modelos, documentoBase, datosAprobacion, req); + } + else { + console.log('Es aprobacion VIA'); + + return bl.aprobarVia(modelos, documentoBase, datosAprobacion, tr); + } + }) + .then(() => { + console.log('fin flujo'); + // lel + // t.commit(); + return res.send(util.formatearMensaje("EXITO", "El documento se aprobó correctamente", {})); + }) + .catch(error => { + console.log('Error en la aprobacion del documento', error); + // t.rollback(); + res.status(412).send(util.formatearMensaje("ERROR", error)); + }); + }); + + /** + @apiVersion 1.0.0 + @apiGroup Documento + @apiName Put documento/:id/derivar + @api {put} /api/v1/plantillasFormly/documento/:id/derivar Deriva un documento + + @apiDescription Put para plantillasFormly/documento/:id/derivar Deriva un documento, realizando las actualizaciones necesarias + + @apiParam (Parámetro) {Numérico} id Identificador del documento a derivar + + @apiParam (Petición) {Numérico} usuario Identificador del usuario actual + @apiParam (Petición) {Numérico} destino Identificador del usuario destino + @apiParam (Petición) {Texto} obsrvaciones Texto con el que se hace la dervación (Proveído) + + @apiParamExample {json} Ejemplo para enviar: + { + "usuario":12, + "destino":11, + "observaciones":"derivando a ..." + } + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje":"EXITO", + "mensaje":"El documento se derivó" + } + + @apiSampleRequest off + + */ + + app.put('/api/v1/plantillasFormly/documento/:id/derivar', (req, res) => { + const idDocumento = req.params.id; + const usuarioModificacion = req.body.audit_usuario.id_usuario; + // const usuarioModificacion = req.body.usuario; + const destino = req.body.destino; + + const datos={ + via_actual: destino, + observaciones:req.body.observaciones, + estado : 'DERIVADO', + _usuario_modificacion: usuarioModificacion, + } + let doc = null; + documento.findByPk(idDocumento).then(pDoc => { + doc = pDoc; + if(doc.via_actual !== usuarioModificacion) throw new Error("Usted no esta autorizado para la accion solicitada."); + if(doc.estado !== 'DERIVADO') throw new Error("El documento no puede ser modificado."); + return documento.findOne({ where:{ documento_padre:doc.id_documento } }) + }) + .then(resultado => { + if(resultado==null) return bl.actualizarDocumento(doc,datos,historial_flujo); + else throw new Error("El documento no se puede derivar, porque ya creó una respuesta."); + }) + .then(resultado => notificar.enviar(modelos, doc, 'derivado', {})) + .then(resultado => { + res.send(util.formatearMensaje("EXITO", "El documento se derivó", resultado)); + }).catch(error => { + console.log('Error en la derivacion', error); + res.status(412).send(util.formatearMensaje("ERROR", error)); + }); + }); + + //Servicio rest para rechazar documento + /** + @apiVersion 1.0.0 + @apiGroup Documento + @apiName Put rechazar documento + @api {put} /api/v1/plantillasFormly/documento/:id/rechazar Observación de un documento pendiente + + @apiDescription Put documento , Rechaza un documento con una observación, para que el emisor lo corrija + + @apiParam (Parámetro) {Numérico} id Identificador de documento que se quiere rechazar + + @apiParam (Petición) {Numérico} usuario Identificador del usuario que rechaza + @apiParam (Petición) {Texto} observaciones Observaciones al documento + @apiParam (Petición) {Texto} observado_por Información de quien rechaza el documento + + @apiParamExample {json} Ejemplo para enviar: + { + "usuario" : 1, + "observaciones" : "Este informe no contiene informacion alguna", + "observado_por" : "AGETIC AGETIC" + } + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "El documento se rechazó" + } + @apiSampleRequest off + */ + + app.put('/api/v1/plantillasFormly/documento/:id/rechazar', (req, res) => { + const idDocumento = req.params.id; + const usuarioModificacion = req.body.audit_usuario.id_usuario; + // const usuarioModificacion = req.body.usuario; + const observaciones = req.body.observaciones; + const observadoPor = req.body.observado_por; + let usuarioNotificar = null; + let doc=null; + sequelize.transaction().then(t => { + const tr = { transaction: t }; + documento.findByPk(idDocumento).then(doc => { + + if(usuarioModificacion !== doc.via_actual) throw new Error("Usted no cuenta con la autorizacion"); + if(doc.estado!=='ENVIADO') throw new Error("El documento no puede ser modificado"); + + return doc.update({ + estado : 'RECHAZADO', + observaciones : `Observado por: ${observadoPor} - Observaciones: ${observaciones}`, + _usuario_modificacion: usuarioModificacion, + }, + {where: {id_documento: idDocumento}}, + tr) + }) + .then(docum => { + doc=docum.dataValues; + usuarioNotificar=docum.dataValues._usuario_creacion; + return historial_flujo.create({ + id_documento:docum.id_documento, + accion: 'RECHAZADO', + observacion: docum.observaciones, + estado: 'ACTIVO', + _usuario_creacion: usuarioModificacion, + },tr) + }) + .then(() => + notificar.enviar(modelos, doc,'observado',tr) + .then(pRespuesta => { + console.log("Notificacion enviada"); + return + }) + ) + .then(() => { + t.commit(); + res.send(util.formatearMensaje("EXITO", "El documento se rechazó")); + }).catch(error => { + t.rollback(); + res.status(412).send(util.formatearMensaje("ERROR", error)); + }); + }); + }); + +/** + @apiVersion 1.0.0 + @apiGroup Documento + @apiName Options documento + @api {options} /api/v1/plantillasFormly/documento Extrae formly de documento + + @apiDescription Options de documento + + @apiSuccess (Respuesta) {Texto} key Llave para el campo + @apiSuccess (Respuesta) {Texto} type Tipo de etiqueta este puede ser input, select, datepicker, etc + @apiSuccess (Respuesta) {Objeto} templateOptions Objeto de opciones para la etiqueta, el cual varia de acuerdo el tipo de etiqueta + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + [ + { + "key": "id_documento", + "type": "input", + "templateOptions": { + "type": "number", + "label": "ID", + "required": true + } + }, + { + "key": "nombre", + "type": "input", + "templateOptions": { + "type": "text", + "label": "Nombre", + "required": true + } + }, + { + "key": "plantilla", + "type": "textarea", + "templateOptions": { + "type": "", + "label": "Plantilla", + "required": true + } + }, + { + "key": "plantilla_valor", + "type": "textarea", + "templateOptions": { + "type": "", + "label": "Valores", + "required": true + } + }, + { + "key": "estado", + "type": "select", + "templateOptions": { + "type": "", + "label": "Estado", + "required": false, + "options": [ + { + "name": "ACTIVO", + "value": "ACTIVO" + }, + { + "name": "INACTIVO", + "value": "INACTIVO" + } + ] + } + }, + { + "key": "_usuario_creacion", + "type": "input", + "templateOptions": { + "type": "number", + "label": "Usuario de creación", + "required": true + } + }, + { + "key": "_usuario_modificacion", + "type": "input", + "templateOptions": { + "type": "number", + "label": "Usuario de modificación", + "required": false + } + }, + { + "key": "_fecha_creacion", + "type": "datepicker", + "templateOptions": { + "type": "datetime-local", + "label": "_fecha_creacion", + "required": true + } + }, + { + "key": "_fecha_modificacion", + "type": "datepicker", + "templateOptions": { + "type": "datetime-local", + "label": "_fecha_modificacion", + "required": true + } + } + ] + + @apiSampleRequest off +*/ + + + app.options('/api/v1/plantillasFormly/documento', sequelizeFormly.formly(documento, app.src.db.models)); + app.options('/api/v1/plantillasFormly/documento/:id/todo', sequelizeFormly.formly(documento, app.src.db.models)); + app.options('/api/v1/plantillasFormly/documento/:id/misdocumentos', sequelizeFormly.formly(documento, app.src.db.models)); + app.options('/api/v1/plantillasFormly/documento/:id/encurso', sequelizeFormly.formly(documento, app.src.db.models)); + +}; diff --git a/src/routes/plantillasFormly/firmadoRT.js b/src/routes/plantillasFormly/firmadoRT.js new file mode 100644 index 0000000..1864805 --- /dev/null +++ b/src/routes/plantillasFormly/firmadoRT.js @@ -0,0 +1,411 @@ +const fs = require('fs'); +const _ = require('lodash'); +const Uuid = require('uuid'); +const sequelizeFormly = require("sequelize-formly"); + + +module.exports = app => { + const bl = require('../../bl/plantillasFormly/documentoBL'); + const blFirmado = require('../../bl/plantillasFormly/firmadoBL'); + const Config = app.src.config.config; + const Util = app.src.lib.util; + const FirmaUtil = app.src.lib.firma; + const Archivo = app.src.lib.archivos; + const Documento = app.src.db.models.documento; + const Firma = app.src.db.models.firma; + const Usuario = app.src.db.models.usuario; + const HistorialFlujo = app.src.db.models.historial_flujo; + const rutaExternos = app.src.config.config.host; + const dirDocumento = app.src.config.config.ruta_documentos; + const Modelos = app.src.db.models; + const Op = app.src.db.Sequelize.Op; + + /** + @apiVersion 1.0.0 + @apiGroup Documento + @apiName Post firmar + @api {post} /api/v1/documento/firmado Guardar documento firmado + + @apiDescription Post para documento firmado + + @apiParam (Petición) {Base64} base64 Documento firmado digitalmente a guardar. + @apiParam (Petición) {Numérico} id_documento Identificador del documento firmado. + + @apiParamExample {json} Ejemplo para enviar: + { + "base64": "", + "id_documento": 123456 + } + + @apiSuccess (Respuesta) {Texto} tipoMensaje Indica el tipo de mensaje de respuesta obtenido. + @apiSuccess (Respuesta) {Texto} mensaje Describe el estado de la solicitud + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Documento firmado correctamente." + } + + @apiSampleRequest off + */ + app.post('/api/v1/documento/firmado', (req,res) => { + let usuarioFirmante = req.body.audit_usuario.id_usuario; + const estadosValidos = ['CERRADO', 'DERIVADO']; + let documento= null; + let datos = {}; + let firmantes = []; + let firmanteValido = true; + let documentoInstancia = null; + Documento.findOne({ + where: { + firmante_actual: usuarioFirmante, + id_documento: req.body.id_documento + } + }) + .then(documentoResp => { + if(!documentoResp) throw Error('Usted no esta autorizado a firmar el documento.'); + documento = documentoResp.dataValues; + documentoInstancia = documentoResp; + let firmaron = documento.firmaron || []; + firmantes = JSON.parse(documento.de).concat(JSON.parse(documento.via)).concat(JSON.parse(documento.para)); + if (documento.firmaron === null) documento.firmaron = []; + // if(documento.firmaron.indexOf(usuarioFirmante) > -1 ) throw new Error('Usted ya firmo el documento'); + if(documento.firmaron.indexOf(usuarioFirmante) > -1 ) { + datos = bl.validarYaFirmo(firmantes, documento.firmaron, usuarioFirmante); + firmanteValido = false; + return; + } + if(estadosValidos.indexOf(documento.estado) === -1) throw new Error('El documento aun no puede ser firmado por su estado.'); + let firmanteActual= null; + if(firmantes.indexOf(usuarioFirmante) === -1 ) { + + if(firmaron.length === 0) { + firmanteActual = firmantes[0]; + } + else { + let faltantes = _.xor(firmaron, firmantes); + firmanteActual = faltantes[0]; + } + + datos = { firmante_actual: firmanteActual, firmaron }; + firmanteValido = false; + return; + } + + if(firmaron.length === 0) firmaron.push(usuarioFirmante); + else firmaron.push(usuarioFirmante); + + let indiceFirmante = firmantes.indexOf(usuarioFirmante); + let nuevoFirmante = null; + if(indiceFirmante < firmantes.length -1) { + firmanteActual = firmantes[indiceFirmante+1]; + } + datos = { firmante_actual: firmanteActual, firmaron }; + + if(indiceFirmante === firmantes.length -1) { + datos.firmado = true; + } + return; + + }) + .then(() => { + if(firmanteValido === false) return; + const nombre_privado= Util.formatoNombreDoc(documento.nombre); + const nombreDocumento = `${Util.formatoNombreDoc(documento.nombre)}.pdf`; + return Archivo.guardarFirmado(dirDocumento, new Buffer(req.body.base64, "base64"), nombreDocumento, true); + }) + .then(() => documentoInstancia.update(datos)) + .then(() => { + if(firmanteValido === false) return; + return HistorialFlujo.create({ + id_documento: documento.id_documento, + accion:'FIRMO', + observacion:'', + estado: 'ACTIVO', + _usuario_creacion: usuarioFirmante + }); + }) + .then(() => { + return bl.obtenerCrearHash(documento, req); + }) + .then(hash => bl.actualizarFirmaHash(Modelos, hash, documento, usuarioFirmante)) + .then( () => { + + res.status(200).send(Util.formatearMensaje('EXITO', 'Documento firmado correctamente.')); + }) + .catch(error => { + console.log("Error al escribir el documento firmado", error); + res.status(412).send(Util.formatearMensaje('ERROR', error)); + }); + }); + + /** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Get documento/firmar + @api {get} /api/v1/documento/firmar Obtiene los documentos a firmar + + @apiDescription Get documento, obtiene los documentos a firmar + @apiParam (Parámetro) {Texto} order Campo por el cual se ordenara + @apiParam (Parámetro) {Numérico} limit Establece el limite de resultados a obtener + @apiParam (Parámetro) {Numérico} page Define la pagina de resultados a obtener + @apiParam (Parámetro) {Texto} fields Campos a obtener + @apiParam (Parámetro) {Texto} filter Parametro de busqueda + + + @apiSuccess (Respuesta) {Numérico} id_documento Identificador de documento + @apiSuccess (Respuesta) {Texto} nombre Nombre del documento + @apiSuccess (Respuesta) {Texto} nombre_plantilla Nombre de la plantilla base del documento + @apiSuccess (Respuesta) {Texto} plantilla Plantilla del documento + @apiSuccess (Respuesta) {Texto} plantilla_valor Valores de la plantilla + @apiSuccess (Respuesta) {FechaHora} fecha Fecha y hora de aprobación + @apiSuccess (Respuesta) {Texto} estado Estado del registro + @apiSuccess (Respuesta) {Texto} impreso Si el documento fue o no impreso + @apiSuccess (Respuesta) {Boolean} firmado Si el documento está o no firmado + @apiSuccess (Respuesta) {Array} firmaron Usuarios que firmaron el documento + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario modificador + @apiSuccess (Respuesta) {FechaHora} _fecha_creacion Fecha de creación de documento + @apiSuccess (Respuesta) {FechaHora} _fecha_modificacion Fecha de modificación de documento + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La busqueda fue exitosa", + "datos": { + "total": 2, + "resultado": [ + { + "id_documento": 12345, + "nombre": "MiSistema/SS/00002/2018", + "nombre_plantilla": "Solicitud de Salidas", + "fecha": "2018-03-19T13:40:46.000Z", + "estado": "DERIVADO", + "impreso": "NO", + "_fecha_creacion": "2018-03-19T13:39:28.193Z", + "_fecha_modificacion": "2018-03-19T13:40:46.702Z", + "_usuario_creacion": 1, + "firmantes": [ + 1, + 101 + ], + "firmaron": null + }, + { + "id_documento": 23590, + "nombre": "MiSistema/RSPO/00002/2018", + "nombre_plantilla": "Requerimiento de Servicios Personales y Otros", + "fecha": "2018-02-28T23:32:51.000Z", + "estado": "CERRADO", + "impreso": "NO", + "_fecha_creacion": "2018-02-28T13:04:46.616Z", + "_fecha_modificacion": "2018-02-28T23:32:51.224Z", + "_usuario_creacion": 35, + "firmantes": [ + 35 + ], + "firmaron": null + } + ] + } + } + */ + app.get('/api/v1/documento/firmar', filtros, (req, res) => { + let order; + const usuario = req.body.audit_usuario.id_usuario; + const estadosValidos = ['CERRADO', 'DERIVADO']; + const opcionesDocumento = { + attributes: ['id_documento', 'nombre', 'nombre_plantilla', 'fecha', 'estado', 'impreso', '_fecha_creacion', '_fecha_modificacion', '_usuario_creacion', 'firmado', 'firmaron'], + where: { + firmante_actual: usuario, + estado: { [Op.in]: estadosValidos}, + firmado: false + } + }; + + if(req.query.limit) opcionesDocumento.limit=req.query.limit; + if(req.query.page) opcionesDocumento.offset=(req.query.limit * ((req.query.page || 1) - 1)) || 0; + if(req.query.order) { + order = (req.query.order.charAt(0)=='-')? 'DESC': ''; + req.query.order = (req.query.order.charAt(0)=='-')? req.query.order.substring(1,req.query.order.length) : req.query.order; + opcionesDocumento.order = [[req.query.order, order]]; + } + if(req.query.filter) { + opcionesDocumento.where[Op.or] = req.xfilter; + } + Documento.findAndCountAll(opcionesDocumento) + .then(resp => { + res.send(Util.formatearMensaje("EXITO", "La busqueda fue exitosa", {total:resp.count,resultado:resp.rows})); + }) + .catch(error => { + console.log("Error en la obtención de documento para firmar", error); + res.status(412).send(Util.formatearMensaje('ERROR', error)); + }); + }); + + function filtros (req,res,next){ + if(req.query.filter!='') + Util.consulta(req,res,next,Documento); + else next(); + } + + /** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Post Documento para firmar + @api {post} /api/v1/documento/firmar Obtener pdf válido para firma + + @apiDescription Post para obtener un documento válido para firma + + @apiParam (Petición) {Texto} cite Cite del documento a firmar + @apiParam (Petición) {Numérico} id_documento Identificador del documento que se desea firmar + + @apiParamExample {json} Ejemplo para enviar: + { + "cite":"AGETIC/SS/0002/2020", + "id_documento":86281 + } + + @apiSuccess (Respuesta) {Base64} Documento pdf a ser firmado en base 64 + + @apiSuccessExample {Base64} Respuesta del Ejemplo: + HTTP/1.1 200 OK + "JVBERi0xL......" + + @apiSampleRequest off + */ + + app.post('/api/v1/documento/firmar', (req,res) => { + if(!req.body.cite) return res.status(412).send(Util.formatearMensaje('ERROR', 'Es necesario que proporcione el cite del documento.')); + if(!req.body.id_documento) return res.status(412).send(Util.formatearMensaje('ERROR', 'Es necesario que proporcione el identificador del documento.')); + + const nombre= req.body.cite.substr(0,req.body.cite.indexOf('.pdf')); + const usuarioPeticion = req.body.audit_usuario; + const msg = "Usted no esta autorizado para ver este documento."; + let dirArch = '.'; + let enFirma = false; + let nombreDocumento; + let documento; + Documento.findOne({ + attributes: ['id_documento', 'nombre', 'firmado', 'firmaron', 'plantilla', 'plantilla_valor', 'grupo', 'anulado'], + where: { + id_documento: req.body.id_documento, + firmante_actual: usuarioPeticion.id_usuario, + estado: { [Op.in]: ['CERRADO', 'DERIVADO']} + }, + include:[ + { + model: Firma, + as: 'firma', + required: false + } + ] + }) + .then(documentoResp => { + if(!documentoResp) throw new Error('El documento solicitado no esta disponible para usted.'); + + documento = documentoResp; + nombreDocumento = `${Util.formatoNombreDoc(documento.dataValues.nombre)}`; + dirArch += `/public/documentos/${nombreDocumento}.pdf`; + if (!documento.dataValues.firma) return bl.crearCodigoFirma(Modelos, documento.dataValues, req); + return documento.dataValues.firma.dataValues.codigo; + }) + // .then(codigo => { // Removido por el problema de saturacion de la libreria html-pdf... + // const datos = { + // doc: { + // nombre: nombreDocumento, + // plantilla: documento.plantilla, + // }, + // form_actual: Util.dataToView(JSON.parse(documento.plantilla), JSON.parse(documento.plantilla_valor)), + // model_actual: JSON.parse(documento.plantilla_valor), + // audit_usuario: req.body.audit_usuario, + // host: rutaExternos, + // grupo: documento.grupo, + // codigo, + // }; + + // datos.model_actual['cite-0'].fecha = Util.formatearFecha(datos.model_actual['cite-0'].fecha); + // console.log('Revisando los datos para la firma', documento.dataValues.anulado); + + // if((Array.isArray(documento.firmaron) && documento.firmaron.length > 0) || documento.anulado== true) return; + // return Util.generarDocumento(datos, true); + // }) + .then(() => { + const documentoExiste =fs.existsSync(dirArch); + if(!documentoExiste || documentoExiste === false) throw Error('No se pudo obtener el documento a firmar.'); + return fs.readFile(dirArch, (error, data) => { + if(error) { + throw Error(process.env.NODE_ENV==='production'?'No se pudo obtener el documento a firmar.': error); + } + return res.send(data); + }); + }) + .catch(error => { + console.log("Error en la busqueda del documento", error, req.body); + res.status(412).send(Util.formatearMensaje('ERROR', error)); + }); + }); + + /** + @apiVersion 2.0.0 + @apiGroup Documento + @apiName Get documento/firmado/:id + @api {get} /api/v1/documento/firmado/:id Obtiene información de las firmas del documento + + @apiDescription Get documento/firmado/:id, obtiene información de las firmas del documento + + @apiParam (Parámetro) {Numérico} id Identificador del documento + + @apiSuccess (Respuesta) {Texto} tipoMensaje Texto que define el éxito de la petición + @apiSuccess (Respuesta) {Texto} mensaje Texto detallado del resultado de la petición + @apiSuccess (Respuesta) {Array} datos Array de firmas + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Firmas obtenidas correctamente.", + "datos": [] + } + */ + + app.get('/api/v1/documento/firmado/:id', (req,res) => { + const dirDocumento = app.src.config.config.ruta_documentos; + const usuarioPeticion = req.body.audit_usuario; + + let nombreDocumento = null; + let usuarios = []; + Documento.findOne({ + attributes: ['id_documento', 'nombre', 'firmado', 'firmaron', 'de', 'via', 'para'], + where: { id_documento : req.params.id }, + }) + .then(documento => { + if(!documento) return ([]); + nombreDocumento = `${Util.formatoNombreDoc(documento.nombre)}.pdf`; + const firmantes = JSON.parse(documento.de).concat(JSON.parse(documento.via)).concat(JSON.parse(documento.para)); + return Usuario.findAll({ + attributes: ['id_usuario', 'numero_documento', 'nombres', 'apellidos'], + where: { id_usuario: { [Op.in]: firmantes}}, + }); + }) + .then((usuariosResp = []) => { + usuarios = usuariosResp; + return FirmaUtil.obtenerFirmas(`${dirDocumento}${nombreDocumento}`); + }) + .then((data) => { + const firmas = data.data || []; + return blFirmado.procesarFirmas(usuarios, firmas); + }) + .then((filtrado = []) => { + res.send(Util.formatearMensaje('EXITO', 'Firmas obtenidas correctamente.', filtrado.reverse())); + }) + .catch(e => { + res.status(412).send(Util.formatearMensaje('ERROR', e)); + }); + }); + + app.options('/api/v1/documento/firmar', sequelizeFormly.formly(Documento, app.src.db.models)); + +}; diff --git a/src/routes/plantillasFormly/historial_flujoRT.js b/src/routes/plantillasFormly/historial_flujoRT.js new file mode 100644 index 0000000..b09372d --- /dev/null +++ b/src/routes/plantillasFormly/historial_flujoRT.js @@ -0,0 +1,388 @@ +const sequelizeHandlers = require("sequelize-handlers"); +const sequelizeFormly = require("sequelize-formly"); + +module.exports = app => { + + const documento = app.src.db.models.documento; + const unidad = app.src.db.models.unidad; + const usuario = app.src.db.models.usuario; + const correlativo = app.src.db.models.correlativo; + const historial_flujo = app.src.db.models.historial_flujo; + const util = require('../../lib/util') + const Op = app.src.db.Sequelize.Op; + + /** + @apiVersion 2.0.0 + @apiGroup Historial Flujo + @apiName Get historialFlujo/:id/ultimo + @api {get} /api/v1/historialFlujo/:id/ultimo Obtiene el último usuario + + @apiDescription Get historialFlujo/:id/ultimo, obtiene el último usuario que intervino en el historial + + @apiParam (Parámetro) {Numérico} id Identificador del documento + + @apiSuccess (Respuesta) {Texto} nombres Nombres del último usuario + @apiSuccess (Respuesta) {Texto} apellidos Apellidos del último usuario + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Historial de flujo de un documento", + "datos": { + "nombres":"Oso", + "apellidos":"Pardo", + } + } + */ + + app.get('/api/v1/historialFlujo/:id/ultimo', (req, res) => { + const idDocumento = req.params.id; + let tipoError = 'ERROR'; + + historial_flujo.findAll({ + where: { + id_documento: idDocumento, + estado: 'ACTIVO', + }, + order: [['_fecha_creacion','DESC']], + }) + .then((hist) => { + if(hist && hist[0]){ + return usuario.findByPk(hist[0]._usuario_creacion) + }else { + tipoError = 'ADVERTENCIA'; + throw new Error('El documento no tiene historial'); + } + }) + .then((usu) => { + res.send(util.formatearMensaje("EXITO", "Historial de flujo de un documento", { + nombres: usu.dataValues.nombres, + apellidos: usu.dataValues.apellidos, + })); + }) + .catch(error => + res.status(412).send(util.formatearMensaje(tipoError, error)) + ); + }) + + /** + @apiVersion 2.0.0 + @apiGroup Historial Flujo + @apiName Get historialFlujo/:id + @api {get} /api/v1/historialFlujo/:id Obtiene el historial del documento + + @apiDescription Get historialFlujo/:id, obtiene el historial completo de un documento + + @apiParam (Parámetro) {Numérico} id Identificador del documento + + @apiSuccess (Respuesta) {Numérico} id_historial_flujo Identificador del resgistro en historial_flujo + @apiSuccess (Respuesta) {Numérico} id_documento Identificador del documento + @apiSuccess (Respuesta) {Texto} accion Acción que se haya o esté realizando en el documento + @apiSuccess (Respuesta) {Texto} observacion Observación sobre el documento + @apiSuccess (Respuesta) {Texto} estado Estado del documento + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario de creación del hito + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario que modificó el hito + @apiSuccess (Respuesta) {Texto} _fecha_creacion Fecha y hora de creación del hito + @apiSuccess (Respuesta) {Texto} _fecha_modificacion Fecha y hora de modificación del hito + @apiSuccess (Respuesta) {Texto} tipo_doc Nombre de la plantilla del documento que forma parte del hito + @apiSuccess (Respuesta) {Texto} cite Cadena que identifica a un documento. + @apiSuccess (Respuesta) {Texto} nombres Nombres del usuario protagonista del hito + @apiSuccess (Respuesta) {Texto} usuario Nombre de usuario del protagonista del hito + @apiSuccess (Respuesta) {Objeto} derivado Usuario a quien se ha derivado + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Historial de flujo de un documento", + "datos":[ + { + "_fecha_creacion":"1991-01-01T14:20:43.914Z", + "_fecha_modificacion":"1991-01-01T14:20:43.914Z", + "accion":"REVISANDO", + "estado":"ACTIVO", + "id_documento":0, + "id_historial_flujo":-1, + "nombres":"Juana de Arco", + "observacion":"", + "usuario":"jarco" + }, + { + "id_historial_flujo":123, + "id_documento":62, + "accion":"ENVIADO", + "observacion":"", + "estado":"ACTIVO", + "_usuario_creacion":3, + "_usuario_modificacion":null, + "_fecha_creacion":"1991-01-01T14:20:43.914Z", + "_fecha_modificacion":"1991-01-01T14:20:43.914Z", + "tipo_doc":"Solicitud de Salidas", + "nombres":"Juan Perez", + "usuario":"jperez" + } + ] + } +*/ + app.get('/api/v1/historialFlujo/:id', (req, res) => { + const idDocumento = req.params.id; + const resultado = {detalle: idDocumento}; + let xdoc, xdocs; + let tipoError = 'ERROR'; + documento.findByPk(idDocumento) + .then( doc => { + xdoc = doc; + return historial_flujo.findAll({ + where: { + id_documento: idDocumento, + estado: 'ACTIVO', + }, + order: [['_fecha_creacion','DESC']], + }); + }) + .then((doc) => { + + if (doc != null && doc.length > 0) { + const promesas = []; + doc.forEach((pItem, pIndice) => { + if(['CERRADO','DERIVADO','CREADO'].indexOf(pItem.accion)!=-1){ + pItem.dataValues.cite = xdoc.nombre; + } + pItem.dataValues.tipo_doc = xdoc.nombre_plantilla; + promesas.push(new Promise((resolve, reject) => + usuario.findByPk(pItem._usuario_creacion) + .then(pUsuario => { + pItem.dataValues.nombres = `${pUsuario.nombres} ${pUsuario.apellidos}`; + pItem.dataValues.usuario = pUsuario.usuario; + resolve(pItem); + }) + .catch(e => reject(e)) + )); + }) + return Promise.all(promesas); + } + + }) + .then(doc => { + if(doc){ + xdocs = doc; + if( doc[0].accion=='RECHAZADO' ) + return usuario.findByPk(xdoc._usuario_creacion); + return usuario.findByPk(xdoc.via_actual); + }else { + tipoError = 'ADVERTENCIA'; + throw new Error('El documento no tiene historial'); + } + }) + .then(usu => { + if( ['CERRADO','CREADO'].indexOf(xdocs[0].accion)==-1 ){ + xdocs.unshift({ + _fecha_creacion: xdocs[0]._fecha_creacion, + _fecha_modificacion: xdocs[0]._fecha_creacion, + accion: "REVISANDO", + estado: "ACTIVO", + id_documento: 314, + id_historial_flujo: -1, + nombres: `${usu.nombres} ${usu.apellidos}`, + observacion: "", + usuario: usu.usuario, + }); + } + res.send(util.formatearMensaje("EXITO", "Historial de flujo de un documento", xdocs)) + }) + .catch(error => + res.status(412).send(util.formatearMensaje(tipoError, error)) + ); + }); + + /** + @apiVersion 2.0.0 + @apiGroup Historial Flujo + @apiName Get historialFlujo/:id/proceso + @api {get} /api/v1/historialFlujo/:id/proceso Obtiene el historial del proceso iniciado con el documento + + @apiDescription Get historialFlujo/:id/proceso, obtiene el historial del proceso iniciado con el documento, es decir el historial del flujo que haya seguido el documento. + + @apiParam (Parámetro) {Numérico} id Identificador del documento + + @apiSuccess (Respuesta) {Numérico} id_historial_flujo Identificador del resgistro en historial_flujo + @apiSuccess (Respuesta) {Numérico} id_documento Identificador del documento + @apiSuccess (Respuesta) {Texto} accion Acción que se haya o esté realizando en el documento + @apiSuccess (Respuesta) {Texto} observacion Observación sobre el documento + @apiSuccess (Respuesta) {Texto} estado Estado del documento + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario de creación del hito + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario que modificó el hito + @apiSuccess (Respuesta) {Texto} _fecha_creacion Fecha y hora de creación del hito + @apiSuccess (Respuesta) {Texto} _fecha_modificacion Fecha y hora de modificación del hito + @apiSuccess (Respuesta) {Texto} tipo_doc Nombre de la plantilla del documento que forma parte del hito + @apiSuccess (Respuesta) {Texto} cite Cadena que identifica a un documento. + @apiSuccess (Respuesta) {Texto} nombres Nombres del usuario protagonista del hito + @apiSuccess (Respuesta) {Texto} usuario Nombre de usuario del protagonista del hito + @apiSuccess (Respuesta) {Objeto} derivado Usuario a quien se ha derivado + + @apiSuccessExample {json} Respuesta: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Historial de flujo de un proceso", + "datos":[ + { + "_fecha_creacion":"1991-01-01T14:20:43.914Z", + "_fecha_modificacion":"1991-01-01T14:20:43.914Z", + "accion":"REVISANDO", + "estado":"ACTIVO", + "id_documento":0, + "id_historial_flujo":-1, + "nombres":"Juana de Arco", + "observacion":"", + "usuario":"jarco" + }, + { + "id_historial_flujo":123, + "id_documento":62, + "accion":"ENVIADO", + "observacion":"", + "estado":"ACTIVO", + "_usuario_creacion":3, + "_usuario_modificacion":null, + "_fecha_creacion":"1991-01-01T14:20:43.914Z", + "_fecha_modificacion":"1991-01-01T14:20:43.914Z", + "tipo_doc":"Solicitud de Salidas", + "nombres":"Juan Perez", + "usuario":"jperez" + } + ] + } +*/ + + app.get('/api/v1/historialFlujo/:id/proceso', (req, res) => { + console.log('Iniciando la obtencion del flujo PROCESO'.bgGreen); + const historial =[]; + let tipoError ='ERROR'; + let docs; + let adocs; + let documentoPrincipal = null; + // Obtiene todos los documentos del grupo solicitado. + documento.findByPk(req.params.id) + .then(pResultadoDocumento => { + if(!pResultadoDocumento || pResultadoDocumento.dataValues.grupo === null) { + tipoError = 'ADVERTENCIA'; + throw new Error('No existe el documento solicitado.'); + } + documentoPrincipal = pResultadoDocumento.dataValues; + return documento.findAll({ + attributes:['id_documento', 'nombre', 'nombre_plantilla', '_usuario_creacion', 'via_actual'], + where:{ grupo:pResultadoDocumento.dataValues.grupo }, + order: [['_fecha_creacion','DESC']], + }); + }) + .then(pResultado => { + docs = []; + adocs = {}; + pResultado.forEach( doc => { + adocs[doc.dataValues.id_documento] = doc.dataValues; + docs.push(doc.dataValues.id_documento); + }); + + if(pResultado.length>0){ + return historial_flujo.findAll({ + where:{ + id_documento:{ [Op.or]:{ [Op.in]:docs } }, + }, + order:[['_fecha_creacion','DESC']], + }); + } + else{ + tipoError = 'ADVERTENCIA'; + throw new Error('No existe el proceso solicitado.'); + } + + }) + .then(pResultado => { + + if(pResultado.length>0){ + const historicos = pResultado.map(pItem => { + if(['FIRMO','CERRADO','DERIVADO','CREADO','ANULADO'].indexOf(pItem.accion)!=-1){ + pItem.dataValues.cite = adocs[pItem.dataValues.id_documento].nombre; + } + pItem.dataValues.tipo_doc = adocs[pItem.dataValues.id_documento].nombre_plantilla; + return usuario.findByPk(pItem.dataValues._usuario_creacion) + .then(pUsuario => { + pItem.dataValues.nombres = `${pUsuario.nombres} ${pUsuario.apellidos}`; + pItem.dataValues.usuario = pUsuario.usuario; + }) + .then(() => { + if(pItem.accion === 'DERIVADO') { + return documento.findOne({ + attributes: ['id_documento', 'via_actual'], + where: { id_documento: pItem.dataValues.id_documento} + }) + .then(pRespDoc => usuario.findByPk(pRespDoc.via_actual)) + .then(pUsuario => { + pItem.dataValues.derivado = { + nombres: `${pUsuario.nombres} ${pUsuario.apellidos}`, + usuario: pUsuario.usuario + }; + }); + } + if(pItem.accion === 'ANULADO') { + + return usuario.findByPk(pItem.dataValues._usuario_modificacion) + .then(pUsuario => { + pItem.dataValues.aprobado = { + nombres: `${pUsuario.nombres} ${pUsuario.apellidos}`, + usuario: pUsuario.usuario + }; + }); + } + }) + .then(() => Promise.resolve(pItem)) + .catch(pError => Promise.reject(pError)); + }); + + return Promise.all(historicos); + } + else{ + tipoError = 'ADVERTENCIA'; + throw new Error('El documento no tiene historial'); + } + }) + .then(pResultado => { + if(pResultado){ + docs = pResultado; + if( docs[0].accion=='RECHAZADO' || docs[0].accion=='ELIMINADO') + return usuario.findByPk(adocs[docs[0].id_documento]._usuario_creacion); + return usuario.findByPk(adocs[docs[0].id_documento].via_actual); + } else { + tipoError = 'ADVERTENCIA'; + throw new Error('El documento no tiene historial'); + } + }) + .then(usu => { + if(documentoPrincipal.firmaron === null || documentoPrincipal.firmaron.length ===0) { + + if( ['CERRADO','CREADO'].indexOf(docs[0].accion) === -1 ){ + docs.unshift({ + _fecha_creacion: docs[0]._fecha_creacion, + _fecha_modificacion: docs[0]._fecha_creacion, + accion: "REVISANDO", + estado: "ACTIVO", + id_documento: 0, + id_historial_flujo: -1, + nombres: `${usu.nombres} ${usu.apellidos}`, + observacion: "", + usuario: usu.usuario + }); + } + } + res.send(util.formatearMensaje("EXITO", "Historial de flujo de un proceso", docs)); + }) + .catch(pError => { + console.log("Error al obtener el Historial", pError); + res.status(412).send(util.formatearMensaje(tipoError, pError)); + }); + }); + + app.options('/api/v1/historialFlujo/documento', sequelizeFormly.formly(documento, app.src.db.models)); +}; diff --git a/src/routes/plantillasFormly/plantilla_formlyRT.js b/src/routes/plantillasFormly/plantilla_formlyRT.js new file mode 100644 index 0000000..1d1e11e --- /dev/null +++ b/src/routes/plantillasFormly/plantilla_formlyRT.js @@ -0,0 +1,608 @@ +const {ModelHandler} = require("sequelize-handlers"); +const sequelizeFormly = require("sequelize-formly"); +const bl = require('../../bl/plantillasFormly/plantillasBL'); + +module.exports = app => { + const plantilla_formly = app.src.db.models.plantilla_formly; + const documento = app.src.db.models.documento; + const Modelos = app.src.db.models; + const util = app.src.lib.util; + const rutaExternos = app.src.config.config.host; + const Op = app.src.db.Sequelize.Op; + const sequelizeHandlers = new ModelHandler(plantilla_formly); + +/** + @apiVersion 1.0.0 + @apiGroup Plantillas_Formly + @apiName Post plantillas_formly + @api {post} /api/v1/plantillasFormly/plantillas_formly Crear plantillas_formly + + @apiDescription Post para plantillas_formly + + @apiParam (Petición) {Texto} nombre Nombre de la plantilla_formly + @apiParam (Petición) {Texto} abreviacion Abreviacion de la plantilla_formly + @apiParam (Petición) {Texto} plantilla Plantilla_formly + @apiParam (Petición) {Numérico} _usuario_creacion Identificador del usuario que esta creando + + @apiParamExample {json} Ejemplo para enviar: + { + "nombre":"plantilla_test", + "abreviacion":"plant", + "plantilla":"[]", + "_usuario_creacion":1 + } + + @apiSuccess (Respuesta) {Numérico} id_plantillas_formly Identificador de plantillas_formly + @apiSuccess (Respuesta) {Texto} nombre Nombre de plantilla_formly + @apiSuccess (Respuesta) {Texto} abreviacion Abreviacion de plantillas_formly + @apiSuccess (Respuesta) {Texto} plantilla Plantillas_formly + @apiSuccess (Respuesta) {Texto} plantilla_valor Valor de plantillas_formly + @apiSuccess (Respuesta) {Texto} estado Estado de plantillas_formly + @apiSuccess (Respuesta) {Numérico} _usuario_creacion Identificador del usuario creador + @apiSuccess (Respuesta) {Numérico} _usuario_modificacion Identificador del usuario modificador + @apiSuccess (Respuesta) {FechaHora} _fecha_creacion Fecha de creación de plantillas_formly + @apiSuccess (Respuesta) {FechaHora} _fecha_modificacion Fecha de modificación de plantillas_formly + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "La operación se realizó correctamente.", + "datos": { + "id_plantilla_formly": 21, + "nombre": "plantilla_test", + "abreviacion": "plant", + "plantilla": "[]", + "plantilla_valor": null, + "estado": "ACTIVO", + "_usuario_creacion": 1, + "_usuario_modificacion": null + "_fecha_modificacion": "2016-12-19T20:55:31.372Z", + "_fecha_creacion": "2016-12-19T20:55:31.372Z", + } + } + + @apiSampleRequest off +*/ +app.post('/api/v1/plantillasFormly/plantilla_formly', sequelizeHandlers.create(plantilla_formly)); + +/** + @apiVersion 2.0.0 + @apiGroup Plantillas_Formly + @apiName Post plantillasFormly/generarDocumento + @api {post} /api/v1/plantillasFormly/generarDocumento Generar el documento PDF + + @apiDescription Post del plantillas_formly/generarDocumento para generar el documento en formato PDF en base a una plantilla + + @apiParam (Petición) {Texto} nombre Nombre del documento + @apiParam (Petición) {Texto} plantilla Plantilla_formly + @apiParam (Petición) {Vector} form_actual Plantilla_formly en array + @apiParam (Petición) {Objeto} model_actual Datos de la plantilla + + @apiParamExample {json} Ejemplo para enviar: + { + "nombre":"plantilla_test", + "plantilla":"[]", + "form_actual": [], + "model_actual": {} + } + + @apiSuccess (Respuesta) {Texto} nombre Nombre del documento PDF generado + @apiSuccess (Respuesta) {Texto} html Documento en formato html + + @apiSuccessExample {json} Respuesta del Ejemplo: + HTTP/1.1 200 OK + { + "tipoMensaje": "EXITO", + "mensaje": "Exitosa generación de la vísta previa.", + "datos": { + "nombre": "plantilla_test.pdf", + "html": " diff --git a/src/views/partials/header.ejs b/src/views/partials/header.ejs new file mode 100644 index 0000000..905877d --- /dev/null +++ b/src/views/partials/header.ejs @@ -0,0 +1,19 @@ + + +