From cfe5dab601d69b03e9df77735b7207209a41fb2d Mon Sep 17 00:00:00 2001 From: boedy Date: Fri, 10 May 2019 17:56:32 +0200 Subject: [PATCH] Use CocoaPods instead of including copy of GCDWebServer in Project. Reduces conflict chance with other plugins --- .gitignore | 1 + package-lock.json | 2204 ++++++++--------- plugin.xml | 49 +- src/ios/GCDWebServer/Core/GCDWebServer.h | 623 ----- src/ios/GCDWebServer/Core/GCDWebServer.m | 1320 ---------- .../Core/GCDWebServerConnection.h | 183 -- .../Core/GCDWebServerConnection.m | 868 ------- .../GCDWebServer/Core/GCDWebServerFunctions.h | 109 - .../GCDWebServer/Core/GCDWebServerFunctions.m | 316 --- .../Core/GCDWebServerHTTPStatusCodes.h | 116 - .../GCDWebServer/Core/GCDWebServerPrivate.h | 245 -- .../GCDWebServer/Core/GCDWebServerRequest.h | 210 -- .../GCDWebServer/Core/GCDWebServerRequest.m | 303 --- .../GCDWebServer/Core/GCDWebServerResponse.h | 212 -- .../GCDWebServer/Core/GCDWebServerResponse.m | 284 --- .../Requests/GCDWebServerDataRequest.h | 64 - .../Requests/GCDWebServerDataRequest.m | 104 - .../Requests/GCDWebServerFileRequest.h | 49 - .../Requests/GCDWebServerFileRequest.m | 102 - .../GCDWebServerMultiPartFormRequest.h | 136 - .../GCDWebServerMultiPartFormRequest.m | 405 --- .../GCDWebServerURLEncodedFormRequest.h | 55 - .../GCDWebServerURLEncodedFormRequest.m | 60 - .../Responses/GCDWebServerDataResponse.h | 113 - .../Responses/GCDWebServerDataResponse.m | 136 - .../Responses/GCDWebServerErrorResponse.h | 85 - .../Responses/GCDWebServerErrorResponse.m | 124 - .../Responses/GCDWebServerFileResponse.h | 108 - .../Responses/GCDWebServerFileResponse.m | 185 -- .../Responses/GCDWebServerStreamedResponse.h | 80 - .../Responses/GCDWebServerStreamedResponse.m | 78 - 31 files changed, 1111 insertions(+), 7816 deletions(-) delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServer.h delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServer.m delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerConnection.h delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerConnection.m delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerFunctions.h delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerFunctions.m delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerPrivate.h delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerRequest.h delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerRequest.m delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerResponse.h delete mode 100755 src/ios/GCDWebServer/Core/GCDWebServerResponse.m delete mode 100755 src/ios/GCDWebServer/Requests/GCDWebServerDataRequest.h delete mode 100755 src/ios/GCDWebServer/Requests/GCDWebServerDataRequest.m delete mode 100755 src/ios/GCDWebServer/Requests/GCDWebServerFileRequest.h delete mode 100755 src/ios/GCDWebServer/Requests/GCDWebServerFileRequest.m delete mode 100755 src/ios/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h delete mode 100755 src/ios/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m delete mode 100755 src/ios/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h delete mode 100755 src/ios/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m delete mode 100755 src/ios/GCDWebServer/Responses/GCDWebServerDataResponse.h delete mode 100755 src/ios/GCDWebServer/Responses/GCDWebServerDataResponse.m delete mode 100755 src/ios/GCDWebServer/Responses/GCDWebServerErrorResponse.h delete mode 100755 src/ios/GCDWebServer/Responses/GCDWebServerErrorResponse.m delete mode 100755 src/ios/GCDWebServer/Responses/GCDWebServerFileResponse.h delete mode 100755 src/ios/GCDWebServer/Responses/GCDWebServerFileResponse.m delete mode 100755 src/ios/GCDWebServer/Responses/GCDWebServerStreamedResponse.h delete mode 100755 src/ios/GCDWebServer/Responses/GCDWebServerStreamedResponse.m diff --git a/.gitignore b/.gitignore index 7bea99a..833a756 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,4 @@ typings/ # dotenv environment variables file .env +webserver-test diff --git a/package-lock.json b/package-lock.json index 9579897..4f18283 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,8 @@ "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", "dev": true, "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" } }, "abbrev": { @@ -26,7 +26,7 @@ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", "dev": true, "requires": { - "mime-types": "2.1.17", + "mime-types": "~2.1.16", "negotiator": "0.6.1" } }, @@ -42,7 +42,7 @@ "integrity": "sha1-fDCCW5RQueYYW6J1M+r24gZ9S0I=", "dev": true, "requires": { - "browserify-transform-tools": "1.7.0" + "browserify-transform-tools": "~1.7.0" } }, "ansi": { @@ -76,8 +76,8 @@ "dev": true, "optional": true, "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" } }, "arr-diff": { @@ -87,7 +87,7 @@ "dev": true, "optional": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "^1.0.1" } }, "arr-flatten": { @@ -140,9 +140,9 @@ "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", "dev": true, "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "assert": { @@ -166,7 +166,7 @@ "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", "dev": true, "requires": { - "acorn": "4.0.13" + "acorn": "^4.0.3" }, "dependencies": { "acorn": { @@ -214,21 +214,21 @@ "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", "dev": true, "requires": { - "babel-core": "6.26.0", - "babel-polyfill": "6.26.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "chokidar": "1.7.0", - "commander": "2.13.0", - "convert-source-map": "1.5.1", - "fs-readdir-recursive": "1.1.0", - "glob": "7.1.2", - "lodash": "4.17.4", - "output-file-sync": "1.1.2", - "path-is-absolute": "1.0.1", - "slash": "1.0.0", - "source-map": "0.5.7", - "v8flags": "2.1.1" + "babel-core": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "chokidar": "^1.6.1", + "commander": "^2.11.0", + "convert-source-map": "^1.5.0", + "fs-readdir-recursive": "^1.0.0", + "glob": "^7.1.2", + "lodash": "^4.17.4", + "output-file-sync": "^1.1.2", + "path-is-absolute": "^1.0.1", + "slash": "^1.0.0", + "source-map": "^0.5.6", + "v8flags": "^2.1.1" }, "dependencies": { "babel-runtime": { @@ -237,8 +237,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.4.1", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "regenerator-runtime": { @@ -255,9 +255,9 @@ "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.0", + "esutils": "^2.0.2", + "js-tokens": "^3.0.0" } }, "babel-core": { @@ -266,25 +266,25 @@ "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.8", - "json5": "0.5.1", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.7", - "slash": "1.0.0", - "source-map": "0.5.7" + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.0", + "debug": "^2.6.8", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.7", + "slash": "^1.0.0", + "source-map": "^0.5.6" }, "dependencies": { "babel-code-frame": { @@ -293,9 +293,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" } }, "babel-runtime": { @@ -304,8 +304,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.4.1", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-template": { @@ -314,11 +314,11 @@ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.4" + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" } }, "babel-traverse": { @@ -327,15 +327,15 @@ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.8", - "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.4" + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" } }, "babel-types": { @@ -344,10 +344,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.4", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "babylon": { @@ -370,14 +370,14 @@ "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", "dev": true, "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.4", - "source-map": "0.5.7", - "trim-right": "1.0.1" + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.6", + "trim-right": "^1.0.1" }, "dependencies": { "babel-runtime": { @@ -386,8 +386,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.4.1", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-types": { @@ -396,10 +396,10 @@ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.4", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "regenerator-runtime": { @@ -416,9 +416,9 @@ "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-builder-binary-assignment-operator-visitor": { @@ -427,9 +427,9 @@ "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", "dev": true, "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-call-delegate": { @@ -438,10 +438,10 @@ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", "dev": true, "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-define-map": { @@ -450,10 +450,10 @@ "integrity": "sha1-epdH8ljYlH0y1RX2qhx70CIEoIA=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "lodash": "4.17.4" + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1", + "lodash": "^4.2.0" } }, "babel-helper-explode-assignable-expression": { @@ -462,9 +462,9 @@ "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-explode-class": { @@ -473,10 +473,10 @@ "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", "dev": true, "requires": { - "babel-helper-bindify-decorators": "6.24.1", - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-bindify-decorators": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-function-name": { @@ -485,11 +485,11 @@ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", "dev": true, "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-get-function-arity": { @@ -498,8 +498,8 @@ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-hoist-variables": { @@ -508,8 +508,8 @@ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-optimise-call-expression": { @@ -518,8 +518,8 @@ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-helper-regex": { @@ -528,9 +528,9 @@ "integrity": "sha1-024i+rEAjXnYhkjjIRaGgShFbOg=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "lodash": "4.17.4" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1", + "lodash": "^4.2.0" } }, "babel-helper-remap-async-to-generator": { @@ -539,11 +539,11 @@ "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helper-replace-supers": { @@ -552,12 +552,12 @@ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", "dev": true, "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-helpers": { @@ -566,8 +566,8 @@ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-messages": { @@ -576,7 +576,7 @@ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-check-es2015-constants": { @@ -585,7 +585,7 @@ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-syntax-async-functions": { @@ -642,9 +642,9 @@ "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-generators": "6.13.0", - "babel-runtime": "6.23.0" + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-generators": "^6.5.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-async-to-generator": { @@ -653,9 +653,9 @@ "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", "dev": true, "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.23.0" + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-class-properties": { @@ -664,10 +664,10 @@ "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-decorators": { @@ -676,11 +676,11 @@ "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", "dev": true, "requires": { - "babel-helper-explode-class": "6.24.1", - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-explode-class": "^6.24.1", + "babel-plugin-syntax-decorators": "^6.13.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-arrow-functions": { @@ -689,7 +689,7 @@ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-block-scoped-functions": { @@ -698,7 +698,7 @@ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-block-scoping": { @@ -707,11 +707,11 @@ "integrity": "sha1-dsKV3DpHQbFmWt/TFnIV3P8ypXY=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "lodash": "4.17.4" + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1", + "lodash": "^4.2.0" } }, "babel-plugin-transform-es2015-classes": { @@ -720,15 +720,15 @@ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", "dev": true, "requires": { - "babel-helper-define-map": "6.24.1", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-computed-properties": { @@ -737,8 +737,8 @@ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-destructuring": { @@ -747,7 +747,7 @@ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-duplicate-keys": { @@ -756,8 +756,8 @@ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-for-of": { @@ -766,7 +766,7 @@ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-function-name": { @@ -775,9 +775,9 @@ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", "dev": true, "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-literals": { @@ -786,7 +786,7 @@ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-modules-amd": { @@ -795,9 +795,9 @@ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-modules-commonjs": { @@ -806,10 +806,10 @@ "integrity": "sha1-0+MQtA72ZKNmIiAAl8bUQCmPK/4=", "dev": true, "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-types": "6.25.0" + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-modules-systemjs": { @@ -818,9 +818,9 @@ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", "dev": true, "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-modules-umd": { @@ -829,9 +829,9 @@ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", "dev": true, "requires": { - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" } }, "babel-plugin-transform-es2015-object-super": { @@ -840,8 +840,8 @@ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", "dev": true, "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.23.0" + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-parameters": { @@ -850,12 +850,12 @@ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", "dev": true, "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-shorthand-properties": { @@ -864,8 +864,8 @@ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-spread": { @@ -874,7 +874,7 @@ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-sticky-regex": { @@ -883,9 +883,9 @@ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", "dev": true, "requires": { - "babel-helper-regex": "6.24.1", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-plugin-transform-es2015-template-literals": { @@ -894,7 +894,7 @@ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-typeof-symbol": { @@ -903,7 +903,7 @@ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", "dev": true, "requires": { - "babel-runtime": "6.23.0" + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-es2015-unicode-regex": { @@ -912,9 +912,9 @@ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", "dev": true, "requires": { - "babel-helper-regex": "6.24.1", - "babel-runtime": "6.23.0", - "regexpu-core": "2.0.0" + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" } }, "babel-plugin-transform-exponentiation-operator": { @@ -923,9 +923,9 @@ "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", "dev": true, "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.23.0" + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-object-rest-spread": { @@ -934,8 +934,8 @@ "integrity": "sha1-h11ryb52HFiirj/u5dxIldjH+SE=", "dev": true, "requires": { - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.23.0" + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.22.0" } }, "babel-plugin-transform-regenerator": { @@ -953,8 +953,8 @@ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" } }, "babel-polyfill": { @@ -963,9 +963,9 @@ "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", "dev": true, "requires": { - "babel-runtime": "6.26.0", - "core-js": "2.5.3", - "regenerator-runtime": "0.10.5" + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" }, "dependencies": { "babel-runtime": { @@ -974,8 +974,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.3", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" }, "dependencies": { "regenerator-runtime": { @@ -1000,36 +1000,36 @@ "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", "dev": true, "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.24.1", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-regenerator": "6.24.1", - "browserslist": "2.11.3", - "invariant": "2.2.2", - "semver": "5.5.0" + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^2.1.2", + "invariant": "^2.2.2", + "semver": "^5.3.0" } }, "babel-preset-es2015": { @@ -1038,30 +1038,30 @@ "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", "dev": true, "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.24.1", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-regenerator": "6.24.1" + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.24.1", + "babel-plugin-transform-es2015-classes": "^6.24.1", + "babel-plugin-transform-es2015-computed-properties": "^6.24.1", + "babel-plugin-transform-es2015-destructuring": "^6.22.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", + "babel-plugin-transform-es2015-for-of": "^6.22.0", + "babel-plugin-transform-es2015-function-name": "^6.24.1", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-umd": "^6.24.1", + "babel-plugin-transform-es2015-object-super": "^6.24.1", + "babel-plugin-transform-es2015-parameters": "^6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", + "babel-plugin-transform-regenerator": "^6.24.1" } }, "babel-preset-stage-2": { @@ -1070,10 +1070,10 @@ "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", "dev": true, "requires": { - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-decorators": "6.24.1", - "babel-preset-stage-3": "6.24.1" + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-decorators": "^6.24.1", + "babel-preset-stage-3": "^6.24.1" } }, "babel-preset-stage-3": { @@ -1082,11 +1082,11 @@ "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", "dev": true, "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-generator-functions": "6.24.1", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-object-rest-spread": "6.23.0" + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-generator-functions": "^6.24.1", + "babel-plugin-transform-async-to-generator": "^6.24.1", + "babel-plugin-transform-exponentiation-operator": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^6.22.0" } }, "babel-register": { @@ -1095,13 +1095,13 @@ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "dev": true, "requires": { - "babel-core": "6.26.0", - "babel-runtime": "6.26.0", - "core-js": "2.5.3", - "home-or-tmp": "2.0.0", - "lodash": "4.17.4", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" }, "dependencies": { "babel-runtime": { @@ -1110,8 +1110,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.3", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "core-js": { @@ -1134,8 +1134,8 @@ "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", "dev": true, "requires": { - "core-js": "2.4.1", - "regenerator-runtime": "0.10.5" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.10.0" } }, "babel-template": { @@ -1144,11 +1144,11 @@ "integrity": "sha1-ZlJBFmt8KqTGGdceGSlpVSsQwHE=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "babylon": "6.17.4", - "lodash": "4.17.4" + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.25.0", + "babel-types": "^6.25.0", + "babylon": "^6.17.2", + "lodash": "^4.2.0" } }, "babel-traverse": { @@ -1157,15 +1157,15 @@ "integrity": "sha1-IldJfi/NGbie3BPEyROB+VEklvE=", "dev": true, "requires": { - "babel-code-frame": "6.22.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "babylon": "6.17.4", - "debug": "2.6.8", - "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.4" + "babel-code-frame": "^6.22.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-types": "^6.25.0", + "babylon": "^6.17.2", + "debug": "^2.2.0", + "globals": "^9.0.0", + "invariant": "^2.2.0", + "lodash": "^4.2.0" } }, "babel-types": { @@ -1174,10 +1174,10 @@ "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "esutils": "2.0.2", - "lodash": "4.17.4", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.22.0", + "esutils": "^2.0.2", + "lodash": "^4.2.0", + "to-fast-properties": "^1.0.1" } }, "babylon": { @@ -1205,7 +1205,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "big-integer": { @@ -1227,7 +1227,7 @@ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "~2.0.0" } }, "bn.js": { @@ -1243,15 +1243,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.2", + "depd": "~1.1.1", + "http-errors": "~1.6.2", "iconv-lite": "0.4.19", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "1.6.15" + "type-is": "~1.6.15" }, "dependencies": { "debug": { @@ -1271,7 +1271,7 @@ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "bplist-creator": { @@ -1280,7 +1280,7 @@ "integrity": "sha1-N98VNgkoJLh8QvlXsBNEEXNyrkU=", "dev": true, "requires": { - "stream-buffers": "2.2.0" + "stream-buffers": "~2.2.0" } }, "bplist-parser": { @@ -1289,7 +1289,7 @@ "integrity": "sha1-1g1dzCDLptx+HymbNdPh+V2vuuY=", "dev": true, "requires": { - "big-integer": "1.6.26" + "big-integer": "^1.6.7" } }, "brace-expansion": { @@ -1298,7 +1298,7 @@ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -1309,9 +1309,9 @@ "dev": true, "optional": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, "brorand": { @@ -1326,12 +1326,12 @@ "integrity": "sha512-Jo+RYsn8X8OhyP9tMXXg0ueR2fW696HUu1Hf3/DeiwNean1oGiPtdgGRNuUHBpPHzBH3x4n1kzAlgOgHSIq88g==", "dev": true, "requires": { - "JSONStream": "1.3.2", - "combine-source-map": "0.8.0", - "defined": "1.0.0", - "safe-buffer": "5.1.1", - "through2": "2.0.3", - "umd": "3.0.1" + "JSONStream": "^1.0.3", + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" } }, "browser-resolve": { @@ -1357,53 +1357,53 @@ "integrity": "sha1-CJo0Y69Y0OSNjNQHCz90ZU1avKk=", "dev": true, "requires": { - "JSONStream": "1.3.2", - "assert": "1.4.1", - "browser-pack": "6.0.3", - "browser-resolve": "1.11.2", - "browserify-zlib": "0.1.4", - "buffer": "5.0.8", - "cached-path-relative": "1.0.1", - "concat-stream": "1.5.2", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "defined": "1.0.0", - "deps-sort": "2.0.0", - "domain-browser": "1.1.7", - "duplexer2": "0.1.4", - "events": "1.1.1", - "glob": "7.1.2", - "has": "1.0.1", - "htmlescape": "1.1.1", - "https-browserify": "1.0.0", - "inherits": "2.0.3", - "insert-module-globals": "7.0.1", - "labeled-stream-splicer": "2.0.0", - "module-deps": "4.1.1", - "os-browserify": "0.1.2", - "parents": "1.0.1", - "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "read-only-stream": "2.0.0", - "readable-stream": "2.3.3", - "resolve": "1.5.0", - "shasum": "1.0.2", - "shell-quote": "1.6.1", - "stream-browserify": "2.0.1", - "stream-http": "2.8.0", - "string_decoder": "1.0.3", - "subarg": "1.0.0", - "syntax-error": "1.3.0", - "through2": "2.0.3", - "timers-browserify": "1.4.2", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", - "vm-browserify": "0.0.4", - "xtend": "4.0.1" + "JSONStream": "^1.0.3", + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^1.11.0", + "browserify-zlib": "~0.1.2", + "buffer": "^5.0.2", + "cached-path-relative": "^1.0.0", + "concat-stream": "~1.5.1", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.0", + "domain-browser": "~1.1.0", + "duplexer2": "~0.1.2", + "events": "~1.1.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.0.0", + "labeled-stream-splicer": "^2.0.0", + "module-deps": "^4.0.8", + "os-browserify": "~0.1.1", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^2.0.0", + "stream-http": "^2.0.0", + "string_decoder": "~1.0.0", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "~0.0.0", + "url": "~0.11.0", + "util": "~0.10.1", + "vm-browserify": "~0.0.1", + "xtend": "^4.0.0" } }, "browserify-aes": { @@ -1412,12 +1412,12 @@ "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", "dev": true, "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "browserify-cipher": { @@ -1426,9 +1426,9 @@ "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", "dev": true, "requires": { - "browserify-aes": "1.1.1", - "browserify-des": "1.0.0", - "evp_bytestokey": "1.0.3" + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" } }, "browserify-des": { @@ -1437,9 +1437,9 @@ "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", "dev": true, "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3" + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1" } }, "browserify-rsa": { @@ -1448,8 +1448,8 @@ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { - "bn.js": "4.11.8", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" } }, "browserify-sign": { @@ -1458,13 +1458,13 @@ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "elliptic": "6.4.0", - "inherits": "2.0.3", - "parse-asn1": "5.1.0" + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" } }, "browserify-transform-tools": { @@ -1473,8 +1473,8 @@ "integrity": "sha1-g+J3Ih9jJZvtLn6yooOpcKUB9MQ=", "dev": true, "requires": { - "falafel": "2.1.0", - "through": "2.3.8" + "falafel": "^2.0.0", + "through": "^2.3.7" } }, "browserify-zlib": { @@ -1483,7 +1483,7 @@ "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", "dev": true, "requires": { - "pako": "0.2.9" + "pako": "~0.2.0" } }, "browserslist": { @@ -1492,8 +1492,8 @@ "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", "dev": true, "requires": { - "caniuse-lite": "1.0.30000792", - "electron-to-chromium": "1.3.31" + "caniuse-lite": "^1.0.30000792", + "electron-to-chromium": "^1.3.30" } }, "buffer": { @@ -1502,8 +1502,8 @@ "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==", "dev": true, "requires": { - "base64-js": "1.2.1", - "ieee754": "1.1.8" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" }, "dependencies": { "base64-js": { @@ -1568,11 +1568,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "chokidar": { @@ -1582,15 +1582,15 @@ "dev": true, "optional": true, "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.1.3", - "glob-parent": "2.0.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" } }, "cipher-base": { @@ -1599,8 +1599,8 @@ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "cli-cursor": { @@ -1609,7 +1609,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "^1.0.1" } }, "cli-width": { @@ -1630,10 +1630,10 @@ "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", "dev": true, "requires": { - "convert-source-map": "1.1.3", - "inline-source-map": "0.6.2", - "lodash.memoize": "3.0.4", - "source-map": "0.5.7" + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" }, "dependencies": { "convert-source-map": { @@ -1650,7 +1650,7 @@ "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", "dev": true, "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "commander": { @@ -1665,7 +1665,7 @@ "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", "dev": true, "requires": { - "mime-db": "1.30.0" + "mime-db": ">= 1.30.0 < 2" } }, "compression": { @@ -1674,13 +1674,13 @@ "integrity": "sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s=", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "~1.3.4", "bytes": "3.0.0", - "compressible": "2.0.12", + "compressible": "~2.0.11", "debug": "2.6.9", - "on-headers": "1.0.1", + "on-headers": "~1.0.1", "safe-buffer": "5.1.1", - "vary": "1.1.2" + "vary": "~1.1.2" }, "dependencies": { "debug": { @@ -1706,9 +1706,9 @@ "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.0.6", - "typedarray": "0.0.6" + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" }, "dependencies": { "readable-stream": { @@ -1717,12 +1717,12 @@ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -1739,15 +1739,15 @@ "integrity": "sha1-c3o6cDbpiGECqmCZ5HuzOrGroaE=", "dev": true, "requires": { - "dot-prop": "3.0.0", - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "os-tmpdir": "1.0.2", - "osenv": "0.1.4", - "uuid": "2.0.3", - "write-file-atomic": "1.3.4", - "xdg-basedir": "2.0.0" + "dot-prop": "^3.0.0", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "object-assign": "^4.0.1", + "os-tmpdir": "^1.0.0", + "osenv": "^0.1.0", + "uuid": "^2.0.1", + "write-file-atomic": "^1.1.2", + "xdg-basedir": "^2.0.0" } }, "console-browserify": { @@ -1756,7 +1756,7 @@ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "dev": true, "requires": { - "date-now": "0.1.4" + "date-now": "^0.1.4" } }, "constants-browserify": { @@ -1802,7 +1802,7 @@ "dev": true, "requires": { "configstore": "2.1.0", - "cordova-common": "2.2.1", + "cordova-common": "^2.2.0", "cordova-lib": "8.0.0", "editor": "1.0.0", "insight": "0.8.4", @@ -1822,19 +1822,19 @@ "integrity": "sha1-cAm8WRcpyqcoWliM/Wp7VM2DTww=", "dev": true, "requires": { - "ansi": "0.3.1", - "bplist-parser": "0.1.1", - "cordova-registry-mapper": "1.1.15", + "ansi": "^0.3.1", + "bplist-parser": "^0.1.0", + "cordova-registry-mapper": "^1.1.8", "elementtree": "0.1.6", - "glob": "5.0.15", - "minimatch": "3.0.4", - "osenv": "0.1.4", - "plist": "1.2.0", - "q": "1.5.1", - "semver": "5.5.0", - "shelljs": "0.5.3", - "underscore": "1.8.3", - "unorm": "1.4.1" + "glob": "^5.0.13", + "minimatch": "^3.0.0", + "osenv": "^0.1.3", + "plist": "^1.2.0", + "q": "^1.4.1", + "semver": "^5.0.1", + "shelljs": "^0.5.3", + "underscore": "^1.8.3", + "unorm": "^1.3.3" }, "dependencies": { "glob": { @@ -1843,11 +1843,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } } } @@ -1858,9 +1858,9 @@ "integrity": "sha1-g7CScbN40cA7x9mnhv7dYEhcPM8=", "dev": true, "requires": { - "cordova-app-hello-world": "3.12.0", - "cordova-common": "2.2.1", - "cordova-fetch": "1.3.0", + "cordova-app-hello-world": "^3.11.0", + "cordova-common": "^2.2.0", + "cordova-fetch": "^1.3.0", "q": "1.0.1", "shelljs": "0.3.0", "valid-identifier": "0.0.1" @@ -1886,12 +1886,12 @@ "integrity": "sha1-SYbQd5s26yOYIsKrQTpH/58Jf+o=", "dev": true, "requires": { - "cordova-common": "2.2.1", - "dependency-ls": "1.1.1", - "hosted-git-info": "2.5.0", - "is-url": "1.2.2", - "q": "1.5.1", - "shelljs": "0.7.8" + "cordova-common": "^2.2.0", + "dependency-ls": "^1.1.0", + "hosted-git-info": "^2.5.0", + "is-url": "^1.2.1", + "q": "^1.4.1", + "shelljs": "^0.7.0" }, "dependencies": { "shelljs": { @@ -1900,9 +1900,9 @@ "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", "dev": true, "requires": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" } } } @@ -1922,31 +1922,31 @@ "integrity": "sha1-hkvV3mt5/ElENhRgqjIU5Z2pNvI=", "dev": true, "requires": { - "aliasify": "2.1.0", - "cordova-common": "2.2.1", - "cordova-create": "1.1.2", - "cordova-fetch": "1.3.0", - "cordova-js": "4.2.2", - "cordova-serve": "2.0.0", + "aliasify": "^2.1.0", + "cordova-common": "^2.2.0", + "cordova-create": "^1.1.0", + "cordova-fetch": "^1.3.0", + "cordova-js": "^4.2.2", + "cordova-serve": "^2.0.0", "dep-graph": "1.1.0", - "dependency-ls": "1.1.1", - "detect-indent": "5.0.0", + "dependency-ls": "^1.1.1", + "detect-indent": "^5.0.0", "elementtree": "0.1.6", "glob": "7.1.1", - "init-package-json": "1.10.1", + "init-package-json": "^1.2.0", "nopt": "4.0.1", "opener": "1.4.2", "plist": "2.0.1", "properties-parser": "0.3.1", "q": "1.0.1", "request": "2.79.0", - "semver": "5.5.0", + "semver": "^5.3.0", "shelljs": "0.3.0", "tar": "2.2.1", "underscore": "1.8.3", "unorm": "1.4.1", "valid-identifier": "0.0.1", - "xcode": "1.0.0" + "xcode": "^1.0.0" }, "dependencies": { "base64-js": { @@ -1967,12 +1967,12 @@ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "nopt": { @@ -1981,8 +1981,8 @@ "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.4" + "abbrev": "1", + "osenv": "^0.1.4" } }, "plist": { @@ -1993,7 +1993,7 @@ "requires": { "base64-js": "1.1.2", "xmlbuilder": "8.2.2", - "xmldom": "0.1.27" + "xmldom": "0.1.x" } }, "q": { @@ -2028,11 +2028,11 @@ "integrity": "sha1-14NLg7GGYH4rjxlD4HPAYzNg6kM=", "dev": true, "requires": { - "chalk": "1.1.3", - "compression": "1.7.1", - "express": "4.16.2", + "chalk": "^1.1.1", + "compression": "^1.6.0", + "express": "^4.13.3", "open": "0.0.5", - "shelljs": "0.5.3" + "shelljs": "^0.5.3" } }, "core-js": { @@ -2053,8 +2053,8 @@ "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", "dev": true, "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0" + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" } }, "create-hash": { @@ -2063,10 +2063,10 @@ "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", "dev": true, "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "sha.js": "2.4.10" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "sha.js": "^2.4.0" } }, "create-hmac": { @@ -2075,12 +2075,12 @@ "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", "dev": true, "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.10" + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "cryptiles": { @@ -2089,7 +2089,7 @@ "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, "requires": { - "boom": "2.10.1" + "boom": "2.x.x" } }, "crypto-browserify": { @@ -2098,17 +2098,17 @@ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, "requires": { - "browserify-cipher": "1.0.0", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.0", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "diffie-hellman": "5.0.2", - "inherits": "2.0.3", - "pbkdf2": "3.0.14", - "public-encrypt": "4.0.0", - "randombytes": "2.0.6", - "randomfill": "1.0.3" + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" } }, "dashdash": { @@ -2117,7 +2117,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -2207,10 +2207,10 @@ "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", "dev": true, "requires": { - "JSONStream": "1.3.2", - "shasum": "1.0.2", - "subarg": "1.0.0", - "through2": "2.0.3" + "JSONStream": "^1.0.3", + "shasum": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" } }, "des.js": { @@ -2219,8 +2219,8 @@ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "destroy": { @@ -2235,7 +2235,7 @@ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "detective": { @@ -2244,8 +2244,8 @@ "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", "dev": true, "requires": { - "acorn": "5.3.0", - "defined": "1.0.0" + "acorn": "^5.2.1", + "defined": "^1.0.0" } }, "diffie-hellman": { @@ -2254,9 +2254,9 @@ "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", "dev": true, "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" } }, "domain-browser": { @@ -2271,7 +2271,7 @@ "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", "dev": true, "requires": { - "is-obj": "1.0.1" + "is-obj": "^1.0.0" } }, "duplexer2": { @@ -2280,7 +2280,7 @@ "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "requires": { - "readable-stream": "2.3.3" + "readable-stream": "^2.0.2" } }, "duplexify": { @@ -2289,10 +2289,10 @@ "integrity": "sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==", "dev": true, "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "stream-shift": "1.0.0" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, "ecc-jsbn": { @@ -2302,7 +2302,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "editor": { @@ -2338,13 +2338,13 @@ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" } }, "encodeurl": { @@ -2359,7 +2359,7 @@ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.4.0" } }, "escape-html": { @@ -2398,8 +2398,8 @@ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { - "md5.js": "1.3.4", - "safe-buffer": "5.1.1" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, "exit-hook": { @@ -2415,7 +2415,7 @@ "dev": true, "optional": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "^0.1.0" } }, "expand-range": { @@ -2425,7 +2425,7 @@ "dev": true, "optional": true, "requires": { - "fill-range": "2.2.3" + "fill-range": "^2.1.0" } }, "express": { @@ -2434,36 +2434,36 @@ "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "~1.3.4", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", - "content-type": "1.0.4", + "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.1", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "finalhandler": "1.1.0", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", + "proxy-addr": "~2.0.2", "qs": "6.5.1", - "range-parser": "1.2.0", + "range-parser": "~1.2.0", "safe-buffer": "5.1.1", "send": "0.16.1", "serve-static": "1.13.1", "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", + "statuses": "~1.3.1", + "type-is": "~1.6.15", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" }, "dependencies": { "debug": { @@ -2490,7 +2490,7 @@ "dev": true, "optional": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "extsprintf": { @@ -2505,10 +2505,10 @@ "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", "dev": true, "requires": { - "acorn": "5.3.0", - "foreach": "2.0.5", + "acorn": "^5.0.0", + "foreach": "^2.0.5", "isarray": "0.0.1", - "object-keys": "1.0.11" + "object-keys": "^1.0.6" }, "dependencies": { "isarray": { @@ -2525,8 +2525,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, "filename-regex": { @@ -2543,11 +2543,11 @@ "dev": true, "optional": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^1.1.3", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" } }, "finalhandler": { @@ -2557,12 +2557,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" }, "dependencies": { "debug": { @@ -2590,7 +2590,7 @@ "dev": true, "optional": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } }, "foreach": { @@ -2611,9 +2611,9 @@ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" } }, "forwarded": { @@ -2647,8 +2647,8 @@ "dev": true, "optional": true, "requires": { - "nan": "2.8.0", - "node-pre-gyp": "0.6.39" + "nan": "^2.3.0", + "node-pre-gyp": "^0.6.39" }, "dependencies": { "abbrev": { @@ -2663,8 +2663,8 @@ "dev": true, "optional": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" } }, "ansi-regex": { @@ -2684,8 +2684,8 @@ "dev": true, "optional": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "asn1": { @@ -2729,7 +2729,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "block-stream": { @@ -2737,7 +2737,7 @@ "bundled": true, "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "~2.0.0" } }, "boom": { @@ -2745,7 +2745,7 @@ "bundled": true, "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "brace-expansion": { @@ -2753,7 +2753,7 @@ "bundled": true, "dev": true, "requires": { - "balanced-match": "0.4.2", + "balanced-match": "^0.4.1", "concat-map": "0.0.1" } }, @@ -2784,7 +2784,7 @@ "bundled": true, "dev": true, "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "concat-map": { @@ -2807,7 +2807,7 @@ "bundled": true, "dev": true, "requires": { - "boom": "2.10.1" + "boom": "2.x.x" } }, "dashdash": { @@ -2816,7 +2816,7 @@ "dev": true, "optional": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -2865,7 +2865,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "extend": { @@ -2891,9 +2891,9 @@ "dev": true, "optional": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" } }, "fs.realpath": { @@ -2906,10 +2906,10 @@ "bundled": true, "dev": true, "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" } }, "fstream-ignore": { @@ -2918,9 +2918,9 @@ "dev": true, "optional": true, "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" + "fstream": "^1.0.0", + "inherits": "2", + "minimatch": "^3.0.0" } }, "gauge": { @@ -2929,14 +2929,14 @@ "dev": true, "optional": true, "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, "getpass": { @@ -2945,7 +2945,7 @@ "dev": true, "optional": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -2961,12 +2961,12 @@ "bundled": true, "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "graceful-fs": { @@ -2986,8 +2986,8 @@ "dev": true, "optional": true, "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "ajv": "^4.9.1", + "har-schema": "^1.0.5" } }, "has-unicode": { @@ -3001,10 +3001,10 @@ "bundled": true, "dev": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" } }, "hoek": { @@ -3018,9 +3018,9 @@ "dev": true, "optional": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "inflight": { @@ -3028,8 +3028,8 @@ "bundled": true, "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -3048,7 +3048,7 @@ "bundled": true, "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-typedarray": { @@ -3074,7 +3074,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "jsbn": { @@ -3095,7 +3095,7 @@ "dev": true, "optional": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json-stringify-safe": { @@ -3140,7 +3140,7 @@ "bundled": true, "dev": true, "requires": { - "mime-db": "1.27.0" + "mime-db": "~1.27.0" } }, "minimatch": { @@ -3148,7 +3148,7 @@ "bundled": true, "dev": true, "requires": { - "brace-expansion": "1.1.7" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -3176,17 +3176,17 @@ "dev": true, "optional": true, "requires": { - "detect-libc": "1.0.2", + "detect-libc": "^1.0.2", "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "npmlog": "^4.0.2", + "rc": "^1.1.7", "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^2.2.1", + "tar-pack": "^3.4.0" } }, "nopt": { @@ -3195,8 +3195,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" + "abbrev": "1", + "osenv": "^0.1.4" } }, "npmlog": { @@ -3205,10 +3205,10 @@ "dev": true, "optional": true, "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "number-is-nan": { @@ -3233,7 +3233,7 @@ "bundled": true, "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "os-homedir": { @@ -3254,8 +3254,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "path-is-absolute": { @@ -3292,10 +3292,10 @@ "dev": true, "optional": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { @@ -3311,13 +3311,13 @@ "bundled": true, "dev": true, "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" } }, "request": { @@ -3326,28 +3326,28 @@ "dev": true, "optional": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" } }, "rimraf": { @@ -3355,7 +3355,7 @@ "bundled": true, "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "safe-buffer": { @@ -3386,7 +3386,7 @@ "bundled": true, "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "sshpk": { @@ -3395,15 +3395,15 @@ "dev": true, "optional": true, "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jodid25519": "^1.0.0", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" }, "dependencies": { "assert-plus": { @@ -3419,9 +3419,9 @@ "bundled": true, "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -3429,7 +3429,7 @@ "bundled": true, "dev": true, "requires": { - "safe-buffer": "5.0.1" + "safe-buffer": "^5.0.1" } }, "stringstream": { @@ -3443,7 +3443,7 @@ "bundled": true, "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -3457,9 +3457,9 @@ "bundled": true, "dev": true, "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, "tar-pack": { @@ -3468,14 +3468,14 @@ "dev": true, "optional": true, "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" + "debug": "^2.2.0", + "fstream": "^1.0.10", + "fstream-ignore": "^1.0.5", + "once": "^1.3.3", + "readable-stream": "^2.1.4", + "rimraf": "^2.5.1", + "tar": "^2.2.1", + "uid-number": "^0.0.6" } }, "tough-cookie": { @@ -3484,7 +3484,7 @@ "dev": true, "optional": true, "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" } }, "tunnel-agent": { @@ -3493,7 +3493,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "5.0.1" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -3534,7 +3534,7 @@ "dev": true, "optional": true, "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2" } }, "wrappy": { @@ -3550,10 +3550,10 @@ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" } }, "function-bind": { @@ -3574,7 +3574,7 @@ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, "requires": { - "is-property": "1.0.2" + "is-property": "^1.0.0" } }, "getpass": { @@ -3583,7 +3583,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -3600,12 +3600,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "glob-base": { @@ -3615,8 +3615,8 @@ "dev": true, "optional": true, "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" } }, "glob-parent": { @@ -3625,7 +3625,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.0" } }, "globals": { @@ -3640,16 +3640,16 @@ "integrity": "sha1-5dDtSvVfw+701WAHdp2YGSvLLso=", "dev": true, "requires": { - "duplexify": "3.5.3", - "infinity-agent": "2.0.3", - "is-redirect": "1.0.0", - "is-stream": "1.1.0", - "lowercase-keys": "1.0.0", - "nested-error-stacks": "1.0.2", - "object-assign": "3.0.0", - "prepend-http": "1.0.4", - "read-all-stream": "3.1.0", - "timed-out": "2.0.0" + "duplexify": "^3.2.0", + "infinity-agent": "^2.0.0", + "is-redirect": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "nested-error-stacks": "^1.0.0", + "object-assign": "^3.0.0", + "prepend-http": "^1.0.0", + "read-all-stream": "^3.0.0", + "timed-out": "^2.0.0" }, "dependencies": { "object-assign": { @@ -3672,10 +3672,10 @@ "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", "dev": true, "requires": { - "chalk": "1.1.3", - "commander": "2.13.0", - "is-my-json-valid": "2.17.1", - "pinkie-promise": "2.0.1" + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" } }, "has": { @@ -3684,7 +3684,7 @@ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "dev": true, "requires": { - "function-bind": "1.1.1" + "function-bind": "^1.0.2" } }, "has-ansi": { @@ -3693,7 +3693,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "hash-base": { @@ -3702,7 +3702,7 @@ "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "^2.0.1" } }, "hash.js": { @@ -3711,8 +3711,8 @@ "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "dev": true, "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" } }, "hawk": { @@ -3721,10 +3721,10 @@ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" } }, "hmac-drbg": { @@ -3733,9 +3733,9 @@ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, "hoek": { @@ -3750,8 +3750,8 @@ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" } }, "hosted-git-info": { @@ -3775,7 +3775,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": "1.3.1" + "statuses": ">= 1.3.1 < 2" }, "dependencies": { "depd": { @@ -3798,9 +3798,9 @@ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "https-browserify": { @@ -3845,8 +3845,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -3867,14 +3867,14 @@ "integrity": "sha1-zYc6FneWvvuZYSsodioLY5P9j2o=", "dev": true, "requires": { - "glob": "7.1.2", - "npm-package-arg": "5.1.2", - "promzard": "0.3.0", - "read": "1.0.7", - "read-package-json": "2.0.12", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.1", - "validate-npm-package-name": "3.0.0" + "glob": "^7.1.1", + "npm-package-arg": "^4.0.0 || ^5.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^3.0.0" } }, "inline-source-map": { @@ -3883,7 +3883,7 @@ "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "~0.5.3" } }, "inquirer": { @@ -3892,18 +3892,18 @@ "integrity": "sha1-6iXkzmnKFF4FyZ5G3P7AXkASWUo=", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "1.1.1", - "figures": "1.7.0", - "lodash": "3.10.1", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^1.0.1", + "figures": "^1.3.5", + "lodash": "^3.3.1", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" }, "dependencies": { "lodash": { @@ -3920,14 +3920,14 @@ "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", "dev": true, "requires": { - "JSONStream": "1.3.2", - "combine-source-map": "0.7.2", - "concat-stream": "1.5.2", - "is-buffer": "1.1.6", - "lexical-scope": "1.2.0", - "process": "0.11.10", - "through2": "2.0.3", - "xtend": "4.0.1" + "JSONStream": "^1.0.3", + "combine-source-map": "~0.7.1", + "concat-stream": "~1.5.1", + "is-buffer": "^1.1.0", + "lexical-scope": "^1.2.0", + "process": "~0.11.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" }, "dependencies": { "combine-source-map": { @@ -3936,10 +3936,10 @@ "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", "dev": true, "requires": { - "convert-source-map": "1.1.3", - "inline-source-map": "0.6.2", - "lodash.memoize": "3.0.4", - "source-map": "0.5.7" + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" } }, "convert-source-map": { @@ -3956,16 +3956,16 @@ "integrity": "sha1-ZxyvZbR8n+jD0bMgbPRbshG3WIQ=", "dev": true, "requires": { - "async": "1.5.2", - "chalk": "1.1.3", - "configstore": "1.4.0", - "inquirer": "0.10.1", - "lodash.debounce": "3.1.1", - "object-assign": "4.1.1", - "os-name": "1.0.3", - "request": "2.79.0", - "tough-cookie": "2.3.3", - "uuid": "3.2.1" + "async": "^1.4.2", + "chalk": "^1.0.0", + "configstore": "^1.0.0", + "inquirer": "^0.10.0", + "lodash.debounce": "^3.0.1", + "object-assign": "^4.0.1", + "os-name": "^1.0.0", + "request": "^2.74.0", + "tough-cookie": "^2.0.0", + "uuid": "^3.0.0" }, "dependencies": { "configstore": { @@ -3974,14 +3974,14 @@ "integrity": "sha1-w1eB0FAdJowlxUuLF/YkDopPsCE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "os-tmpdir": "1.0.2", - "osenv": "0.1.4", - "uuid": "2.0.3", - "write-file-atomic": "1.3.4", - "xdg-basedir": "2.0.0" + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "object-assign": "^4.0.1", + "os-tmpdir": "^1.0.0", + "osenv": "^0.1.0", + "uuid": "^2.0.1", + "write-file-atomic": "^1.1.2", + "xdg-basedir": "^2.0.0" }, "dependencies": { "uuid": { @@ -4012,7 +4012,7 @@ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", "dev": true, "requires": { - "loose-envify": "1.3.1" + "loose-envify": "^1.0.0" } }, "ipaddr.js": { @@ -4028,7 +4028,7 @@ "dev": true, "optional": true, "requires": { - "binary-extensions": "1.11.0" + "binary-extensions": "^1.0.0" } }, "is-buffer": { @@ -4043,7 +4043,7 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "^1.0.0" } }, "is-dotfile": { @@ -4060,7 +4060,7 @@ "dev": true, "optional": true, "requires": { - "is-primitive": "2.0.0" + "is-primitive": "^2.0.0" } }, "is-extendable": { @@ -4082,7 +4082,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-fullwidth-code-point": { @@ -4091,7 +4091,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-glob": { @@ -4100,7 +4100,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "is-my-json-valid": { @@ -4109,10 +4109,10 @@ "integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==", "dev": true, "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" } }, "is-npm": { @@ -4128,7 +4128,7 @@ "dev": true, "optional": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "is-obj": { @@ -4240,7 +4240,7 @@ "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json-stringify-safe": { @@ -4299,7 +4299,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } }, "labeled-stream-splicer": { @@ -4308,9 +4308,9 @@ "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", "dev": true, "requires": { - "inherits": "2.0.3", - "isarray": "0.0.1", - "stream-splicer": "2.0.0" + "inherits": "^2.0.1", + "isarray": "~0.0.1", + "stream-splicer": "^2.0.0" }, "dependencies": { "isarray": { @@ -4327,7 +4327,7 @@ "integrity": "sha1-cs/Ebj6NG+ZR4eu1Tqn26pbzdLs=", "dev": true, "requires": { - "package-json": "1.2.0" + "package-json": "^1.0.0" } }, "lexical-scope": { @@ -4336,7 +4336,7 @@ "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", "dev": true, "requires": { - "astw": "2.2.0" + "astw": "^2.0.0" } }, "lodash": { @@ -4357,7 +4357,7 @@ "integrity": "sha1-gSIRw3ipTMKdWqTjNGzwv846ffU=", "dev": true, "requires": { - "lodash._getnative": "3.9.1" + "lodash._getnative": "^3.0.0" } }, "lodash.memoize": { @@ -4372,7 +4372,7 @@ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "dev": true, "requires": { - "js-tokens": "3.0.2" + "js-tokens": "^3.0.0" } }, "lowercase-keys": { @@ -4387,8 +4387,8 @@ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" }, "dependencies": { "hash-base": { @@ -4397,8 +4397,8 @@ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } } } @@ -4428,19 +4428,19 @@ "dev": true, "optional": true, "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" } }, "miller-rabin": { @@ -4449,8 +4449,8 @@ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" + "bn.js": "^4.0.0", + "brorand": "^1.0.1" } }, "mime": { @@ -4471,7 +4471,7 @@ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "mime-db": "1.30.0" + "mime-db": "~1.30.0" } }, "minimalistic-assert": { @@ -4492,7 +4492,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -4516,21 +4516,21 @@ "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", "dev": true, "requires": { - "JSONStream": "1.3.2", - "browser-resolve": "1.11.2", - "cached-path-relative": "1.0.1", - "concat-stream": "1.5.2", - "defined": "1.0.0", - "detective": "4.7.1", - "duplexer2": "0.1.4", - "inherits": "2.0.3", - "parents": "1.0.1", - "readable-stream": "2.3.3", - "resolve": "1.5.0", - "stream-combiner2": "1.1.1", - "subarg": "1.0.0", - "through2": "2.0.3", - "xtend": "4.0.1" + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "cached-path-relative": "^1.0.0", + "concat-stream": "~1.5.0", + "defined": "^1.0.0", + "detective": "^4.0.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.3", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" } }, "ms": { @@ -4564,7 +4564,7 @@ "integrity": "sha1-GfYZWRUZ8JZ2mlupqG5u7sgjw88=", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "~2.0.1" } }, "nopt": { @@ -4573,7 +4573,7 @@ "integrity": "sha1-vOXEJEajKR9HYio3CrvxWPu6y/0=", "dev": true, "requires": { - "abbrev": "1.1.1" + "abbrev": "1" } }, "normalize-package-data": { @@ -4582,10 +4582,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.1" + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "normalize-path": { @@ -4594,7 +4594,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.1.0" + "remove-trailing-separator": "^1.0.1" } }, "npm-package-arg": { @@ -4603,10 +4603,10 @@ "integrity": "sha512-wJBsrf0qpypPT7A0LART18hCdyhpCMxeTtcb0X4IZO2jsP6Om7EHN1d9KSKiqD+KVH030RVNpWS9thk+pb7wzA==", "dev": true, "requires": { - "hosted-git-info": "2.5.0", - "osenv": "0.1.4", - "semver": "5.5.0", - "validate-npm-package-name": "3.0.0" + "hosted-git-info": "^2.4.2", + "osenv": "^0.1.4", + "semver": "^5.1.0", + "validate-npm-package-name": "^3.0.0" } }, "number-is-nan": { @@ -4640,8 +4640,8 @@ "dev": true, "optional": true, "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" } }, "on-finished": { @@ -4665,7 +4665,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -4704,8 +4704,8 @@ "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", "dev": true, "requires": { - "osx-release": "1.1.0", - "win-release": "1.1.1" + "osx-release": "^1.0.0", + "win-release": "^1.0.0" } }, "os-tmpdir": { @@ -4720,8 +4720,8 @@ "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "osx-release": { @@ -4730,7 +4730,7 @@ "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "^1.1.0" }, "dependencies": { "minimist": { @@ -4747,9 +4747,9 @@ "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "object-assign": "4.1.1" + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" } }, "package-json": { @@ -4758,8 +4758,8 @@ "integrity": "sha1-yOysCUInzfdqMWh07QXifMk5oOA=", "dev": true, "requires": { - "got": "3.3.1", - "registry-url": "3.1.0" + "got": "^3.2.0", + "registry-url": "^3.0.0" } }, "pako": { @@ -4774,7 +4774,7 @@ "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", "dev": true, "requires": { - "path-platform": "0.11.15" + "path-platform": "~0.11.15" } }, "parse-asn1": { @@ -4783,11 +4783,11 @@ "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", "dev": true, "requires": { - "asn1.js": "4.9.2", - "browserify-aes": "1.1.1", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.14" + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" } }, "parse-glob": { @@ -4797,10 +4797,10 @@ "dev": true, "optional": true, "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" } }, "parseurl": { @@ -4845,11 +4845,11 @@ "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", "dev": true, "requires": { - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.10" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "pegjs": { @@ -4870,7 +4870,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "plist": { @@ -4882,7 +4882,7 @@ "base64-js": "0.0.8", "util-deprecate": "1.0.2", "xmlbuilder": "4.0.0", - "xmldom": "0.1.27" + "xmldom": "0.1.x" } }, "prepend-http": { @@ -4922,7 +4922,7 @@ "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", "dev": true, "requires": { - "read": "1.0.7" + "read": "1" } }, "properties-parser": { @@ -4931,7 +4931,7 @@ "integrity": "sha1-ExbpU5/7/ZOEXjabIRAiq9R4dxo=", "dev": true, "requires": { - "string.prototype.codepointat": "0.2.0" + "string.prototype.codepointat": "^0.2.0" } }, "proxy-addr": { @@ -4940,7 +4940,7 @@ "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", "dev": true, "requires": { - "forwarded": "0.1.2", + "forwarded": "~0.1.2", "ipaddr.js": "1.5.2" } }, @@ -4950,11 +4950,11 @@ "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", "dev": true, "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "parse-asn1": "5.1.0", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1" } }, "punycode": { @@ -4994,8 +4994,8 @@ "dev": true, "optional": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "is-number": { @@ -5005,7 +5005,7 @@ "dev": true, "optional": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -5015,7 +5015,7 @@ "dev": true, "optional": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -5027,7 +5027,7 @@ "dev": true, "optional": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -5038,7 +5038,7 @@ "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.1.0" } }, "randomfill": { @@ -5047,8 +5047,8 @@ "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", "dev": true, "requires": { - "randombytes": "2.0.6", - "safe-buffer": "5.1.1" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, "range-parser": { @@ -5075,10 +5075,10 @@ "integrity": "sha1-oPYGyq4qO4YrvQ74VILAElsxX6M=", "dev": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { @@ -5095,7 +5095,7 @@ "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", "dev": true, "requires": { - "mute-stream": "0.0.7" + "mute-stream": "~0.0.4" } }, "read-all-stream": { @@ -5104,8 +5104,8 @@ "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", "dev": true, "requires": { - "pinkie-promise": "2.0.1", - "readable-stream": "2.3.3" + "pinkie-promise": "^2.0.0", + "readable-stream": "^2.0.0" } }, "read-only-stream": { @@ -5114,7 +5114,7 @@ "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", "dev": true, "requires": { - "readable-stream": "2.3.3" + "readable-stream": "^2.0.2" } }, "read-package-json": { @@ -5123,11 +5123,11 @@ "integrity": "sha512-m7/I0+tP6D34EVvSlzCtuVA4D/dHL6OpLcn2e4XVP5X57pCKGUy1JjRSBVKHWpB+vUU91sL85h84qX0MdXzBSw==", "dev": true, "requires": { - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "json-parse-better-errors": "1.0.1", - "normalize-package-data": "2.4.0", - "slash": "1.0.0" + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.0", + "normalize-package-data": "^2.0.0", + "slash": "^1.0.0" } }, "readable-stream": { @@ -5136,13 +5136,13 @@ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "readdirp": { @@ -5152,10 +5152,10 @@ "dev": true, "optional": true, "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.3", - "set-immediate-shim": "1.0.1" + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" } }, "readline2": { @@ -5164,8 +5164,8 @@ "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", "mute-stream": "0.0.5" }, "dependencies": { @@ -5183,7 +5183,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.5.0" + "resolve": "^1.1.6" } }, "regenerate": { @@ -5204,9 +5204,9 @@ "integrity": "sha1-On0GdSDLe3F2dp61/4aGkb7+EoM=", "dev": true, "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "private": "0.1.7" + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" } }, "regex-cache": { @@ -5216,7 +5216,7 @@ "dev": true, "optional": true, "requires": { - "is-equal-shallow": "0.1.3" + "is-equal-shallow": "^0.1.3" } }, "regexpu-core": { @@ -5225,9 +5225,9 @@ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "dev": true, "requires": { - "regenerate": "1.3.2", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" } }, "registry-url": { @@ -5236,7 +5236,7 @@ "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", "dev": true, "requires": { - "rc": "1.2.4" + "rc": "^1.0.1" } }, "regjsgen": { @@ -5251,7 +5251,7 @@ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { - "jsesc": "0.5.0" + "jsesc": "~0.5.0" }, "dependencies": { "jsesc": { @@ -5287,7 +5287,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "^1.0.0" } }, "request": { @@ -5296,26 +5296,26 @@ "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", "dev": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.4.3", - "uuid": "3.2.1" + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "qs": "~6.3.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1", + "uuid": "^3.0.0" }, "dependencies": { "qs": { @@ -5338,7 +5338,7 @@ "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "restore-cursor": { @@ -5347,8 +5347,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" } }, "rimraf": { @@ -5357,7 +5357,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "ripemd160": { @@ -5366,8 +5366,8 @@ "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", "dev": true, "requires": { - "hash-base": "2.0.2", - "inherits": "2.0.3" + "hash-base": "^2.0.0", + "inherits": "^2.0.1" } }, "run-async": { @@ -5376,7 +5376,7 @@ "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", "dev": true, "requires": { - "once": "1.4.0" + "once": "^1.3.0" } }, "rx-lite": { @@ -5409,7 +5409,7 @@ "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", "dev": true, "requires": { - "semver": "5.5.0" + "semver": "^5.0.3" } }, "send": { @@ -5419,18 +5419,18 @@ "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.1", + "destroy": "~1.0.4", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.2", + "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.3.1" + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.3.1" }, "dependencies": { "debug": { @@ -5450,9 +5450,9 @@ "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", "dev": true, "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.2", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", "send": "0.16.1" } }, @@ -5475,8 +5475,8 @@ "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "shasum": { @@ -5485,8 +5485,8 @@ "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", "dev": true, "requires": { - "json-stable-stringify": "0.0.1", - "sha.js": "2.4.10" + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" } }, "shell-quote": { @@ -5495,10 +5495,10 @@ "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", "dev": true, "requires": { - "array-filter": "0.0.1", - "array-map": "0.0.0", - "array-reduce": "0.0.0", - "jsonify": "0.0.0" + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" } }, "shelljs": { @@ -5532,7 +5532,7 @@ "requires": { "base64-js": "1.1.2", "xmlbuilder": "8.2.2", - "xmldom": "0.1.27" + "xmldom": "0.1.x" } }, "xmlbuilder": { @@ -5561,7 +5561,7 @@ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "source-map": { @@ -5576,7 +5576,7 @@ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.5.6" } }, "spdx-correct": { @@ -5585,7 +5585,7 @@ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", "dev": true, "requires": { - "spdx-license-ids": "1.2.2" + "spdx-license-ids": "^1.0.2" } }, "spdx-expression-parse": { @@ -5606,14 +5606,14 @@ "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", "dev": true, "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" }, "dependencies": { "assert-plus": { @@ -5636,8 +5636,8 @@ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3" + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, "stream-buffers": { @@ -5652,8 +5652,8 @@ "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", "dev": true, "requires": { - "duplexer2": "0.1.4", - "readable-stream": "2.3.3" + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" } }, "stream-http": { @@ -5662,11 +5662,11 @@ "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", "dev": true, "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.3", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, "stream-shift": { @@ -5681,8 +5681,8 @@ "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3" + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" } }, "string-length": { @@ -5691,7 +5691,7 @@ "integrity": "sha1-VpcPscOFWOnnC3KL894mmsRa36w=", "dev": true, "requires": { - "strip-ansi": "3.0.1" + "strip-ansi": "^3.0.0" } }, "string.prototype.codepointat": { @@ -5706,7 +5706,7 @@ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "stringstream": { @@ -5721,7 +5721,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -5736,7 +5736,7 @@ "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "dev": true, "requires": { - "minimist": "1.2.0" + "minimist": "^1.1.0" }, "dependencies": { "minimist": { @@ -5759,7 +5759,7 @@ "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=", "dev": true, "requires": { - "acorn": "4.0.13" + "acorn": "^4.0.3" }, "dependencies": { "acorn": { @@ -5776,9 +5776,9 @@ "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, "through": { @@ -5793,8 +5793,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" } }, "timed-out": { @@ -5809,7 +5809,7 @@ "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", "dev": true, "requires": { - "process": "0.11.10" + "process": "~0.11.0" } }, "to-arraybuffer": { @@ -5830,7 +5830,7 @@ "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", "dev": true, "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" } }, "trim-right": { @@ -5865,7 +5865,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.17" + "mime-types": "~2.1.15" } }, "typedarray": { @@ -5891,7 +5891,7 @@ "resolved": "https://registry.npmjs.org/universal-router/-/universal-router-5.1.0.tgz", "integrity": "sha512-Es8QWjX6CAqoWJ8oD3KgGHYfLkqvhzJr01J9tMgD8TN5ixyOHmopZTem7s439fYsDVZ1pFbcnplab9/w4+vbYQ==", "requires": { - "path-to-regexp": "2.1.0" + "path-to-regexp": "^2.1.0" }, "dependencies": { "path-to-regexp": { @@ -5919,13 +5919,13 @@ "integrity": "sha1-B7XcIGazYnqztPUwEw9+3doHpMw=", "dev": true, "requires": { - "chalk": "1.1.3", - "configstore": "1.4.0", - "is-npm": "1.0.0", - "latest-version": "1.0.1", - "repeating": "1.1.3", - "semver-diff": "2.1.0", - "string-length": "1.0.1" + "chalk": "^1.0.0", + "configstore": "^1.0.0", + "is-npm": "^1.0.0", + "latest-version": "^1.0.0", + "repeating": "^1.1.2", + "semver-diff": "^2.0.0", + "string-length": "^1.0.0" }, "dependencies": { "configstore": { @@ -5934,14 +5934,14 @@ "integrity": "sha1-w1eB0FAdJowlxUuLF/YkDopPsCE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "os-tmpdir": "1.0.2", - "osenv": "0.1.4", - "uuid": "2.0.3", - "write-file-atomic": "1.3.4", - "xdg-basedir": "2.0.0" + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "object-assign": "^4.0.1", + "os-tmpdir": "^1.0.0", + "osenv": "^0.1.0", + "uuid": "^2.0.1", + "write-file-atomic": "^1.1.2", + "xdg-basedir": "^2.0.0" } }, "repeating": { @@ -5950,7 +5950,7 @@ "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "^1.0.0" } } } @@ -6020,7 +6020,7 @@ "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { - "user-home": "1.1.1" + "user-home": "^1.1.1" } }, "valid-identifier": { @@ -6035,8 +6035,8 @@ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", "dev": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "spdx-correct": "~1.0.0", + "spdx-expression-parse": "~1.0.0" } }, "validate-npm-package-name": { @@ -6045,7 +6045,7 @@ "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", "dev": true, "requires": { - "builtins": "1.0.3" + "builtins": "^1.0.3" } }, "vary": { @@ -6060,9 +6060,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" }, "dependencies": { "assert-plus": { @@ -6088,7 +6088,7 @@ "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", "dev": true, "requires": { - "semver": "5.5.0" + "semver": "^5.0.1" } }, "wrappy": { @@ -6103,9 +6103,9 @@ "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "slide": "1.1.6" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" } }, "xcode": { @@ -6114,8 +6114,8 @@ "integrity": "sha1-4fWxRDJF3tOMGAeW3xoQ/e2ghOw=", "dev": true, "requires": { - "pegjs": "0.10.0", - "simple-plist": "0.2.1", + "pegjs": "^0.10.0", + "simple-plist": "^0.2.1", "uuid": "3.0.1" }, "dependencies": { @@ -6133,7 +6133,7 @@ "integrity": "sha1-7byQPMOF/ARSPZZqM1UEtVBNG9I=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.0" } }, "xmlbuilder": { @@ -6142,7 +6142,7 @@ "integrity": "sha1-mLj2UcowqmJANvEn0RzGbce5B6M=", "dev": true, "requires": { - "lodash": "3.10.1" + "lodash": "^3.5.0" }, "dependencies": { "lodash": { diff --git a/plugin.xml b/plugin.xml index ba425e8..c734c43 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,7 +1,7 @@ + version="1.1.0"> @@ -27,55 +27,22 @@ + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ios/GCDWebServer/Core/GCDWebServer.h b/src/ios/GCDWebServer/Core/GCDWebServer.h deleted file mode 100755 index beec7b8..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServer.h +++ /dev/null @@ -1,623 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -#import "GCDWebServerRequest.h" -#import "GCDWebServerResponse.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerMatchBlock is called for every handler added to the - * GCDWebServer whenever a new HTTP request has started (i.e. HTTP headers have - * been received). The block is passed the basic info for the request (HTTP method, - * URL, headers...) and must decide if it wants to handle it or not. - * - * If the handler can handle the request, the block must return a new - * GCDWebServerRequest instance created with the same basic info. - * Otherwise, it simply returns nil. - */ -typedef GCDWebServerRequest* _Nullable (^GCDWebServerMatchBlock)(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery); - -/** - * The GCDWebServerProcessBlock is called after the HTTP request has been fully - * received (i.e. the entire HTTP body has been read). The block is passed the - * GCDWebServerRequest created at the previous step by the GCDWebServerMatchBlock. - * - * The block must return a GCDWebServerResponse or nil on error, which will - * result in a 500 HTTP status code returned to the client. It's however - * recommended to return a GCDWebServerErrorResponse on error so more useful - * information can be returned to the client. - */ -typedef GCDWebServerResponse* _Nullable (^GCDWebServerProcessBlock)(__kindof GCDWebServerRequest* request); - -/** - * The GCDWebServerAsynchronousProcessBlock works like the GCDWebServerProcessBlock - * except the GCDWebServerResponse can be returned to the server at a later time - * allowing for asynchronous generation of the response. - * - * The block must eventually call "completionBlock" passing a GCDWebServerResponse - * or nil on error, which will result in a 500 HTTP status code returned to the client. - * It's however recommended to return a GCDWebServerErrorResponse on error so more - * useful information can be returned to the client. - */ -typedef void (^GCDWebServerCompletionBlock)(GCDWebServerResponse* _Nullable response); -typedef void (^GCDWebServerAsyncProcessBlock)(__kindof GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock); - -/** - * The port used by the GCDWebServer (NSNumber / NSUInteger). - * - * The default value is 0 i.e. let the OS pick a random port. - */ -extern NSString* const GCDWebServerOption_Port; - -/** - * The Bonjour name used by the GCDWebServer (NSString). If set to an empty string, - * the name will automatically take the value of the GCDWebServerOption_ServerName - * option. If this option is set to nil, Bonjour will be disabled. - * - * The default value is nil. - */ -extern NSString* const GCDWebServerOption_BonjourName; - -/** - * The Bonjour service type used by the GCDWebServer (NSString). - * - * The default value is "_http._tcp", the service type for HTTP web servers. - */ -extern NSString* const GCDWebServerOption_BonjourType; - -/** - * Request a port mapping in the NAT gateway (NSNumber / BOOL). - * - * This uses the DNSService API under the hood which supports IPv4 mappings only. - * - * The default value is NO. - * - * @warning The external port set up by the NAT gateway may be different than - * the one used by the GCDWebServer. - */ -extern NSString* const GCDWebServerOption_RequestNATPortMapping; - -/** - * Only accept HTTP requests coming from localhost i.e. not from the outside - * network (NSNumber / BOOL). - * - * The default value is NO. - * - * @warning Bonjour and NAT port mapping should be disabled if using this option - * since the server will not be reachable from the outside network anyway. - */ -extern NSString* const GCDWebServerOption_BindToLocalhost; - -/** - * The maximum number of incoming HTTP requests that can be queued waiting to - * be handled before new ones are dropped (NSNumber / NSUInteger). - * - * The default value is 16. - */ -extern NSString* const GCDWebServerOption_MaxPendingConnections; - -/** - * The value for "Server" HTTP header used by the GCDWebServer (NSString). - * - * The default value is the GCDWebServer class name. - */ -extern NSString* const GCDWebServerOption_ServerName; - -/** - * The authentication method used by the GCDWebServer - * (one of "GCDWebServerAuthenticationMethod_..."). - * - * The default value is nil i.e. authentication is disabled. - */ -extern NSString* const GCDWebServerOption_AuthenticationMethod; - -/** - * The authentication realm used by the GCDWebServer (NSString). - * - * The default value is the same as the GCDWebServerOption_ServerName option. - */ -extern NSString* const GCDWebServerOption_AuthenticationRealm; - -/** - * The authentication accounts used by the GCDWebServer - * (NSDictionary of username / password pairs). - * - * The default value is nil i.e. no accounts. - */ -extern NSString* const GCDWebServerOption_AuthenticationAccounts; - -/** - * The class used by the GCDWebServer when instantiating GCDWebServerConnection - * (subclass of GCDWebServerConnection). - * - * The default value is the GCDWebServerConnection class. - */ -extern NSString* const GCDWebServerOption_ConnectionClass; - -/** - * Allow the GCDWebServer to pretend "HEAD" requests are actually "GET" ones - * and automatically discard the HTTP body of the response (NSNumber / BOOL). - * - * The default value is YES. - */ -extern NSString* const GCDWebServerOption_AutomaticallyMapHEADToGET; - -/** - * The interval expressed in seconds used by the GCDWebServer to decide how to - * coalesce calls to -webServerDidConnect: and -webServerDidDisconnect: - * (NSNumber / double). Coalescing will be disabled if the interval is <= 0.0. - * - * The default value is 1.0 second. - */ -extern NSString* const GCDWebServerOption_ConnectedStateCoalescingInterval; - -/** - * Set the dispatch queue priority on which server connection will be - * run (NSNumber / long). - * - * - * The default value is DISPATCH_QUEUE_PRIORITY_DEFAULT. - */ -extern NSString* const GCDWebServerOption_DispatchQueuePriority; - -#if TARGET_OS_IPHONE - -/** - * Enables the GCDWebServer to automatically suspend itself (as if -stop was - * called) when the iOS app goes into the background and the last - * GCDWebServerConnection is closed, then resume itself (as if -start was called) - * when the iOS app comes back to the foreground (NSNumber / BOOL). - * - * See the README.md file for more information about this option. - * - * The default value is YES. - * - * @warning The running property will be NO while the GCDWebServer is suspended. - */ -extern NSString* const GCDWebServerOption_AutomaticallySuspendInBackground; - -#endif - -/** - * HTTP Basic Authentication scheme (see https://tools.ietf.org/html/rfc2617). - * - * @warning Use of this authentication scheme is not recommended as the - * passwords are sent in clear. - */ -extern NSString* const GCDWebServerAuthenticationMethod_Basic; - -/** - * HTTP Digest Access Authentication scheme (see https://tools.ietf.org/html/rfc2617). - */ -extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; - -@class GCDWebServer; - -/** - * Delegate methods for GCDWebServer. - * - * @warning These methods are always called on the main thread in a serialized way. - */ -@protocol GCDWebServerDelegate -@optional - -/** - * This method is called after the server has successfully started. - */ -- (void)webServerDidStart:(GCDWebServer*)server; - -/** - * This method is called after the Bonjour registration for the server has - * successfully completed. - * - * Use the "bonjourServerURL" property to retrieve the Bonjour address of the - * server. - */ -- (void)webServerDidCompleteBonjourRegistration:(GCDWebServer*)server; - -/** - * This method is called after the NAT port mapping for the server has been - * updated. - * - * Use the "publicServerURL" property to retrieve the public address of the - * server. - */ -- (void)webServerDidUpdateNATPortMapping:(GCDWebServer*)server; - -/** - * This method is called when the first GCDWebServerConnection is opened by the - * server to serve a series of HTTP requests. - * - * A series of HTTP requests is considered ongoing as long as new HTTP requests - * keep coming (and new GCDWebServerConnection instances keep being opened), - * until before the last HTTP request has been responded to (and the - * corresponding last GCDWebServerConnection closed). - */ -- (void)webServerDidConnect:(GCDWebServer*)server; - -/** - * This method is called when the last GCDWebServerConnection is closed after - * the server has served a series of HTTP requests. - * - * The GCDWebServerOption_ConnectedStateCoalescingInterval option can be used - * to have the server wait some extra delay before considering that the series - * of HTTP requests has ended (in case there some latency between consecutive - * requests). This effectively coalesces the calls to -webServerDidConnect: - * and -webServerDidDisconnect:. - */ -- (void)webServerDidDisconnect:(GCDWebServer*)server; - -/** - * This method is called after the server has stopped. - */ -- (void)webServerDidStop:(GCDWebServer*)server; - -@end - -/** - * The GCDWebServer class listens for incoming HTTP requests on a given port, - * then passes each one to a "handler" capable of generating an HTTP response - * for it, which is then sent back to the client. - * - * GCDWebServer instances can be created and used from any thread but it's - * recommended to have the main thread's runloop be running so internal callbacks - * can be handled e.g. for Bonjour registration. - * - * See the README.md file for more information about the architecture of GCDWebServer. - */ -@interface GCDWebServer : NSObject - -/** - * Sets the delegate for the server. - */ -@property(nonatomic, weak, nullable) id delegate; - -/** - * Returns YES if the server is currently running. - */ -@property(nonatomic, readonly, getter=isRunning) BOOL running; - -/** - * Returns the port used by the server. - * - * @warning This property is only valid if the server is running. - */ -@property(nonatomic, readonly) NSUInteger port; - -/** - * Returns the Bonjour name used by the server. - * - * @warning This property is only valid if the server is running and Bonjour - * registration has successfully completed, which can take up to a few seconds. - */ -@property(nonatomic, readonly, nullable) NSString* bonjourName; - -/** - * Returns the Bonjour service type used by the server. - * - * @warning This property is only valid if the server is running and Bonjour - * registration has successfully completed, which can take up to a few seconds. - */ -@property(nonatomic, readonly, nullable) NSString* bonjourType; - -/** - * This method is the designated initializer for the class. - */ -- (instancetype)init; - -/** - * Adds to the server a handler that generates responses synchronously when handling incoming HTTP requests. - * - * Handlers are called in a LIFO queue, so if multiple handlers can potentially - * respond to a given request, the latest added one wins. - * - * @warning Addling handlers while the server is running is not allowed. - */ -- (void)addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock processBlock:(GCDWebServerProcessBlock)processBlock; - -/** - * Adds to the server a handler that generates responses asynchronously when handling incoming HTTP requests. - * - * Handlers are called in a LIFO queue, so if multiple handlers can potentially - * respond to a given request, the latest added one wins. - * - * @warning Addling handlers while the server is running is not allowed. - */ -- (void)addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock asyncProcessBlock:(GCDWebServerAsyncProcessBlock)processBlock; - -/** - * Removes all handlers previously added to the server. - * - * @warning Removing handlers while the server is running is not allowed. - */ -- (void)removeAllHandlers; - -/** - * Starts the server with explicit options. This method is the designated way - * to start the server. - * - * Returns NO if the server failed to start and sets "error" argument if not NULL. - */ -- (BOOL)startWithOptions:(nullable NSDictionary*)options error:(NSError** _Nullable)error; - -/** - * Stops the server and prevents it to accepts new HTTP requests. - * - * @warning Stopping the server does not abort GCDWebServerConnection instances - * currently handling already received HTTP requests. These connections will - * continue to execute normally until completion. - */ -- (void)stop; - -@end - -@interface GCDWebServer (Extensions) - -/** - * Returns the server's URL. - * - * @warning This property is only valid if the server is running. - */ -@property(nonatomic, readonly, nullable) NSURL* serverURL; - -/** - * Returns the server's Bonjour URL. - * - * @warning This property is only valid if the server is running and Bonjour - * registration has successfully completed, which can take up to a few seconds. - * Also be aware this property will not automatically update if the Bonjour hostname - * has been dynamically changed after the server started running (this should be rare). - */ -@property(nonatomic, readonly, nullable) NSURL* bonjourServerURL; - -/** - * Returns the server's public URL. - * - * @warning This property is only valid if the server is running and NAT port - * mapping is active. - */ -@property(nonatomic, readonly, nullable) NSURL* publicServerURL; - -/** - * Starts the server on port 8080 (OS X & iOS Simulator) or port 80 (iOS) - * using the default Bonjour name. - * - * Returns NO if the server failed to start. - */ -- (BOOL)start; - -/** - * Starts the server on a given port and with a specific Bonjour name. - * Pass a nil Bonjour name to disable Bonjour entirely or an empty string to - * use the default name. - * - * Returns NO if the server failed to start. - */ -- (BOOL)startWithPort:(NSUInteger)port bonjourName:(nullable NSString*)name; - -#if !TARGET_OS_IPHONE - -/** - * Runs the server synchronously using -startWithPort:bonjourName: until a - * SIGINT signal is received i.e. Ctrl-C. This method is intended to be used - * by command line tools. - * - * Returns NO if the server failed to start. - * - * @warning This method must be used from the main thread only. - */ -- (BOOL)runWithPort:(NSUInteger)port bonjourName:(nullable NSString*)name; - -/** - * Runs the server synchronously using -startWithOptions: until a SIGTERM or - * SIGINT signal is received i.e. Ctrl-C in Terminal. This method is intended to - * be used by command line tools. - * - * Returns NO if the server failed to start and sets "error" argument if not NULL. - * - * @warning This method must be used from the main thread only. - */ -- (BOOL)runWithOptions:(nullable NSDictionary*)options error:(NSError** _Nullable)error; - -#endif - -@end - -@interface GCDWebServer (Handlers) - -/** - * Adds a default handler to the server to handle all incoming HTTP requests - * with a given HTTP method and generate responses synchronously. - */ -- (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block; - -/** - * Adds a default handler to the server to handle all incoming HTTP requests - * with a given HTTP method and generate responses asynchronously. - */ -- (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block; - -/** - * Adds a handler to the server to handle incoming HTTP requests with a given - * HTTP method and a specific case-insensitive path and generate responses - * synchronously. - */ -- (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block; - -/** - * Adds a handler to the server to handle incoming HTTP requests with a given - * HTTP method and a specific case-insensitive path and generate responses - * asynchronously. - */ -- (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block; - -/** - * Adds a handler to the server to handle incoming HTTP requests with a given - * HTTP method and a path matching a case-insensitive regular expression and - * generate responses synchronously. - */ -- (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block; - -/** - * Adds a handler to the server to handle incoming HTTP requests with a given - * HTTP method and a path matching a case-insensitive regular expression and - * generate responses asynchronously. - */ -- (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block; - -@end - -@interface GCDWebServer (GETHandlers) - -/** - * Adds a handler to the server to respond to incoming "GET" HTTP requests - * with a specific case-insensitive path with in-memory data. - */ -- (void)addGETHandlerForPath:(NSString*)path staticData:(NSData*)staticData contentType:(nullable NSString*)contentType cacheAge:(NSUInteger)cacheAge; - -/** - * Adds a handler to the server to respond to incoming "GET" HTTP requests - * with a specific case-insensitive path with a file. - */ -- (void)addGETHandlerForPath:(NSString*)path filePath:(NSString*)filePath isAttachment:(BOOL)isAttachment cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests; - -/** - * Adds a handler to the server to respond to incoming "GET" HTTP requests - * with a case-insensitive path inside a base path with the corresponding file - * inside a local directory. If no local file matches the request path, a 401 - * HTTP status code is returned to the client. - * - * The "indexFilename" argument allows to specify an "index" file name to use - * when the request path corresponds to a directory. - */ -- (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(nullable NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests; - -@end - -/** - * GCDWebServer provides its own built-in logging facility which is used by - * default. It simply sends log messages to stderr assuming it is connected - * to a terminal type device. - * - * GCDWebServer is also compatible with a limited set of third-party logging - * facilities. If one of them is available at compile time, GCDWebServer will - * automatically use it in place of the built-in one. - * - * Currently supported third-party logging facilities are: - * - XLFacility (by the same author as GCDWebServer): https://github.com/swisspol/XLFacility - * - CocoaLumberjack: https://github.com/CocoaLumberjack/CocoaLumberjack - * - * For both the built-in logging facility and CocoaLumberjack, the default - * logging level is INFO (or DEBUG if the preprocessor constant "DEBUG" - * evaluates to non-zero at compile time). - * - * It's possible to have GCDWebServer use a custom logging facility by defining - * the "__GCDWEBSERVER_LOGGING_HEADER__" preprocessor constant in Xcode build - * settings to the name of a custom header file (escaped like \"MyLogging.h\"). - * This header file must define the following set of macros: - * - * GWS_LOG_DEBUG(...) - * GWS_LOG_VERBOSE(...) - * GWS_LOG_INFO(...) - * GWS_LOG_WARNING(...) - * GWS_LOG_ERROR(...) - * - * IMPORTANT: These macros must behave like NSLog(). Furthermore the GWS_LOG_DEBUG() - * macro should not do anything unless the preprocessor constant "DEBUG" evaluates - * to non-zero. - * - * The logging methods below send log messages to the same logging facility - * used by GCDWebServer. They can be used for consistency wherever you interact - * with GCDWebServer in your code (e.g. in the implementation of handlers). - */ -@interface GCDWebServer (Logging) - -/** - * Sets the log level of the logging facility below which log messages are discarded. - * - * @warning The interpretation of the "level" argument depends on the logging - * facility used at compile time. - * - * If using the built-in logging facility, the log levels are as follow: - * DEBUG = 0 - * VERBOSE = 1 - * INFO = 2 - * WARNING = 3 - * ERROR = 4 - */ -+ (void)setLogLevel:(int)level; - -/** - * Logs a message to the logging facility at the VERBOSE level. - */ -- (void)logVerbose:(NSString*)format, ... NS_FORMAT_FUNCTION(1, 2); - -/** - * Logs a message to the logging facility at the INFO level. - */ -- (void)logInfo:(NSString*)format, ... NS_FORMAT_FUNCTION(1, 2); - -/** - * Logs a message to the logging facility at the WARNING level. - */ -- (void)logWarning:(NSString*)format, ... NS_FORMAT_FUNCTION(1, 2); - -/** - * Logs a message to the logging facility at the ERROR level. - */ -- (void)logError:(NSString*)format, ... NS_FORMAT_FUNCTION(1, 2); - -@end - -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ - -@interface GCDWebServer (Testing) - -/** - * Activates recording of HTTP requests and responses which create files in the - * current directory containing the raw data for all requests and responses. - * - * @warning The current directory must not contain any prior recording files. - */ -@property(nonatomic, getter=isRecordingEnabled) BOOL recordingEnabled; - -/** - * Runs tests by playing back pre-recorded HTTP requests in the given directory - * and comparing the generated responses with the pre-recorded ones. - * - * Returns the number of failed tests or -1 if server failed to start. - */ -- (NSInteger)runTestsWithOptions:(nullable NSDictionary*)options inDirectory:(NSString*)path; - -@end - -#endif - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Core/GCDWebServer.m b/src/ios/GCDWebServer/Core/GCDWebServer.m deleted file mode 100755 index 837c083..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServer.m +++ /dev/null @@ -1,1320 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import -#if TARGET_OS_IPHONE -#import -#else -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ -#import -#endif -#endif -#import -#import - -#import "GCDWebServerPrivate.h" - -#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR -#define kDefaultPort 80 -#else -#define kDefaultPort 8080 -#endif - -#define kBonjourResolutionTimeout 5.0 - -NSString* const GCDWebServerOption_Port = @"Port"; -NSString* const GCDWebServerOption_BonjourName = @"BonjourName"; -NSString* const GCDWebServerOption_BonjourType = @"BonjourType"; -NSString* const GCDWebServerOption_RequestNATPortMapping = @"RequestNATPortMapping"; -NSString* const GCDWebServerOption_BindToLocalhost = @"BindToLocalhost"; -NSString* const GCDWebServerOption_MaxPendingConnections = @"MaxPendingConnections"; -NSString* const GCDWebServerOption_ServerName = @"ServerName"; -NSString* const GCDWebServerOption_AuthenticationMethod = @"AuthenticationMethod"; -NSString* const GCDWebServerOption_AuthenticationRealm = @"AuthenticationRealm"; -NSString* const GCDWebServerOption_AuthenticationAccounts = @"AuthenticationAccounts"; -NSString* const GCDWebServerOption_ConnectionClass = @"ConnectionClass"; -NSString* const GCDWebServerOption_AutomaticallyMapHEADToGET = @"AutomaticallyMapHEADToGET"; -NSString* const GCDWebServerOption_ConnectedStateCoalescingInterval = @"ConnectedStateCoalescingInterval"; -NSString* const GCDWebServerOption_DispatchQueuePriority = @"DispatchQueuePriority"; -#if TARGET_OS_IPHONE -NSString* const GCDWebServerOption_AutomaticallySuspendInBackground = @"AutomaticallySuspendInBackground"; -#endif - -NSString* const GCDWebServerAuthenticationMethod_Basic = @"Basic"; -NSString* const GCDWebServerAuthenticationMethod_DigestAccess = @"DigestAccess"; - -#if defined(__GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__) -#if DEBUG -GCDWebServerLoggingLevel GCDWebServerLogLevel = kGCDWebServerLoggingLevel_Debug; -#else -GCDWebServerLoggingLevel GCDWebServerLogLevel = kGCDWebServerLoggingLevel_Info; -#endif -#elif defined(__GCDWEBSERVER_LOGGING_FACILITY_COCOALUMBERJACK__) -#if DEBUG -DDLogLevel GCDWebServerLogLevel = DDLogLevelDebug; -#else -DDLogLevel GCDWebServerLogLevel = DDLogLevelInfo; -#endif -#endif - -#if !TARGET_OS_IPHONE -static BOOL _run; -#endif - -#ifdef __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__ - -void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) { - static const char* levelNames[] = {"DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR"}; - static int enableLogging = -1; - if (enableLogging < 0) { - enableLogging = (isatty(STDERR_FILENO) ? 1 : 0); - } - if (enableLogging) { - va_list arguments; - va_start(arguments, format); - NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments]; - va_end(arguments); - fprintf(stderr, "[%s] %s\n", levelNames[level], [message UTF8String]); - } -} - -#endif - -#if !TARGET_OS_IPHONE - -static void _SignalHandler(int signal) { - _run = NO; - printf("\n"); -} - -#endif - -#if !TARGET_OS_IPHONE || defined(__GCDWEBSERVER_ENABLE_TESTING__) - -// This utility function is used to ensure scheduled callbacks on the main thread are called when running the server synchronously -// https://developer.apple.com/library/mac/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html -// The main queue works with the application’s run loop to interleave the execution of queued tasks with the execution of other event sources attached to the run loop -// TODO: Ensure all scheduled blocks on the main queue are also executed -static void _ExecuteMainThreadRunLoopSources() { - SInt32 result; - do { - result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, true); - } while (result == kCFRunLoopRunHandledSource); -} - -#endif - -@implementation GCDWebServerHandler - -- (instancetype)initWithMatchBlock:(GCDWebServerMatchBlock _Nonnull)matchBlock asyncProcessBlock:(GCDWebServerAsyncProcessBlock _Nonnull)processBlock { - if ((self = [super init])) { - _matchBlock = [matchBlock copy]; - _asyncProcessBlock = [processBlock copy]; - } - return self; -} - -@end - -@implementation GCDWebServer { - dispatch_queue_t _syncQueue; - dispatch_group_t _sourceGroup; - NSMutableArray* _handlers; - NSInteger _activeConnections; // Accessed through _syncQueue only - BOOL _connected; // Accessed on main thread only - CFRunLoopTimerRef _disconnectTimer; // Accessed on main thread only - - NSDictionary* _options; - NSMutableDictionary* _authenticationBasicAccounts; - NSMutableDictionary* _authenticationDigestAccounts; - Class _connectionClass; - CFTimeInterval _disconnectDelay; - dispatch_source_t _source4; - dispatch_source_t _source6; - CFNetServiceRef _registrationService; - CFNetServiceRef _resolutionService; - DNSServiceRef _dnsService; - CFSocketRef _dnsSocket; - CFRunLoopSourceRef _dnsSource; - NSString* _dnsAddress; - NSUInteger _dnsPort; - BOOL _bindToLocalhost; -#if TARGET_OS_IPHONE - BOOL _suspendInBackground; - UIBackgroundTaskIdentifier _backgroundTask; -#endif -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ - BOOL _recording; -#endif -} - -+ (void)initialize { - GCDWebServerInitializeFunctions(); -} - -- (instancetype)init { - if ((self = [super init])) { - _syncQueue = dispatch_queue_create([NSStringFromClass([self class]) UTF8String], DISPATCH_QUEUE_SERIAL); - _sourceGroup = dispatch_group_create(); - _handlers = [[NSMutableArray alloc] init]; -#if TARGET_OS_IPHONE - _backgroundTask = UIBackgroundTaskInvalid; -#endif - } - return self; -} - -- (void)dealloc { - GWS_DCHECK(_connected == NO); - GWS_DCHECK(_activeConnections == 0); - GWS_DCHECK(_options == nil); // The server can never be dealloc'ed while running because of the retain-cycle with the dispatch source - GWS_DCHECK(_disconnectTimer == NULL); // The server can never be dealloc'ed while the disconnect timer is pending because of the retain-cycle - -#if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE - dispatch_release(_sourceGroup); - dispatch_release(_syncQueue); -#endif -} - -#if TARGET_OS_IPHONE - -// Always called on main thread -- (void)_startBackgroundTask { - GWS_DCHECK([NSThread isMainThread]); - if (_backgroundTask == UIBackgroundTaskInvalid) { - GWS_LOG_DEBUG(@"Did start background task"); - _backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - - GWS_LOG_WARNING(@"Application is being suspended while %@ is still connected", [self class]); - [self _endBackgroundTask]; - - }]; - } else { - GWS_DNOT_REACHED(); - } -} - -#endif - -// Always called on main thread -- (void)_didConnect { - GWS_DCHECK([NSThread isMainThread]); - GWS_DCHECK(_connected == NO); - _connected = YES; - GWS_LOG_DEBUG(@"Did connect"); - -#if TARGET_OS_IPHONE - if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) { - [self _startBackgroundTask]; - } -#endif - - if ([_delegate respondsToSelector:@selector(webServerDidConnect:)]) { - [_delegate webServerDidConnect:self]; - } -} - -- (void)willStartConnection:(GCDWebServerConnection*)connection { - dispatch_sync(_syncQueue, ^{ - - GWS_DCHECK(_activeConnections >= 0); - if (_activeConnections == 0) { - dispatch_async(dispatch_get_main_queue(), ^{ - if (_disconnectTimer) { - CFRunLoopTimerInvalidate(_disconnectTimer); - CFRelease(_disconnectTimer); - _disconnectTimer = NULL; - } - if (_connected == NO) { - [self _didConnect]; - } - }); - } - _activeConnections += 1; - - }); -} - -#if TARGET_OS_IPHONE - -// Always called on main thread -- (void)_endBackgroundTask { - GWS_DCHECK([NSThread isMainThread]); - if (_backgroundTask != UIBackgroundTaskInvalid) { - if (_suspendInBackground && ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) && _source4) { - [self _stop]; - } - [[UIApplication sharedApplication] endBackgroundTask:_backgroundTask]; - _backgroundTask = UIBackgroundTaskInvalid; - GWS_LOG_DEBUG(@"Did end background task"); - } -} - -#endif - -// Always called on main thread -- (void)_didDisconnect { - GWS_DCHECK([NSThread isMainThread]); - GWS_DCHECK(_connected == YES); - _connected = NO; - GWS_LOG_DEBUG(@"Did disconnect"); - -#if TARGET_OS_IPHONE - [self _endBackgroundTask]; -#endif - - if ([_delegate respondsToSelector:@selector(webServerDidDisconnect:)]) { - [_delegate webServerDidDisconnect:self]; - } -} - -- (void)didEndConnection:(GCDWebServerConnection*)connection { - dispatch_sync(_syncQueue, ^{ - GWS_DCHECK(_activeConnections > 0); - _activeConnections -= 1; - if (_activeConnections == 0) { - dispatch_async(dispatch_get_main_queue(), ^{ - if ((_disconnectDelay > 0.0) && (_source4 != NULL)) { - if (_disconnectTimer) { - CFRunLoopTimerInvalidate(_disconnectTimer); - CFRelease(_disconnectTimer); - } - _disconnectTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + _disconnectDelay, 0.0, 0, 0, ^(CFRunLoopTimerRef timer) { - GWS_DCHECK([NSThread isMainThread]); - [self _didDisconnect]; - CFRelease(_disconnectTimer); - _disconnectTimer = NULL; - }); - CFRunLoopAddTimer(CFRunLoopGetMain(), _disconnectTimer, kCFRunLoopCommonModes); - } else { - [self _didDisconnect]; - } - }); - } - }); -} - -- (NSString*)bonjourName { - CFStringRef name = _resolutionService ? CFNetServiceGetName(_resolutionService) : NULL; - return name && CFStringGetLength(name) ? CFBridgingRelease(CFStringCreateCopy(kCFAllocatorDefault, name)) : nil; -} - -- (NSString*)bonjourType { - CFStringRef type = _resolutionService ? CFNetServiceGetType(_resolutionService) : NULL; - return type && CFStringGetLength(type) ? CFBridgingRelease(CFStringCreateCopy(kCFAllocatorDefault, type)) : nil; -} - -- (void)addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock processBlock:(GCDWebServerProcessBlock)processBlock { - [self addHandlerWithMatchBlock:matchBlock - asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { - completionBlock(processBlock(request)); - }]; -} - -- (void)addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock asyncProcessBlock:(GCDWebServerAsyncProcessBlock)processBlock { - GWS_DCHECK(_options == nil); - GCDWebServerHandler* handler = [[GCDWebServerHandler alloc] initWithMatchBlock:matchBlock asyncProcessBlock:processBlock]; - [_handlers insertObject:handler atIndex:0]; -} - -- (void)removeAllHandlers { - GWS_DCHECK(_options == nil); - [_handlers removeAllObjects]; -} - -static void _NetServiceRegisterCallBack(CFNetServiceRef service, CFStreamError* error, void* info) { - GWS_DCHECK([NSThread isMainThread]); - @autoreleasepool { - if (error->error) { - GWS_LOG_ERROR(@"Bonjour registration error %i (domain %i)", (int)error->error, (int)error->domain); - } else { - GCDWebServer* server = (__bridge GCDWebServer*)info; - GWS_LOG_VERBOSE(@"Bonjour registration complete for %@", [server class]); - if (!CFNetServiceResolveWithTimeout(server->_resolutionService, kBonjourResolutionTimeout, NULL)) { - GWS_LOG_ERROR(@"Failed starting Bonjour resolution"); - GWS_DNOT_REACHED(); - } - } - } -} - -static void _NetServiceResolveCallBack(CFNetServiceRef service, CFStreamError* error, void* info) { - GWS_DCHECK([NSThread isMainThread]); - @autoreleasepool { - if (error->error) { - if ((error->domain != kCFStreamErrorDomainNetServices) && (error->error != kCFNetServicesErrorTimeout)) { - GWS_LOG_ERROR(@"Bonjour resolution error %i (domain %i)", (int)error->error, (int)error->domain); - } - } else { - GCDWebServer* server = (__bridge GCDWebServer*)info; - GWS_LOG_INFO(@"%@ now locally reachable at %@", [server class], server.bonjourServerURL); - if ([server.delegate respondsToSelector:@selector(webServerDidCompleteBonjourRegistration:)]) { - [server.delegate webServerDidCompleteBonjourRegistration:server]; - } - } - } -} - -static void _DNSServiceCallBack(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, uint32_t externalAddress, DNSServiceProtocol protocol, uint16_t internalPort, uint16_t externalPort, uint32_t ttl, void* context) { - GWS_DCHECK([NSThread isMainThread]); - @autoreleasepool { - GCDWebServer* server = (__bridge GCDWebServer*)context; - if ((errorCode == kDNSServiceErr_NoError) || (errorCode == kDNSServiceErr_DoubleNAT)) { - struct sockaddr_in addr4; - bzero(&addr4, sizeof(addr4)); - addr4.sin_len = sizeof(addr4); - addr4.sin_family = AF_INET; - addr4.sin_addr.s_addr = externalAddress; // Already in network byte order - server->_dnsAddress = GCDWebServerStringFromSockAddr((const struct sockaddr*)&addr4, NO); - server->_dnsPort = ntohs(externalPort); - GWS_LOG_INFO(@"%@ now publicly reachable at %@", [server class], server.publicServerURL); - } else { - GWS_LOG_ERROR(@"DNS service error %i", errorCode); - server->_dnsAddress = nil; - server->_dnsPort = 0; - } - if ([server.delegate respondsToSelector:@selector(webServerDidUpdateNATPortMapping:)]) { - [server.delegate webServerDidUpdateNATPortMapping:server]; - } - } -} - -static void _SocketCallBack(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void* data, void* info) { - GWS_DCHECK([NSThread isMainThread]); - @autoreleasepool { - GCDWebServer* server = (__bridge GCDWebServer*)info; - DNSServiceErrorType status = DNSServiceProcessResult(server->_dnsService); - if (status != kDNSServiceErr_NoError) { - GWS_LOG_ERROR(@"DNS service error %i", status); - } - } -} - -static inline id _GetOption(NSDictionary* options, NSString* key, id defaultValue) { - id value = [options objectForKey:key]; - return value ? value : defaultValue; -} - -static inline NSString* _EncodeBase64(NSString* string) { - NSData* data = [string dataUsingEncoding:NSUTF8StringEncoding]; -#if (TARGET_OS_IPHONE && !(__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0)) || (!TARGET_OS_IPHONE && !(__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_9)) - if (![data respondsToSelector:@selector(base64EncodedDataWithOptions:)]) { - return [data base64Encoding]; - } -#endif - return [[NSString alloc] initWithData:[data base64EncodedDataWithOptions:0] encoding:NSASCIIStringEncoding]; -} - -- (int)_createListeningSocket:(BOOL)useIPv6 - localAddress:(const void*)address - length:(socklen_t)length - maxPendingConnections:(NSUInteger)maxPendingConnections - error:(NSError**)error { - int listeningSocket = socket(useIPv6 ? PF_INET6 : PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (listeningSocket > 0) { - int yes = 1; - setsockopt(listeningSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - - if (bind(listeningSocket, address, length) == 0) { - if (listen(listeningSocket, (int)maxPendingConnections) == 0) { - GWS_LOG_DEBUG(@"Did open %s listening socket %i", useIPv6 ? "IPv6" : "IPv4", listeningSocket); - return listeningSocket; - } else { - if (error) { - *error = GCDWebServerMakePosixError(errno); - } - GWS_LOG_ERROR(@"Failed starting %s listening socket: %s (%i)", useIPv6 ? "IPv6" : "IPv4", strerror(errno), errno); - close(listeningSocket); - } - } else { - if (error) { - *error = GCDWebServerMakePosixError(errno); - } - GWS_LOG_ERROR(@"Failed binding %s listening socket: %s (%i)", useIPv6 ? "IPv6" : "IPv4", strerror(errno), errno); - close(listeningSocket); - } - - } else { - if (error) { - *error = GCDWebServerMakePosixError(errno); - } - GWS_LOG_ERROR(@"Failed creating %s listening socket: %s (%i)", useIPv6 ? "IPv6" : "IPv4", strerror(errno), errno); - } - return -1; -} - -- (dispatch_source_t)_createDispatchSourceWithListeningSocket:(int)listeningSocket isIPv6:(BOOL)isIPv6 { - dispatch_group_enter(_sourceGroup); - dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, listeningSocket, 0, dispatch_get_global_queue(_dispatchQueuePriority, 0)); - dispatch_source_set_cancel_handler(source, ^{ - - @autoreleasepool { - int result = close(listeningSocket); - if (result != 0) { - GWS_LOG_ERROR(@"Failed closing %s listening socket: %s (%i)", isIPv6 ? "IPv6" : "IPv4", strerror(errno), errno); - } else { - GWS_LOG_DEBUG(@"Did close %s listening socket %i", isIPv6 ? "IPv6" : "IPv4", listeningSocket); - } - } - dispatch_group_leave(_sourceGroup); - - }); - dispatch_source_set_event_handler(source, ^{ - - @autoreleasepool { - struct sockaddr_storage remoteSockAddr; - socklen_t remoteAddrLen = sizeof(remoteSockAddr); - int socket = accept(listeningSocket, (struct sockaddr*)&remoteSockAddr, &remoteAddrLen); - if (socket > 0) { - NSData* remoteAddress = [NSData dataWithBytes:&remoteSockAddr length:remoteAddrLen]; - - struct sockaddr_storage localSockAddr; - socklen_t localAddrLen = sizeof(localSockAddr); - NSData* localAddress = nil; - if (getsockname(socket, (struct sockaddr*)&localSockAddr, &localAddrLen) == 0) { - localAddress = [NSData dataWithBytes:&localSockAddr length:localAddrLen]; - GWS_DCHECK((!isIPv6 && localSockAddr.ss_family == AF_INET) || (isIPv6 && localSockAddr.ss_family == AF_INET6)); - } else { - GWS_DNOT_REACHED(); - } - - int noSigPipe = 1; - setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &noSigPipe, sizeof(noSigPipe)); // Make sure this socket cannot generate SIG_PIPE - - GCDWebServerConnection* connection = [[_connectionClass alloc] initWithServer:self localAddress:localAddress remoteAddress:remoteAddress socket:socket]; // Connection will automatically retain itself while opened - [connection self]; // Prevent compiler from complaining about unused variable / useless statement - } else { - GWS_LOG_ERROR(@"Failed accepting %s socket: %s (%i)", isIPv6 ? "IPv6" : "IPv4", strerror(errno), errno); - } - } - - }); - return source; -} - -- (BOOL)_start:(NSError**)error { - GWS_DCHECK(_source4 == NULL); - - NSUInteger port = [_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue]; - BOOL bindToLocalhost = [_GetOption(_options, GCDWebServerOption_BindToLocalhost, @NO) boolValue]; - NSUInteger maxPendingConnections = [_GetOption(_options, GCDWebServerOption_MaxPendingConnections, @16) unsignedIntegerValue]; - - struct sockaddr_in addr4; - bzero(&addr4, sizeof(addr4)); - addr4.sin_len = sizeof(addr4); - addr4.sin_family = AF_INET; - addr4.sin_port = htons(port); - addr4.sin_addr.s_addr = bindToLocalhost ? htonl(INADDR_LOOPBACK) : htonl(INADDR_ANY); - int listeningSocket4 = [self _createListeningSocket:NO localAddress:&addr4 length:sizeof(addr4) maxPendingConnections:maxPendingConnections error:error]; - if (listeningSocket4 <= 0) { - return NO; - } - if (port == 0) { - struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); - if (getsockname(listeningSocket4, (struct sockaddr*)&addr, &addrlen) == 0) { - port = ntohs(addr.sin_port); - } else { - GWS_LOG_ERROR(@"Failed retrieving socket address: %s (%i)", strerror(errno), errno); - } - } - - struct sockaddr_in6 addr6; - bzero(&addr6, sizeof(addr6)); - addr6.sin6_len = sizeof(addr6); - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(port); - addr6.sin6_addr = bindToLocalhost ? in6addr_loopback : in6addr_any; - int listeningSocket6 = [self _createListeningSocket:YES localAddress:&addr6 length:sizeof(addr6) maxPendingConnections:maxPendingConnections error:error]; - if (listeningSocket6 <= 0) { - close(listeningSocket4); - return NO; - } - - _serverName = [_GetOption(_options, GCDWebServerOption_ServerName, NSStringFromClass([self class])) copy]; - NSString* authenticationMethod = _GetOption(_options, GCDWebServerOption_AuthenticationMethod, nil); - if ([authenticationMethod isEqualToString:GCDWebServerAuthenticationMethod_Basic]) { - _authenticationRealm = [_GetOption(_options, GCDWebServerOption_AuthenticationRealm, _serverName) copy]; - _authenticationBasicAccounts = [[NSMutableDictionary alloc] init]; - NSDictionary* accounts = _GetOption(_options, GCDWebServerOption_AuthenticationAccounts, @{}); - [accounts enumerateKeysAndObjectsUsingBlock:^(NSString* username, NSString* password, BOOL* stop) { - [_authenticationBasicAccounts setObject:_EncodeBase64([NSString stringWithFormat:@"%@:%@", username, password]) forKey:username]; - }]; - } else if ([authenticationMethod isEqualToString:GCDWebServerAuthenticationMethod_DigestAccess]) { - _authenticationRealm = [_GetOption(_options, GCDWebServerOption_AuthenticationRealm, _serverName) copy]; - _authenticationDigestAccounts = [[NSMutableDictionary alloc] init]; - NSDictionary* accounts = _GetOption(_options, GCDWebServerOption_AuthenticationAccounts, @{}); - [accounts enumerateKeysAndObjectsUsingBlock:^(NSString* username, NSString* password, BOOL* stop) { - [_authenticationDigestAccounts setObject:GCDWebServerComputeMD5Digest(@"%@:%@:%@", username, _authenticationRealm, password) forKey:username]; - }]; - } - _connectionClass = _GetOption(_options, GCDWebServerOption_ConnectionClass, [GCDWebServerConnection class]); - _shouldAutomaticallyMapHEADToGET = [_GetOption(_options, GCDWebServerOption_AutomaticallyMapHEADToGET, @YES) boolValue]; - _disconnectDelay = [_GetOption(_options, GCDWebServerOption_ConnectedStateCoalescingInterval, @1.0) doubleValue]; - _dispatchQueuePriority = [_GetOption(_options, GCDWebServerOption_DispatchQueuePriority, @(DISPATCH_QUEUE_PRIORITY_DEFAULT)) longValue]; - - _source4 = [self _createDispatchSourceWithListeningSocket:listeningSocket4 isIPv6:NO]; - _source6 = [self _createDispatchSourceWithListeningSocket:listeningSocket6 isIPv6:YES]; - _port = port; - _bindToLocalhost = bindToLocalhost; - - NSString* bonjourName = _GetOption(_options, GCDWebServerOption_BonjourName, nil); - NSString* bonjourType = _GetOption(_options, GCDWebServerOption_BonjourType, @"_http._tcp"); - if (bonjourName) { - _registrationService = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), (__bridge CFStringRef)bonjourType, (__bridge CFStringRef)(bonjourName.length ? bonjourName : _serverName), (SInt32)_port); - if (_registrationService) { - CFNetServiceClientContext context = {0, (__bridge void*)self, NULL, NULL, NULL}; - - CFNetServiceSetClient(_registrationService, _NetServiceRegisterCallBack, &context); - CFNetServiceScheduleWithRunLoop(_registrationService, CFRunLoopGetMain(), kCFRunLoopCommonModes); - CFStreamError streamError = {0}; - CFNetServiceRegisterWithOptions(_registrationService, 0, &streamError); - - _resolutionService = CFNetServiceCreateCopy(kCFAllocatorDefault, _registrationService); - if (_resolutionService) { - CFNetServiceSetClient(_resolutionService, _NetServiceResolveCallBack, &context); - CFNetServiceScheduleWithRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes); - } else { - GWS_LOG_ERROR(@"Failed creating CFNetService for resolution"); - } - } else { - GWS_LOG_ERROR(@"Failed creating CFNetService for registration"); - } - } - - if ([_GetOption(_options, GCDWebServerOption_RequestNATPortMapping, @NO) boolValue]) { - DNSServiceErrorType status = DNSServiceNATPortMappingCreate(&_dnsService, 0, 0, kDNSServiceProtocol_TCP, htons(port), htons(port), 0, _DNSServiceCallBack, (__bridge void*)self); - if (status == kDNSServiceErr_NoError) { - CFSocketContext context = {0, (__bridge void*)self, NULL, NULL, NULL}; - _dnsSocket = CFSocketCreateWithNative(kCFAllocatorDefault, DNSServiceRefSockFD(_dnsService), kCFSocketReadCallBack, _SocketCallBack, &context); - if (_dnsSocket) { - CFSocketSetSocketFlags(_dnsSocket, CFSocketGetSocketFlags(_dnsSocket) & ~kCFSocketCloseOnInvalidate); - _dnsSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _dnsSocket, 0); - if (_dnsSource) { - CFRunLoopAddSource(CFRunLoopGetMain(), _dnsSource, kCFRunLoopCommonModes); - } else { - GWS_LOG_ERROR(@"Failed creating CFRunLoopSource"); - GWS_DNOT_REACHED(); - } - } else { - GWS_LOG_ERROR(@"Failed creating CFSocket"); - GWS_DNOT_REACHED(); - } - } else { - GWS_LOG_ERROR(@"Failed creating NAT port mapping (%i)", status); - } - } - - dispatch_resume(_source4); - dispatch_resume(_source6); - GWS_LOG_INFO(@"%@ started on port %i and reachable at %@", [self class], (int)_port, self.serverURL); - if ([_delegate respondsToSelector:@selector(webServerDidStart:)]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [_delegate webServerDidStart:self]; - }); - } - - return YES; -} - -- (void)_stop { - GWS_DCHECK(_source4 != NULL); - - if (_dnsService) { - _dnsAddress = nil; - _dnsPort = 0; - if (_dnsSource) { - CFRunLoopSourceInvalidate(_dnsSource); - CFRelease(_dnsSource); - _dnsSource = NULL; - } - if (_dnsSocket) { - CFRelease(_dnsSocket); - _dnsSocket = NULL; - } - DNSServiceRefDeallocate(_dnsService); - _dnsService = NULL; - } - - if (_registrationService) { - if (_resolutionService) { - CFNetServiceUnscheduleFromRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes); - CFNetServiceSetClient(_resolutionService, NULL, NULL); - CFNetServiceCancel(_resolutionService); - CFRelease(_resolutionService); - _resolutionService = NULL; - } - CFNetServiceUnscheduleFromRunLoop(_registrationService, CFRunLoopGetMain(), kCFRunLoopCommonModes); - CFNetServiceSetClient(_registrationService, NULL, NULL); - CFNetServiceCancel(_registrationService); - CFRelease(_registrationService); - _registrationService = NULL; - } - - dispatch_source_cancel(_source6); - dispatch_source_cancel(_source4); - dispatch_group_wait(_sourceGroup, DISPATCH_TIME_FOREVER); // Wait until the cancellation handlers have been called which guarantees the listening sockets are closed -#if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE - dispatch_release(_source6); -#endif - _source6 = NULL; -#if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE - dispatch_release(_source4); -#endif - _source4 = NULL; - _port = 0; - _bindToLocalhost = NO; - - _serverName = nil; - _authenticationRealm = nil; - _authenticationBasicAccounts = nil; - _authenticationDigestAccounts = nil; - - dispatch_async(dispatch_get_main_queue(), ^{ - if (_disconnectTimer) { - CFRunLoopTimerInvalidate(_disconnectTimer); - CFRelease(_disconnectTimer); - _disconnectTimer = NULL; - [self _didDisconnect]; - } - }); - - GWS_LOG_INFO(@"%@ stopped", [self class]); - if ([_delegate respondsToSelector:@selector(webServerDidStop:)]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [_delegate webServerDidStop:self]; - }); - } -} - -#if TARGET_OS_IPHONE - -- (void)_didEnterBackground:(NSNotification*)notification { - GWS_DCHECK([NSThread isMainThread]); - GWS_LOG_DEBUG(@"Did enter background"); - if ((_backgroundTask == UIBackgroundTaskInvalid) && _source4) { - [self _stop]; - } -} - -- (void)_willEnterForeground:(NSNotification*)notification { - GWS_DCHECK([NSThread isMainThread]); - GWS_LOG_DEBUG(@"Will enter foreground"); - if (!_source4) { - [self _start:NULL]; // TODO: There's probably nothing we can do on failure - } -} - -#endif - -- (BOOL)startWithOptions:(NSDictionary*)options error:(NSError**)error { - if (_options == nil) { - _options = options ? [options copy] : @{}; -#if TARGET_OS_IPHONE - _suspendInBackground = [_GetOption(_options, GCDWebServerOption_AutomaticallySuspendInBackground, @YES) boolValue]; - if (((_suspendInBackground == NO) || ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground)) && ![self _start:error]) -#else - if (![self _start:error]) -#endif - { - _options = nil; - return NO; - } -#if TARGET_OS_IPHONE - if (_suspendInBackground) { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_willEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; - } -#endif - return YES; - } else { - GWS_DNOT_REACHED(); - } - return NO; -} - -- (BOOL)isRunning { - return (_options ? YES : NO); -} - -- (void)stop { - if (_options) { -#if TARGET_OS_IPHONE - if (_suspendInBackground) { - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; - } -#endif - if (_source4) { - [self _stop]; - } - _options = nil; - } else { - GWS_DNOT_REACHED(); - } -} - -@end - -@implementation GCDWebServer (Extensions) - -- (NSURL*)serverURL { - if (_source4) { - NSString* ipAddress = _bindToLocalhost ? @"localhost" : GCDWebServerGetPrimaryIPAddress(NO); // We can't really use IPv6 anyway as it doesn't work great with HTTP URLs in practice - if (ipAddress) { - if (_port != 80) { - return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@:%i/", ipAddress, (int)_port]]; - } else { - return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/", ipAddress]]; - } - } - } - return nil; -} - -- (NSURL*)bonjourServerURL { - if (_source4 && _resolutionService) { - NSString* name = (__bridge NSString*)CFNetServiceGetTargetHost(_resolutionService); - if (name.length) { - name = [name substringToIndex:(name.length - 1)]; // Strip trailing period at end of domain - if (_port != 80) { - return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@:%i/", name, (int)_port]]; - } else { - return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/", name]]; - } - } - } - return nil; -} - -- (NSURL*)publicServerURL { - if (_source4 && _dnsService && _dnsAddress && _dnsPort) { - if (_dnsPort != 80) { - return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@:%i/", _dnsAddress, (int)_dnsPort]]; - } else { - return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/", _dnsAddress]]; - } - } - return nil; -} - -- (BOOL)start { - return [self startWithPort:kDefaultPort bonjourName:@""]; -} - -- (BOOL)startWithPort:(NSUInteger)port bonjourName:(NSString*)name { - NSMutableDictionary* options = [NSMutableDictionary dictionary]; - [options setObject:[NSNumber numberWithInteger:port] forKey:GCDWebServerOption_Port]; - [options setValue:name forKey:GCDWebServerOption_BonjourName]; - return [self startWithOptions:options error:NULL]; -} - -#if !TARGET_OS_IPHONE - -- (BOOL)runWithPort:(NSUInteger)port bonjourName:(NSString*)name { - NSMutableDictionary* options = [NSMutableDictionary dictionary]; - [options setObject:[NSNumber numberWithInteger:port] forKey:GCDWebServerOption_Port]; - [options setValue:name forKey:GCDWebServerOption_BonjourName]; - return [self runWithOptions:options error:NULL]; -} - -- (BOOL)runWithOptions:(NSDictionary*)options error:(NSError**)error { - GWS_DCHECK([NSThread isMainThread]); - BOOL success = NO; - _run = YES; - void (*termHandler)(int) = signal(SIGTERM, _SignalHandler); - void (*intHandler)(int) = signal(SIGINT, _SignalHandler); - if ((termHandler != SIG_ERR) && (intHandler != SIG_ERR)) { - if ([self startWithOptions:options error:error]) { - while (_run) { - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, true); - } - [self stop]; - success = YES; - } - _ExecuteMainThreadRunLoopSources(); - signal(SIGINT, intHandler); - signal(SIGTERM, termHandler); - } - return success; -} - -#endif - -@end - -@implementation GCDWebServer (Handlers) - -- (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block { - [self addDefaultHandlerForMethod:method - requestClass:aClass - asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { - completionBlock(block(request)); - }]; -} - -- (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block { - [self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - - if (![requestMethod isEqualToString:method]) { - return nil; - } - return [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]; - - } - asyncProcessBlock:block]; -} - -- (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block { - [self addHandlerForMethod:method - path:path - requestClass:aClass - asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { - completionBlock(block(request)); - }]; -} - -- (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block { - if ([path hasPrefix:@"/"] && [aClass isSubclassOfClass:[GCDWebServerRequest class]]) { - [self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - - if (![requestMethod isEqualToString:method]) { - return nil; - } - if ([urlPath caseInsensitiveCompare:path] != NSOrderedSame) { - return nil; - } - return [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]; - - } - asyncProcessBlock:block]; - } else { - GWS_DNOT_REACHED(); - } -} - -- (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block { - [self addHandlerForMethod:method - pathRegex:regex - requestClass:aClass - asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { - completionBlock(block(request)); - }]; -} - -- (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block { - NSRegularExpression* expression = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:NULL]; - if (expression && [aClass isSubclassOfClass:[GCDWebServerRequest class]]) { - [self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - - if (![requestMethod isEqualToString:method]) { - return nil; - } - - NSArray* matches = [expression matchesInString:urlPath options:0 range:NSMakeRange(0, urlPath.length)]; - if (matches.count == 0) { - return nil; - } - - NSMutableArray* captures = [NSMutableArray array]; - for (NSTextCheckingResult* result in matches) { - // Start at 1; index 0 is the whole string - for (NSUInteger i = 1; i < result.numberOfRanges; i++) { - NSRange range = [result rangeAtIndex:i]; - // range is {NSNotFound, 0} "if one of the capture groups did not participate in this particular match" - // see discussion in -[NSRegularExpression firstMatchInString:options:range:] - if (range.location != NSNotFound) { - [captures addObject:[urlPath substringWithRange:range]]; - } - } - } - - GCDWebServerRequest* request = [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]; - [request setAttribute:captures forKey:GCDWebServerRequestAttribute_RegexCaptures]; - return request; - - } - asyncProcessBlock:block]; - } else { - GWS_DNOT_REACHED(); - } -} - -@end - -@implementation GCDWebServer (GETHandlers) - -- (void)addGETHandlerForPath:(NSString*)path staticData:(NSData*)staticData contentType:(NSString*)contentType cacheAge:(NSUInteger)cacheAge { - [self addHandlerForMethod:@"GET" - path:path - requestClass:[GCDWebServerRequest class] - processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { - - GCDWebServerResponse* response = [GCDWebServerDataResponse responseWithData:staticData contentType:contentType]; - response.cacheControlMaxAge = cacheAge; - return response; - - }]; -} - -- (void)addGETHandlerForPath:(NSString*)path filePath:(NSString*)filePath isAttachment:(BOOL)isAttachment cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests { - [self addHandlerForMethod:@"GET" - path:path - requestClass:[GCDWebServerRequest class] - processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { - - GCDWebServerResponse* response = nil; - if (allowRangeRequests) { - response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange isAttachment:isAttachment]; - [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"]; - } else { - response = [GCDWebServerFileResponse responseWithFile:filePath isAttachment:isAttachment]; - } - response.cacheControlMaxAge = cacheAge; - return response; - - }]; -} - -- (GCDWebServerResponse*)_responseWithContentsOfDirectory:(NSString*)path { - NSDirectoryEnumerator* enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path]; - if (enumerator == nil) { - return nil; - } - NSMutableString* html = [NSMutableString string]; - [html appendString:@"\n"]; - [html appendString:@"\n"]; - [html appendString:@"
    \n"]; - for (NSString* file in enumerator) { - if (![file hasPrefix:@"."]) { - NSString* type = [[enumerator fileAttributes] objectForKey:NSFileType]; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - NSString* escapedFile = [file stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; -#pragma clang diagnostic pop - GWS_DCHECK(escapedFile); - if ([type isEqualToString:NSFileTypeRegular]) { - [html appendFormat:@"
  • %@
  • \n", escapedFile, file]; - } else if ([type isEqualToString:NSFileTypeDirectory]) { - [html appendFormat:@"
  • %@/
  • \n", escapedFile, file]; - } - } - [enumerator skipDescendents]; - } - [html appendString:@"
\n"]; - [html appendString:@"\n"]; - return [GCDWebServerDataResponse responseWithHTML:html]; -} - -- (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests { - if ([basePath hasPrefix:@"/"] && [basePath hasSuffix:@"/"]) { - GCDWebServer* __unsafe_unretained server = self; - [self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - - if (![requestMethod isEqualToString:@"GET"]) { - return nil; - } - if (![urlPath hasPrefix:basePath]) { - return nil; - } - return [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]; - - } - processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { - - GCDWebServerResponse* response = nil; - NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]]; - NSString* fileType = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL] fileType]; - if (fileType) { - if ([fileType isEqualToString:NSFileTypeDirectory]) { - if (indexFilename) { - NSString* indexPath = [filePath stringByAppendingPathComponent:indexFilename]; - NSString* indexType = [[[NSFileManager defaultManager] attributesOfItemAtPath:indexPath error:NULL] fileType]; - if ([indexType isEqualToString:NSFileTypeRegular]) { - return [GCDWebServerFileResponse responseWithFile:indexPath]; - } - } - response = [server _responseWithContentsOfDirectory:filePath]; - } else if ([fileType isEqualToString:NSFileTypeRegular]) { - if (allowRangeRequests) { - response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange]; - [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"]; - } else { - response = [GCDWebServerFileResponse responseWithFile:filePath]; - } - } - } - if (response) { - response.cacheControlMaxAge = cacheAge; - } else { - response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NotFound]; - } - return response; - - }]; - } else { - GWS_DNOT_REACHED(); - } -} - -@end - -@implementation GCDWebServer (Logging) - -+ (void)setLogLevel:(int)level { -#if defined(__GCDWEBSERVER_LOGGING_FACILITY_XLFACILITY__) - [XLSharedFacility setMinLogLevel:level]; -#elif defined(__GCDWEBSERVER_LOGGING_FACILITY_COCOALUMBERJACK__) - GCDWebServerLogLevel = level; -#elif defined(__GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__) - GCDWebServerLogLevel = level; -#endif -} - -- (void)logVerbose:(NSString*)format, ... { - va_list arguments; - va_start(arguments, format); - GWS_LOG_VERBOSE(@"%@", [[NSString alloc] initWithFormat:format arguments:arguments]); - va_end(arguments); -} - -- (void)logInfo:(NSString*)format, ... { - va_list arguments; - va_start(arguments, format); - GWS_LOG_INFO(@"%@", [[NSString alloc] initWithFormat:format arguments:arguments]); - va_end(arguments); -} - -- (void)logWarning:(NSString*)format, ... { - va_list arguments; - va_start(arguments, format); - GWS_LOG_WARNING(@"%@", [[NSString alloc] initWithFormat:format arguments:arguments]); - va_end(arguments); -} - -- (void)logError:(NSString*)format, ... { - va_list arguments; - va_start(arguments, format); - GWS_LOG_ERROR(@"%@", [[NSString alloc] initWithFormat:format arguments:arguments]); - va_end(arguments); -} - -@end - -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ - -@implementation GCDWebServer (Testing) - -- (void)setRecordingEnabled:(BOOL)flag { - _recording = flag; -} - -- (BOOL)isRecordingEnabled { - return _recording; -} - -static CFHTTPMessageRef _CreateHTTPMessageFromData(NSData* data, BOOL isRequest) { - CFHTTPMessageRef message = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, isRequest); - if (CFHTTPMessageAppendBytes(message, data.bytes, data.length)) { - return message; - } - CFRelease(message); - return NULL; -} - -static CFHTTPMessageRef _CreateHTTPMessageFromPerformingRequest(NSData* inData, NSUInteger port) { - CFHTTPMessageRef response = NULL; - int httpSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (httpSocket > 0) { - struct sockaddr_in addr4; - bzero(&addr4, sizeof(addr4)); - addr4.sin_len = sizeof(port); - addr4.sin_family = AF_INET; - addr4.sin_port = htons(8080); - addr4.sin_addr.s_addr = htonl(INADDR_ANY); - if (connect(httpSocket, (void*)&addr4, sizeof(addr4)) == 0) { - if (write(httpSocket, inData.bytes, inData.length) == (ssize_t)inData.length) { - NSMutableData* outData = [[NSMutableData alloc] initWithLength:(256 * 1024)]; - NSUInteger length = 0; - while (1) { - ssize_t result = read(httpSocket, (char*)outData.mutableBytes + length, outData.length - length); - if (result < 0) { - length = NSUIntegerMax; - break; - } else if (result == 0) { - break; - } - length += result; - if (length >= outData.length) { - outData.length = 2 * outData.length; - } - } - if (length != NSUIntegerMax) { - outData.length = length; - response = _CreateHTTPMessageFromData(outData, NO); - } else { - GWS_DNOT_REACHED(); - } - } - } - close(httpSocket); - } - return response; -} - -static void _LogResult(NSString* format, ...) { - va_list arguments; - va_start(arguments, format); - NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments]; - va_end(arguments); - fprintf(stdout, "%s\n", [message UTF8String]); -} - -- (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)path { - GWS_DCHECK([NSThread isMainThread]); - NSArray* ignoredHeaders = @[ @"Date", @"Etag" ]; // Dates are always different by definition and ETags depend on file system node IDs - NSInteger result = -1; - if ([self startWithOptions:options error:NULL]) { - _ExecuteMainThreadRunLoopSources(); - - result = 0; - NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL]; - for (NSString* requestFile in files) { - if (![requestFile hasSuffix:@".request"]) { - continue; - } - @autoreleasepool { - NSString* index = [[requestFile componentsSeparatedByString:@"-"] firstObject]; - BOOL success = NO; - NSData* requestData = [NSData dataWithContentsOfFile:[path stringByAppendingPathComponent:requestFile]]; - if (requestData) { - CFHTTPMessageRef request = _CreateHTTPMessageFromData(requestData, YES); - if (request) { - NSString* requestMethod = CFBridgingRelease(CFHTTPMessageCopyRequestMethod(request)); - NSURL* requestURL = CFBridgingRelease(CFHTTPMessageCopyRequestURL(request)); - _LogResult(@"[%i] %@ %@", (int)[index integerValue], requestMethod, requestURL.path); - NSString* prefix = [index stringByAppendingString:@"-"]; - for (NSString* responseFile in files) { - if ([responseFile hasPrefix:prefix] && [responseFile hasSuffix:@".response"]) { - NSData* responseData = [NSData dataWithContentsOfFile:[path stringByAppendingPathComponent:responseFile]]; - if (responseData) { - CFHTTPMessageRef expectedResponse = _CreateHTTPMessageFromData(responseData, NO); - if (expectedResponse) { - CFHTTPMessageRef actualResponse = _CreateHTTPMessageFromPerformingRequest(requestData, self.port); - if (actualResponse) { - success = YES; - - CFIndex expectedStatusCode = CFHTTPMessageGetResponseStatusCode(expectedResponse); - CFIndex actualStatusCode = CFHTTPMessageGetResponseStatusCode(actualResponse); - if (actualStatusCode != expectedStatusCode) { - _LogResult(@" Status code not matching:\n Expected: %i\n Actual: %i", (int)expectedStatusCode, (int)actualStatusCode); - success = NO; - } - - NSDictionary* expectedHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(expectedResponse)); - NSDictionary* actualHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(actualResponse)); - for (NSString* expectedHeader in expectedHeaders) { - if ([ignoredHeaders containsObject:expectedHeader]) { - continue; - } - NSString* expectedValue = [expectedHeaders objectForKey:expectedHeader]; - NSString* actualValue = [actualHeaders objectForKey:expectedHeader]; - if (![actualValue isEqualToString:expectedValue]) { - _LogResult(@" Header '%@' not matching:\n Expected: \"%@\"\n Actual: \"%@\"", expectedHeader, expectedValue, actualValue); - success = NO; - } - } - for (NSString* actualHeader in actualHeaders) { - if (![expectedHeaders objectForKey:actualHeader]) { - _LogResult(@" Header '%@' not matching:\n Expected: \"%@\"\n Actual: \"%@\"", actualHeader, nil, [actualHeaders objectForKey:actualHeader]); - success = NO; - } - } - - NSString* expectedContentLength = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(expectedResponse, CFSTR("Content-Length"))); - NSData* expectedBody = CFBridgingRelease(CFHTTPMessageCopyBody(expectedResponse)); - NSString* actualContentLength = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(actualResponse, CFSTR("Content-Length"))); - NSData* actualBody = CFBridgingRelease(CFHTTPMessageCopyBody(actualResponse)); - if ([actualContentLength isEqualToString:expectedContentLength] && (actualBody.length > expectedBody.length)) { // Handle web browser closing connection before retrieving entire body (e.g. when playing a video file) - actualBody = [actualBody subdataWithRange:NSMakeRange(0, expectedBody.length)]; - } - if (![actualBody isEqualToData:expectedBody]) { - _LogResult(@" Bodies not matching:\n Expected: %lu bytes\n Actual: %lu bytes", (unsigned long)expectedBody.length, (unsigned long)actualBody.length); - success = NO; -#if !TARGET_OS_IPHONE -#if DEBUG - if (GCDWebServerIsTextContentType((NSString*)[expectedHeaders objectForKey:@"Content-Type"])) { - NSString* expectedPath = [NSTemporaryDirectory() stringByAppendingPathComponent:(NSString*)[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]]; - NSString* actualPath = [NSTemporaryDirectory() stringByAppendingPathComponent:(NSString*)[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]]; - if ([expectedBody writeToFile:expectedPath atomically:YES] && [actualBody writeToFile:actualPath atomically:YES]) { - NSTask* task = [[NSTask alloc] init]; - [task setLaunchPath:@"/usr/bin/opendiff"]; - [task setArguments:@[ expectedPath, actualPath ]]; - [task launch]; - } - } -#endif -#endif - } - - CFRelease(actualResponse); - } - CFRelease(expectedResponse); - } - } else { - GWS_DNOT_REACHED(); - } - break; - } - } - CFRelease(request); - } - } else { - GWS_DNOT_REACHED(); - } - _LogResult(@""); - if (!success) { - ++result; - } - } - _ExecuteMainThreadRunLoopSources(); - } - - [self stop]; - - _ExecuteMainThreadRunLoopSources(); - } - return result; -} - -@end - -#endif diff --git a/src/ios/GCDWebServer/Core/GCDWebServerConnection.h b/src/ios/GCDWebServer/Core/GCDWebServerConnection.h deleted file mode 100755 index 420d12a..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerConnection.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GCDWebServer.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GCDWebServerHandler; - -/** - * The GCDWebServerConnection class is instantiated by GCDWebServer to handle - * each new HTTP connection. Each instance stays alive until the connection is - * closed. - * - * You cannot use this class directly, but it is made public so you can - * subclass it to override some hooks. Use the GCDWebServerOption_ConnectionClass - * option for GCDWebServer to install your custom subclass. - * - * @warning The GCDWebServerConnection retains the GCDWebServer until the - * connection is closed. - */ -@interface GCDWebServerConnection : NSObject - -/** - * Returns the GCDWebServer that owns the connection. - */ -@property(nonatomic, readonly) GCDWebServer* server; - -/** - * Returns YES if the connection is using IPv6. - */ -@property(nonatomic, readonly, getter=isUsingIPv6) BOOL usingIPv6; - -/** - * Returns the address of the local peer (i.e. server) of the connection - * as a raw "struct sockaddr". - */ -@property(nonatomic, readonly) NSData* localAddressData; - -/** - * Returns the address of the local peer (i.e. server) of the connection - * as a string. - */ -@property(nonatomic, readonly) NSString* localAddressString; - -/** - * Returns the address of the remote peer (i.e. client) of the connection - * as a raw "struct sockaddr". - */ -@property(nonatomic, readonly) NSData* remoteAddressData; - -/** - * Returns the address of the remote peer (i.e. client) of the connection - * as a string. - */ -@property(nonatomic, readonly) NSString* remoteAddressString; - -/** - * Returns the total number of bytes received from the remote peer (i.e. client) - * so far. - */ -@property(nonatomic, readonly) NSUInteger totalBytesRead; - -/** - * Returns the total number of bytes sent to the remote peer (i.e. client) so far. - */ -@property(nonatomic, readonly) NSUInteger totalBytesWritten; - -@end - -/** - * Hooks to customize the behavior of GCDWebServer HTTP connections. - * - * @warning These methods can be called on any GCD thread. - * Be sure to also call "super" when overriding them. - */ -@interface GCDWebServerConnection (Subclassing) - -/** - * This method is called when the connection is opened. - * - * Return NO to reject the connection e.g. after validating the local - * or remote address. - */ -- (BOOL)open; - -/** - * This method is called whenever data has been received - * from the remote peer (i.e. client). - * - * @warning Do not attempt to modify this data. - */ -- (void)didReadBytes:(const void*)bytes length:(NSUInteger)length; - -/** - * This method is called whenever data has been sent - * to the remote peer (i.e. client). - * - * @warning Do not attempt to modify this data. - */ -- (void)didWriteBytes:(const void*)bytes length:(NSUInteger)length; - -/** - * This method is called after the HTTP headers have been received to - * allow replacing the request URL by another one. - * - * The default implementation returns the original URL. - */ -- (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary*)headers; - -/** - * Assuming a valid HTTP request was received, this method is called before - * the request is processed. - * - * Return a non-nil GCDWebServerResponse to bypass the request processing entirely. - * - * The default implementation checks for HTTP authentication if applicable - * and returns a barebone 401 status code response if authentication failed. - */ -- (nullable GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request; - -/** - * Assuming a valid HTTP request was received and -preflightRequest: returned nil, - * this method is called to process the request by executing the handler's - * process block. - */ -- (void)processRequest:(GCDWebServerRequest*)request completion:(GCDWebServerCompletionBlock)completion; - -/** - * Assuming a valid HTTP request was received and either -preflightRequest: - * or -processRequest:completion: returned a non-nil GCDWebServerResponse, - * this method is called to override the response. - * - * You can either modify the current response and return it, or return a - * completely new one. - * - * The default implementation replaces any response matching the "ETag" or - * "Last-Modified-Date" header of the request by a barebone "Not-Modified" (304) - * one. - */ -- (GCDWebServerResponse*)overrideResponse:(GCDWebServerResponse*)response forRequest:(GCDWebServerRequest*)request; - -/** - * This method is called if any error happens while validing or processing - * the request or if no GCDWebServerResponse was generated during processing. - * - * @warning If the request was invalid (e.g. the HTTP headers were malformed), - * the "request" argument will be nil. - */ -- (void)abortRequest:(nullable GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode; - -/** - * Called when the connection is closed. - */ -- (void)close; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Core/GCDWebServerConnection.m b/src/ios/GCDWebServer/Core/GCDWebServerConnection.m deleted file mode 100755 index b59f3f4..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerConnection.m +++ /dev/null @@ -1,868 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import -#import -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ -#import -#endif - -#import "GCDWebServerPrivate.h" - -#define kHeadersReadCapacity (1 * 1024) -#define kBodyReadCapacity (256 * 1024) - -typedef void (^ReadDataCompletionBlock)(BOOL success); -typedef void (^ReadHeadersCompletionBlock)(NSData* extraData); -typedef void (^ReadBodyCompletionBlock)(BOOL success); - -typedef void (^WriteDataCompletionBlock)(BOOL success); -typedef void (^WriteHeadersCompletionBlock)(BOOL success); -typedef void (^WriteBodyCompletionBlock)(BOOL success); - -static NSData* _CRLFData = nil; -static NSData* _CRLFCRLFData = nil; -static NSData* _continueData = nil; -static NSData* _lastChunkData = nil; -static NSString* _digestAuthenticationNonce = nil; -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ -static int32_t _connectionCounter = 0; -#endif - -NS_ASSUME_NONNULL_BEGIN - -@interface GCDWebServerConnection (Read) -- (void)readData:(NSMutableData*)data withLength:(NSUInteger)length completionBlock:(ReadDataCompletionBlock)block; -- (void)readHeaders:(NSMutableData*)headersData withCompletionBlock:(ReadHeadersCompletionBlock)block; -- (void)readBodyWithRemainingLength:(NSUInteger)length completionBlock:(ReadBodyCompletionBlock)block; -- (void)readNextBodyChunk:(NSMutableData*)chunkData completionBlock:(ReadBodyCompletionBlock)block; -@end - -@interface GCDWebServerConnection (Write) -- (void)writeData:(NSData*)data withCompletionBlock:(WriteDataCompletionBlock)block; -- (void)writeHeadersWithCompletionBlock:(WriteHeadersCompletionBlock)block; -- (void)writeBodyWithCompletionBlock:(WriteBodyCompletionBlock)block; -@end - -NS_ASSUME_NONNULL_END - -@implementation GCDWebServerConnection { - CFSocketNativeHandle _socket; - BOOL _virtualHEAD; - - CFHTTPMessageRef _requestMessage; - GCDWebServerRequest* _request; - GCDWebServerHandler* _handler; - CFHTTPMessageRef _responseMessage; - GCDWebServerResponse* _response; - NSInteger _statusCode; - - BOOL _opened; -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ - NSUInteger _connectionIndex; - NSString* _requestPath; - int _requestFD; - NSString* _responsePath; - int _responseFD; -#endif -} - -+ (void)initialize { - if (_CRLFData == nil) { - _CRLFData = [[NSData alloc] initWithBytes:"\r\n" length:2]; - GWS_DCHECK(_CRLFData); - } - if (_CRLFCRLFData == nil) { - _CRLFCRLFData = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4]; - GWS_DCHECK(_CRLFCRLFData); - } - if (_continueData == nil) { - CFHTTPMessageRef message = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 100, NULL, kCFHTTPVersion1_1); - _continueData = CFBridgingRelease(CFHTTPMessageCopySerializedMessage(message)); - CFRelease(message); - GWS_DCHECK(_continueData); - } - if (_lastChunkData == nil) { - _lastChunkData = [[NSData alloc] initWithBytes:"0\r\n\r\n" length:5]; - } - if (_digestAuthenticationNonce == nil) { - CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); - _digestAuthenticationNonce = GCDWebServerComputeMD5Digest(@"%@", CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid))); - CFRelease(uuid); - } -} - -- (BOOL)isUsingIPv6 { - const struct sockaddr* localSockAddr = _localAddressData.bytes; - return (localSockAddr->sa_family == AF_INET6); -} - -- (void)_initializeResponseHeadersWithStatusCode:(NSInteger)statusCode { - _statusCode = statusCode; - _responseMessage = CFHTTPMessageCreateResponse(kCFAllocatorDefault, statusCode, NULL, kCFHTTPVersion1_1); - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Connection"), CFSTR("Close")); - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Server"), (__bridge CFStringRef)_server.serverName); - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Date"), (__bridge CFStringRef)GCDWebServerFormatRFC822([NSDate date])); -} - -- (void)_startProcessingRequest { - GWS_DCHECK(_responseMessage == NULL); - - GCDWebServerResponse* preflightResponse = [self preflightRequest:_request]; - if (preflightResponse) { - [self _finishProcessingRequest:preflightResponse]; - } else { - [self processRequest:_request - completion:^(GCDWebServerResponse* processResponse) { - [self _finishProcessingRequest:processResponse]; - }]; - } -} - -// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html -- (void)_finishProcessingRequest:(GCDWebServerResponse*)response { - GWS_DCHECK(_responseMessage == NULL); - BOOL hasBody = NO; - - if (response) { - response = [self overrideResponse:response forRequest:_request]; - } - if (response) { - if ([response hasBody]) { - [response prepareForReading]; - hasBody = !_virtualHEAD; - } - NSError* error = nil; - if (hasBody && ![response performOpen:&error]) { - GWS_LOG_ERROR(@"Failed opening response body for socket %i: %@", _socket, error); - } else { - _response = response; - } - } - - if (_response) { - [self _initializeResponseHeadersWithStatusCode:_response.statusCode]; - if (_response.lastModifiedDate) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Last-Modified"), (__bridge CFStringRef)GCDWebServerFormatRFC822((NSDate*)_response.lastModifiedDate)); - } - if (_response.eTag) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("ETag"), (__bridge CFStringRef)_response.eTag); - } - if ((_response.statusCode >= 200) && (_response.statusCode < 300)) { - if (_response.cacheControlMaxAge > 0) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), (__bridge CFStringRef)[NSString stringWithFormat:@"max-age=%i, public", (int)_response.cacheControlMaxAge]); - } else { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), CFSTR("no-cache")); - } - } - if (_response.contentType != nil) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Type"), (__bridge CFStringRef)GCDWebServerNormalizeHeaderValue(_response.contentType)); - } - if (_response.contentLength != NSUIntegerMax) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Length"), (__bridge CFStringRef)[NSString stringWithFormat:@"%lu", (unsigned long)_response.contentLength]); - } - if (_response.usesChunkedTransferEncoding) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Transfer-Encoding"), CFSTR("chunked")); - } - [_response.additionalHeaders enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL* stop) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, (__bridge CFStringRef)key, (__bridge CFStringRef)obj); - }]; - [self writeHeadersWithCompletionBlock:^(BOOL success) { - - if (success) { - if (hasBody) { - [self writeBodyWithCompletionBlock:^(BOOL successInner) { - - [_response performClose]; // TODO: There's nothing we can do on failure as headers have already been sent - - }]; - } - } else if (hasBody) { - [_response performClose]; - } - - }]; - } else { - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - } -} - -- (void)_readBodyWithLength:(NSUInteger)length initialData:(NSData*)initialData { - NSError* error = nil; - if (![_request performOpen:&error]) { - GWS_LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - return; - } - - if (initialData.length) { - if (![_request performWriteData:initialData error:&error]) { - GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error); - if (![_request performClose:&error]) { - GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); - } - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - return; - } - length -= initialData.length; - } - - if (length) { - [self readBodyWithRemainingLength:length - completionBlock:^(BOOL success) { - - NSError* localError = nil; - if ([_request performClose:&localError]) { - [self _startProcessingRequest]; - } else { - GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - } - - }]; - } else { - if ([_request performClose:&error]) { - [self _startProcessingRequest]; - } else { - GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - } - } -} - -- (void)_readChunkedBodyWithInitialData:(NSData*)initialData { - NSError* error = nil; - if (![_request performOpen:&error]) { - GWS_LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - return; - } - - NSMutableData* chunkData = [[NSMutableData alloc] initWithData:initialData]; - [self readNextBodyChunk:chunkData - completionBlock:^(BOOL success) { - - NSError* localError = nil; - if ([_request performClose:&localError]) { - [self _startProcessingRequest]; - } else { - GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - } - - }]; -} - -- (void)_readRequestHeaders { - _requestMessage = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, true); - NSMutableData* headersData = [[NSMutableData alloc] initWithCapacity:kHeadersReadCapacity]; - [self readHeaders:headersData - withCompletionBlock:^(NSData* extraData) { - - if (extraData) { - NSString* requestMethod = CFBridgingRelease(CFHTTPMessageCopyRequestMethod(_requestMessage)); // Method verbs are case-sensitive and uppercase - if (_server.shouldAutomaticallyMapHEADToGET && [requestMethod isEqualToString:@"HEAD"]) { - requestMethod = @"GET"; - _virtualHEAD = YES; - } - NSDictionary* requestHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_requestMessage)); // Header names are case-insensitive but CFHTTPMessageCopyAllHeaderFields() will standardize the common ones - NSURL* requestURL = CFBridgingRelease(CFHTTPMessageCopyRequestURL(_requestMessage)); - if (requestURL) { - requestURL = [self rewriteRequestURL:requestURL withMethod:requestMethod headers:requestHeaders]; - GWS_DCHECK(requestURL); - } - NSString* urlPath = requestURL ? CFBridgingRelease(CFURLCopyPath((CFURLRef)requestURL)) : nil; // Don't use -[NSURL path] which strips the ending slash - NSString* requestPath = urlPath ? GCDWebServerUnescapeURLString(urlPath) : nil; - NSString* queryString = requestURL ? CFBridgingRelease(CFURLCopyQueryString((CFURLRef)requestURL, NULL)) : nil; // Don't use -[NSURL query] to make sure query is not unescaped; - NSDictionary* requestQuery = queryString ? GCDWebServerParseURLEncodedForm(queryString) : @{}; - if (requestMethod && requestURL && requestHeaders && requestPath && requestQuery) { - for (_handler in _server.handlers) { - _request = _handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery); - if (_request) { - break; - } - } - if (_request) { - _request.localAddressData = self.localAddressData; - _request.remoteAddressData = self.remoteAddressData; - if ([_request hasBody]) { - [_request prepareForWriting]; - if (_request.usesChunkedTransferEncoding || (extraData.length <= _request.contentLength)) { - NSString* expectHeader = [requestHeaders objectForKey:@"Expect"]; - if (expectHeader) { - if ([expectHeader caseInsensitiveCompare:@"100-continue"] == NSOrderedSame) { // TODO: Actually validate request before continuing - [self writeData:_continueData - withCompletionBlock:^(BOOL success) { - - if (success) { - if (_request.usesChunkedTransferEncoding) { - [self _readChunkedBodyWithInitialData:extraData]; - } else { - [self _readBodyWithLength:_request.contentLength initialData:extraData]; - } - } - - }]; - } else { - GWS_LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed]; - } - } else { - if (_request.usesChunkedTransferEncoding) { - [self _readChunkedBodyWithInitialData:extraData]; - } else { - [self _readBodyWithLength:_request.contentLength initialData:extraData]; - } - } - } else { - GWS_LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest]; - } - } else { - [self _startProcessingRequest]; - } - } else { - _request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery]; - GWS_DCHECK(_request); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_MethodNotAllowed]; - } - } else { - [self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - GWS_DNOT_REACHED(); - } - } else { - [self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - } - - }]; -} - -- (instancetype)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket { - if ((self = [super init])) { - _server = server; - _localAddressData = localAddress; - _remoteAddressData = remoteAddress; - _socket = socket; - GWS_LOG_DEBUG(@"Did open connection on socket %i", _socket); - - [_server willStartConnection:self]; - - if (![self open]) { - close(_socket); - return nil; - } - _opened = YES; - - [self _readRequestHeaders]; - } - return self; -} - -- (NSString*)localAddressString { - return GCDWebServerStringFromSockAddr(_localAddressData.bytes, YES); -} - -- (NSString*)remoteAddressString { - return GCDWebServerStringFromSockAddr(_remoteAddressData.bytes, YES); -} - -- (void)dealloc { - int result = close(_socket); - if (result != 0) { - GWS_LOG_ERROR(@"Failed closing socket %i for connection: %s (%i)", _socket, strerror(errno), errno); - } else { - GWS_LOG_DEBUG(@"Did close connection on socket %i", _socket); - } - - if (_opened) { - [self close]; - } - - [_server didEndConnection:self]; - - if (_requestMessage) { - CFRelease(_requestMessage); - } - - if (_responseMessage) { - CFRelease(_responseMessage); - } -} - -@end - -@implementation GCDWebServerConnection (Read) - -- (void)readData:(NSMutableData*)data withLength:(NSUInteger)length completionBlock:(ReadDataCompletionBlock)block { - dispatch_read(_socket, length, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t buffer, int error) { - - @autoreleasepool { - if (error == 0) { - size_t size = dispatch_data_get_size(buffer); - if (size > 0) { - NSUInteger originalLength = data.length; - dispatch_data_apply(buffer, ^bool(dispatch_data_t region, size_t chunkOffset, const void* chunkBytes, size_t chunkSize) { - [data appendBytes:chunkBytes length:chunkSize]; - return true; - }); - [self didReadBytes:((char*)data.bytes + originalLength) length:(data.length - originalLength)]; - block(YES); - } else { - if (_totalBytesRead > 0) { - GWS_LOG_ERROR(@"No more data available on socket %i", _socket); - } else { - GWS_LOG_WARNING(@"No data received from socket %i", _socket); - } - block(NO); - } - } else { - GWS_LOG_ERROR(@"Error while reading from socket %i: %s (%i)", _socket, strerror(error), error); - block(NO); - } - } - - }); -} - -- (void)readHeaders:(NSMutableData*)headersData withCompletionBlock:(ReadHeadersCompletionBlock)block { - GWS_DCHECK(_requestMessage); - [self readData:headersData - withLength:NSUIntegerMax - completionBlock:^(BOOL success) { - - if (success) { - NSRange range = [headersData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(0, headersData.length)]; - if (range.location == NSNotFound) { - [self readHeaders:headersData withCompletionBlock:block]; - } else { - NSUInteger length = range.location + range.length; - if (CFHTTPMessageAppendBytes(_requestMessage, headersData.bytes, length)) { - if (CFHTTPMessageIsHeaderComplete(_requestMessage)) { - block([headersData subdataWithRange:NSMakeRange(length, headersData.length - length)]); - } else { - GWS_LOG_ERROR(@"Failed parsing request headers from socket %i", _socket); - block(nil); - } - } else { - GWS_LOG_ERROR(@"Failed appending request headers data from socket %i", _socket); - block(nil); - } - } - } else { - block(nil); - } - - }]; -} - -- (void)readBodyWithRemainingLength:(NSUInteger)length completionBlock:(ReadBodyCompletionBlock)block { - GWS_DCHECK([_request hasBody] && ![_request usesChunkedTransferEncoding]); - NSMutableData* bodyData = [[NSMutableData alloc] initWithCapacity:kBodyReadCapacity]; - [self readData:bodyData - withLength:length - completionBlock:^(BOOL success) { - - if (success) { - if (bodyData.length <= length) { - NSError* error = nil; - if ([_request performWriteData:bodyData error:&error]) { - NSUInteger remainingLength = length - bodyData.length; - if (remainingLength) { - [self readBodyWithRemainingLength:remainingLength completionBlock:block]; - } else { - block(YES); - } - } else { - GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error); - block(NO); - } - } else { - GWS_LOG_ERROR(@"Unexpected extra content reading request body on socket %i", _socket); - block(NO); - GWS_DNOT_REACHED(); - } - } else { - block(NO); - } - - }]; -} - -static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { - char buffer[size + 1]; - bcopy(bytes, buffer, size); - buffer[size] = 0; - char* end = NULL; - long result = strtol(buffer, &end, 16); - return ((end != NULL) && (*end == 0) && (result >= 0) ? result : NSNotFound); -} - -- (void)readNextBodyChunk:(NSMutableData*)chunkData completionBlock:(ReadBodyCompletionBlock)block { - GWS_DCHECK([_request hasBody] && [_request usesChunkedTransferEncoding]); - - while (1) { - NSRange range = [chunkData rangeOfData:_CRLFData options:0 range:NSMakeRange(0, chunkData.length)]; - if (range.location == NSNotFound) { - break; - } - NSRange extensionRange = [chunkData rangeOfData:[NSData dataWithBytes:";" length:1] options:0 range:NSMakeRange(0, range.location)]; // Ignore chunk extensions - NSUInteger length = _ScanHexNumber((char*)chunkData.bytes, extensionRange.location != NSNotFound ? extensionRange.location : range.location); - if (length != NSNotFound) { - if (length) { - if (chunkData.length < range.location + range.length + length + 2) { - break; - } - const char* ptr = (char*)chunkData.bytes + range.location + range.length + length; - if ((*ptr == '\r') && (*(ptr + 1) == '\n')) { - NSError* error = nil; - if ([_request performWriteData:[chunkData subdataWithRange:NSMakeRange(range.location + range.length, length)] error:&error]) { - [chunkData replaceBytesInRange:NSMakeRange(0, range.location + range.length + length + 2) withBytes:NULL length:0]; - } else { - GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error); - block(NO); - return; - } - } else { - GWS_LOG_ERROR(@"Missing terminating CRLF sequence for chunk reading request body on socket %i", _socket); - block(NO); - return; - } - } else { - NSRange trailerRange = [chunkData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(range.location, chunkData.length - range.location)]; // Ignore trailers - if (trailerRange.location != NSNotFound) { - block(YES); - return; - } - } - } else { - GWS_LOG_ERROR(@"Invalid chunk length reading request body on socket %i", _socket); - block(NO); - return; - } - } - - [self readData:chunkData - withLength:NSUIntegerMax - completionBlock:^(BOOL success) { - - if (success) { - [self readNextBodyChunk:chunkData completionBlock:block]; - } else { - block(NO); - } - - }]; -} - -@end - -@implementation GCDWebServerConnection (Write) - -- (void)writeData:(NSData*)data withCompletionBlock:(WriteDataCompletionBlock)block { - dispatch_data_t buffer = dispatch_data_create(data.bytes, data.length, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^{ - [data self]; // Keeps ARC from releasing data too early - }); - dispatch_write(_socket, buffer, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t remainingData, int error) { - - @autoreleasepool { - if (error == 0) { - GWS_DCHECK(remainingData == NULL); - [self didWriteBytes:data.bytes length:data.length]; - block(YES); - } else { - GWS_LOG_ERROR(@"Error while writing to socket %i: %s (%i)", _socket, strerror(error), error); - block(NO); - } - } - - }); -#if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE - dispatch_release(buffer); -#endif -} - -- (void)writeHeadersWithCompletionBlock:(WriteHeadersCompletionBlock)block { - GWS_DCHECK(_responseMessage); - CFDataRef data = CFHTTPMessageCopySerializedMessage(_responseMessage); - [self writeData:(__bridge NSData*)data withCompletionBlock:block]; - CFRelease(data); -} - -- (void)writeBodyWithCompletionBlock:(WriteBodyCompletionBlock)block { - GWS_DCHECK([_response hasBody]); - [_response performReadDataWithCompletion:^(NSData* data, NSError* error) { - - if (data) { - if (data.length) { - if (_response.usesChunkedTransferEncoding) { - const char* hexString = [[NSString stringWithFormat:@"%lx", (unsigned long)data.length] UTF8String]; - size_t hexLength = strlen(hexString); - NSData* chunk = [NSMutableData dataWithLength:(hexLength + 2 + data.length + 2)]; - if (chunk == nil) { - GWS_LOG_ERROR(@"Failed allocating memory for response body chunk for socket %i: %@", _socket, error); - block(NO); - return; - } - char* ptr = (char*)[(NSMutableData*)chunk mutableBytes]; - bcopy(hexString, ptr, hexLength); - ptr += hexLength; - *ptr++ = '\r'; - *ptr++ = '\n'; - bcopy(data.bytes, ptr, data.length); - ptr += data.length; - *ptr++ = '\r'; - *ptr = '\n'; - data = chunk; - } - [self writeData:data - withCompletionBlock:^(BOOL success) { - - if (success) { - [self writeBodyWithCompletionBlock:block]; - } else { - block(NO); - } - - }]; - } else { - if (_response.usesChunkedTransferEncoding) { - [self writeData:_lastChunkData - withCompletionBlock:^(BOOL success) { - - block(success); - - }]; - } else { - block(YES); - } - } - } else { - GWS_LOG_ERROR(@"Failed reading response body for socket %i: %@", _socket, error); - block(NO); - } - - }]; -} - -@end - -@implementation GCDWebServerConnection (Subclassing) - -- (BOOL)open { -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ - if (_server.recordingEnabled) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - _connectionIndex = OSAtomicIncrement32(&_connectionCounter); -#pragma clang diagnostic pop - - _requestPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; - _requestFD = open([_requestPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - GWS_DCHECK(_requestFD > 0); - - _responsePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; - _responseFD = open([_responsePath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - GWS_DCHECK(_responseFD > 0); - } -#endif - - return YES; -} - -- (void)didReadBytes:(const void*)bytes length:(NSUInteger)length { - GWS_LOG_DEBUG(@"Connection received %lu bytes on socket %i", (unsigned long)length, _socket); - _totalBytesRead += length; - -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ - if ((_requestFD > 0) && (write(_requestFD, bytes, length) != (ssize_t)length)) { - GWS_LOG_ERROR(@"Failed recording request data: %s (%i)", strerror(errno), errno); - close(_requestFD); - _requestFD = 0; - } -#endif -} - -- (void)didWriteBytes:(const void*)bytes length:(NSUInteger)length { - GWS_LOG_DEBUG(@"Connection sent %lu bytes on socket %i", (unsigned long)length, _socket); - _totalBytesWritten += length; - -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ - if ((_responseFD > 0) && (write(_responseFD, bytes, length) != (ssize_t)length)) { - GWS_LOG_ERROR(@"Failed recording response data: %s (%i)", strerror(errno), errno); - close(_responseFD); - _responseFD = 0; - } -#endif -} - -- (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary*)headers { - return url; -} - -// https://tools.ietf.org/html/rfc2617 -- (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request { - GWS_LOG_DEBUG(@"Connection on socket %i preflighting request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_totalBytesRead); - GCDWebServerResponse* response = nil; - if (_server.authenticationBasicAccounts) { - __block BOOL authenticated = NO; - NSString* authorizationHeader = [request.headers objectForKey:@"Authorization"]; - if ([authorizationHeader hasPrefix:@"Basic "]) { - NSString* basicAccount = [authorizationHeader substringFromIndex:6]; - [_server.authenticationBasicAccounts enumerateKeysAndObjectsUsingBlock:^(NSString* username, NSString* digest, BOOL* stop) { - if ([basicAccount isEqualToString:digest]) { - authenticated = YES; - *stop = YES; - } - }]; - } - if (!authenticated) { - response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_Unauthorized]; - [response setValue:[NSString stringWithFormat:@"Basic realm=\"%@\"", _server.authenticationRealm] forAdditionalHeader:@"WWW-Authenticate"]; - } - } else if (_server.authenticationDigestAccounts) { - BOOL authenticated = NO; - BOOL isStaled = NO; - NSString* authorizationHeader = [request.headers objectForKey:@"Authorization"]; - if ([authorizationHeader hasPrefix:@"Digest "]) { - NSString* realm = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"realm"); - if ([realm isEqualToString:_server.authenticationRealm]) { - NSString* nonce = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"nonce"); - if ([nonce isEqualToString:_digestAuthenticationNonce]) { - NSString* username = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"username"); - NSString* uri = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"uri"); - NSString* actualResponse = GCDWebServerExtractHeaderValueParameter(authorizationHeader, @"response"); - NSString* ha1 = [_server.authenticationDigestAccounts objectForKey:username]; - NSString* ha2 = GCDWebServerComputeMD5Digest(@"%@:%@", request.method, uri); // We cannot use "request.path" as the query string is required - NSString* expectedResponse = GCDWebServerComputeMD5Digest(@"%@:%@:%@", ha1, _digestAuthenticationNonce, ha2); - if ([actualResponse isEqualToString:expectedResponse]) { - authenticated = YES; - } - } else if (nonce.length) { - isStaled = YES; - } - } - } - if (!authenticated) { - response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_Unauthorized]; - [response setValue:[NSString stringWithFormat:@"Digest realm=\"%@\", nonce=\"%@\"%@", _server.authenticationRealm, _digestAuthenticationNonce, isStaled ? @", stale=TRUE" : @""] forAdditionalHeader:@"WWW-Authenticate"]; // TODO: Support Quality of Protection ("qop") - } - } - return response; -} - -- (void)processRequest:(GCDWebServerRequest*)request completion:(GCDWebServerCompletionBlock)completion { - GWS_LOG_DEBUG(@"Connection on socket %i processing request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_totalBytesRead); - _handler.asyncProcessBlock(request, [completion copy]); -} - -// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 -// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26 -static inline BOOL _CompareResources(NSString* responseETag, NSString* requestETag, NSDate* responseLastModified, NSDate* requestLastModified) { - if (requestLastModified && responseLastModified) { - if ([responseLastModified compare:requestLastModified] != NSOrderedDescending) { - return YES; - } - } - if (requestETag && responseETag) { // Per the specs "If-None-Match" must be checked after "If-Modified-Since" - if ([requestETag isEqualToString:@"*"]) { - return YES; - } - if ([responseETag isEqualToString:requestETag]) { - return YES; - } - } - return NO; -} - -- (GCDWebServerResponse*)overrideResponse:(GCDWebServerResponse*)response forRequest:(GCDWebServerRequest*)request { - if ((response.statusCode >= 200) && (response.statusCode < 300) && _CompareResources(response.eTag, request.ifNoneMatch, response.lastModifiedDate, request.ifModifiedSince)) { - NSInteger code = [request.method isEqualToString:@"HEAD"] || [request.method isEqualToString:@"GET"] ? kGCDWebServerHTTPStatusCode_NotModified : kGCDWebServerHTTPStatusCode_PreconditionFailed; - GCDWebServerResponse* newResponse = [GCDWebServerResponse responseWithStatusCode:code]; - newResponse.cacheControlMaxAge = response.cacheControlMaxAge; - newResponse.lastModifiedDate = response.lastModifiedDate; - newResponse.eTag = response.eTag; - GWS_DCHECK(newResponse); - return newResponse; - } - return response; -} - -- (void)abortRequest:(GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode { - GWS_DCHECK(_responseMessage == NULL); - GWS_DCHECK((statusCode >= 400) && (statusCode < 600)); - [self _initializeResponseHeadersWithStatusCode:statusCode]; - [self writeHeadersWithCompletionBlock:^(BOOL success) { - ; // Nothing more to do - }]; - GWS_LOG_DEBUG(@"Connection aborted with status code %i on socket %i", (int)statusCode, _socket); -} - -- (void)close { -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ - if (_requestPath) { - BOOL success = NO; - NSError* error = nil; - if (_requestFD > 0) { - close(_requestFD); - NSString* name = [NSString stringWithFormat:@"%03lu-%@.request", (unsigned long)_connectionIndex, _virtualHEAD ? @"HEAD" : _request.method]; - success = [[NSFileManager defaultManager] moveItemAtPath:_requestPath toPath:[[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:name] error:&error]; - } - if (!success) { - GWS_LOG_ERROR(@"Failed saving recorded request: %@", error); - GWS_DNOT_REACHED(); - } - unlink([_requestPath fileSystemRepresentation]); - } - - if (_responsePath) { - BOOL success = NO; - NSError* error = nil; - if (_responseFD > 0) { - close(_responseFD); - NSString* name = [NSString stringWithFormat:@"%03lu-%i.response", (unsigned long)_connectionIndex, (int)_statusCode]; - success = [[NSFileManager defaultManager] moveItemAtPath:_responsePath toPath:[[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:name] error:&error]; - } - if (!success) { - GWS_LOG_ERROR(@"Failed saving recorded response: %@", error); - GWS_DNOT_REACHED(); - } - unlink([_responsePath fileSystemRepresentation]); - } -#endif - - if (_request) { - GWS_LOG_VERBOSE(@"[%@] %@ %i \"%@ %@\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_totalBytesRead, (unsigned long)_totalBytesWritten); - } else { - GWS_LOG_VERBOSE(@"[%@] %@ %i \"(invalid request)\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, (unsigned long)_totalBytesRead, (unsigned long)_totalBytesWritten); - } -} - -@end diff --git a/src/ios/GCDWebServer/Core/GCDWebServerFunctions.h b/src/ios/GCDWebServer/Core/GCDWebServerFunctions.h deleted file mode 100755 index 4235ecc..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerFunctions.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Converts a file extension to the corresponding MIME type. - * If there is no match, "application/octet-stream" is returned. - * - * Overrides allow to customize the built-in mapping from extensions to MIME - * types. Keys of the dictionary must be lowercased file extensions without - * the period, and the values must be the corresponding MIME types. - */ -NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary* _Nullable overrides); - -/** - * Add percent-escapes to a string so it can be used in a URL. - * The legal characters ":@/?&=+" are also escaped to ensure compatibility - * with URL encoded forms and URL queries. - */ -NSString* _Nullable GCDWebServerEscapeURLString(NSString* string); - -/** - * Unescapes a URL percent-encoded string. - */ -NSString* _Nullable GCDWebServerUnescapeURLString(NSString* string); - -/** - * Extracts the unescaped names and values from an - * "application/x-www-form-urlencoded" form. - * http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 - */ -NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form); - -/** - * On OS X, returns the IPv4 or IPv6 address as a string of the primary - * connected service or nil if not available. - * - * On iOS, returns the IPv4 or IPv6 address as a string of the WiFi - * interface if connected or nil otherwise. - */ -NSString* _Nullable GCDWebServerGetPrimaryIPAddress(BOOL useIPv6); - -/** - * Converts a date into a string using RFC822 formatting. - * https://tools.ietf.org/html/rfc822#section-5 - * https://tools.ietf.org/html/rfc1123#section-5.2.14 - */ -NSString* GCDWebServerFormatRFC822(NSDate* date); - -/** - * Converts a RFC822 formatted string into a date. - * https://tools.ietf.org/html/rfc822#section-5 - * https://tools.ietf.org/html/rfc1123#section-5.2.14 - * - * @warning Timezones other than GMT are not supported by this function. - */ -NSDate* _Nullable GCDWebServerParseRFC822(NSString* string); - -/** - * Converts a date into a string using IOS 8601 formatting. - * http://tools.ietf.org/html/rfc3339#section-5.6 - */ -NSString* GCDWebServerFormatISO8601(NSDate* date); - -/** - * Converts a ISO 8601 formatted string into a date. - * http://tools.ietf.org/html/rfc3339#section-5.6 - * - * @warning Only "calendar" variant is supported at this time and timezones - * other than GMT are not supported either. - */ -NSDate* _Nullable GCDWebServerParseISO8601(NSString* string); - -#ifdef __cplusplus -} -#endif - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Core/GCDWebServerFunctions.m b/src/ios/GCDWebServer/Core/GCDWebServerFunctions.m deleted file mode 100755 index ec50086..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerFunctions.m +++ /dev/null @@ -1,316 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import -#if TARGET_OS_IPHONE -#import -#else -#import -#endif -#import - -#import -#import -#import - -#import "GCDWebServerPrivate.h" - -static NSDateFormatter* _dateFormatterRFC822 = nil; -static NSDateFormatter* _dateFormatterISO8601 = nil; -static dispatch_queue_t _dateFormatterQueue = NULL; - -// TODO: Handle RFC 850 and ANSI C's asctime() format -void GCDWebServerInitializeFunctions() { - GWS_DCHECK([NSThread isMainThread]); // NSDateFormatter should be initialized on main thread - if (_dateFormatterRFC822 == nil) { - _dateFormatterRFC822 = [[NSDateFormatter alloc] init]; - _dateFormatterRFC822.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; - _dateFormatterRFC822.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'"; - _dateFormatterRFC822.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; - GWS_DCHECK(_dateFormatterRFC822); - } - if (_dateFormatterISO8601 == nil) { - _dateFormatterISO8601 = [[NSDateFormatter alloc] init]; - _dateFormatterISO8601.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; - _dateFormatterISO8601.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'+00:00'"; - _dateFormatterISO8601.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; - GWS_DCHECK(_dateFormatterISO8601); - } - if (_dateFormatterQueue == NULL) { - _dateFormatterQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - GWS_DCHECK(_dateFormatterQueue); - } -} - -NSString* GCDWebServerNormalizeHeaderValue(NSString* value) { - if (value) { - NSRange range = [value rangeOfString:@";"]; // Assume part before ";" separator is case-insensitive - if (range.location != NSNotFound) { - value = [[[value substringToIndex:range.location] lowercaseString] stringByAppendingString:[value substringFromIndex:range.location]]; - } else { - value = [value lowercaseString]; - } - } - return value; -} - -NSString* GCDWebServerTruncateHeaderValue(NSString* value) { - if (value) { - NSRange range = [value rangeOfString:@";"]; - if (range.location != NSNotFound) { - return [value substringToIndex:range.location]; - } - } - return value; -} - -NSString* GCDWebServerExtractHeaderValueParameter(NSString* value, NSString* name) { - NSString* parameter = nil; - if (value) { - NSScanner* scanner = [[NSScanner alloc] initWithString:value]; - [scanner setCaseSensitive:NO]; // Assume parameter names are case-insensitive - NSString* string = [NSString stringWithFormat:@"%@=", name]; - if ([scanner scanUpToString:string intoString:NULL]) { - [scanner scanString:string intoString:NULL]; - if ([scanner scanString:@"\"" intoString:NULL]) { - [scanner scanUpToString:@"\"" intoString:¶meter]; - } else { - [scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:¶meter]; - } - } - } - return parameter; -} - -// http://www.w3schools.com/tags/ref_charactersets.asp -NSStringEncoding GCDWebServerStringEncodingFromCharset(NSString* charset) { - NSStringEncoding encoding = kCFStringEncodingInvalidId; - if (charset) { - encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)charset)); - } - return (encoding != kCFStringEncodingInvalidId ? encoding : NSUTF8StringEncoding); -} - -NSString* GCDWebServerFormatRFC822(NSDate* date) { - __block NSString* string; - dispatch_sync(_dateFormatterQueue, ^{ - string = [_dateFormatterRFC822 stringFromDate:date]; - }); - return string; -} - -NSDate* GCDWebServerParseRFC822(NSString* string) { - __block NSDate* date; - dispatch_sync(_dateFormatterQueue, ^{ - date = [_dateFormatterRFC822 dateFromString:string]; - }); - return date; -} - -NSString* GCDWebServerFormatISO8601(NSDate* date) { - __block NSString* string; - dispatch_sync(_dateFormatterQueue, ^{ - string = [_dateFormatterISO8601 stringFromDate:date]; - }); - return string; -} - -NSDate* GCDWebServerParseISO8601(NSString* string) { - __block NSDate* date; - dispatch_sync(_dateFormatterQueue, ^{ - date = [_dateFormatterISO8601 dateFromString:string]; - }); - return date; -} - -BOOL GCDWebServerIsTextContentType(NSString* type) { - return ([type hasPrefix:@"text/"] || [type hasPrefix:@"application/json"] || [type hasPrefix:@"application/xml"]); -} - -NSString* GCDWebServerDescribeData(NSData* data, NSString* type) { - if (GCDWebServerIsTextContentType(type)) { - NSString* charset = GCDWebServerExtractHeaderValueParameter(type, @"charset"); - NSString* string = [[NSString alloc] initWithData:data encoding:GCDWebServerStringEncodingFromCharset(charset)]; - if (string) { - return string; - } - } - return [NSString stringWithFormat:@"<%lu bytes>", (unsigned long)data.length]; -} - -NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary* overrides) { - NSDictionary* builtInOverrides = @{@"css": @"text/css"}; - NSString* mimeType = nil; - extension = [extension lowercaseString]; - if (extension.length) { - mimeType = [overrides objectForKey:extension]; - if (mimeType == nil) { - mimeType = [builtInOverrides objectForKey:extension]; - } - if (mimeType == nil) { - CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL); - if (uti) { - mimeType = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)); - CFRelease(uti); - } - } - } - return mimeType ? mimeType : kGCDWebServerDefaultMimeType; -} - -NSString* GCDWebServerEscapeURLString(NSString* string) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(":@/?&=+"), kCFStringEncodingUTF8)); -#pragma clang diagnostic pop -} - -NSString* GCDWebServerUnescapeURLString(NSString* string) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - return CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (CFStringRef)string, CFSTR(""), kCFStringEncodingUTF8)); -#pragma clang diagnostic pop -} - -NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form) { - NSMutableDictionary* parameters = [NSMutableDictionary dictionary]; - NSScanner* scanner = [[NSScanner alloc] initWithString:form]; - [scanner setCharactersToBeSkipped:nil]; - while (1) { - NSString* key = nil; - if (![scanner scanUpToString:@"=" intoString:&key] || [scanner isAtEnd]) { - break; - } - [scanner setScanLocation:([scanner scanLocation] + 1)]; - - NSString* value = nil; - [scanner scanUpToString:@"&" intoString:&value]; - if (value == nil) { - value = @""; - } - - key = [key stringByReplacingOccurrencesOfString:@"+" withString:@" "]; - NSString* unescapedKey = key ? GCDWebServerUnescapeURLString(key) : nil; - value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "]; - NSString* unescapedValue = value ? GCDWebServerUnescapeURLString(value) : nil; - if (unescapedKey && unescapedValue) { - [parameters setObject:unescapedValue forKey:unescapedKey]; - } else { - GWS_LOG_WARNING(@"Failed parsing URL encoded form for key \"%@\" and value \"%@\"", key, value); - GWS_DNOT_REACHED(); - } - - if ([scanner isAtEnd]) { - break; - } - [scanner setScanLocation:([scanner scanLocation] + 1)]; - } - return parameters; -} - -NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL includeService) { - char hostBuffer[NI_MAXHOST]; - char serviceBuffer[NI_MAXSERV]; - if (getnameinfo(addr, addr->sa_len, hostBuffer, sizeof(hostBuffer), serviceBuffer, sizeof(serviceBuffer), NI_NUMERICHOST | NI_NUMERICSERV | NI_NOFQDN) != 0) { -#if DEBUG - GWS_DNOT_REACHED(); -#else - return @""; -#endif - } - return includeService ? [NSString stringWithFormat:@"%s:%s", hostBuffer, serviceBuffer] : (NSString*)[NSString stringWithUTF8String:hostBuffer]; -} - -NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6) { - NSString* address = nil; -#if TARGET_OS_IPHONE -#if !TARGET_IPHONE_SIMULATOR && !TARGET_OS_TV - const char* primaryInterface = "en0"; // WiFi interface on iOS -#endif -#else - const char* primaryInterface = NULL; - SCDynamicStoreRef store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("GCDWebServer"), NULL, NULL); - if (store) { - CFPropertyListRef info = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4")); // There is no equivalent for IPv6 but the primary interface should be the same - if (info) { - NSString* interface = [(__bridge NSDictionary*)info objectForKey:@"PrimaryInterface"]; - if (interface) { - primaryInterface = [[NSString stringWithString:interface] UTF8String]; // Copy string to auto-release pool - } - CFRelease(info); - } - CFRelease(store); - } - if (primaryInterface == NULL) { - primaryInterface = "lo0"; - } -#endif - struct ifaddrs* list; - if (getifaddrs(&list) >= 0) { - for (struct ifaddrs* ifap = list; ifap; ifap = ifap->ifa_next) { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_TV - // Assume en0 is Ethernet and en1 is WiFi since there is no way to use SystemConfiguration framework in iOS Simulator - // Assumption holds for Apple TV running tvOS - if (strcmp(ifap->ifa_name, "en0") && strcmp(ifap->ifa_name, "en1")) -#else - if (strcmp(ifap->ifa_name, primaryInterface)) -#endif - { - continue; - } - if ((ifap->ifa_flags & IFF_UP) && ((!useIPv6 && (ifap->ifa_addr->sa_family == AF_INET)) || (useIPv6 && (ifap->ifa_addr->sa_family == AF_INET6)))) { - address = GCDWebServerStringFromSockAddr(ifap->ifa_addr, NO); - break; - } - } - freeifaddrs(list); - } - return address; -} - -NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) { - va_list arguments; - va_start(arguments, format); - const char* string = [[[NSString alloc] initWithFormat:format arguments:arguments] UTF8String]; - va_end(arguments); - unsigned char md5[CC_MD5_DIGEST_LENGTH]; - CC_MD5(string, (CC_LONG)strlen(string), md5); - char buffer[2 * CC_MD5_DIGEST_LENGTH + 1]; - for (int i = 0; i < CC_MD5_DIGEST_LENGTH; ++i) { - unsigned char byte = md5[i]; - unsigned char byteHi = (byte & 0xF0) >> 4; - buffer[2 * i + 0] = byteHi >= 10 ? 'a' + byteHi - 10 : '0' + byteHi; - unsigned char byteLo = byte & 0x0F; - buffer[2 * i + 1] = byteLo >= 10 ? 'a' + byteLo - 10 : '0' + byteLo; - } - buffer[2 * CC_MD5_DIGEST_LENGTH] = 0; - return (NSString*)[NSString stringWithUTF8String:buffer]; -} diff --git a/src/ios/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h b/src/ios/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h deleted file mode 100755 index 6e98381..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html -// http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml - -#import - -/** - * Convenience constants for "informational" HTTP status codes. - */ -typedef NS_ENUM(NSInteger, GCDWebServerInformationalHTTPStatusCode) { - kGCDWebServerHTTPStatusCode_Continue = 100, - kGCDWebServerHTTPStatusCode_SwitchingProtocols = 101, - kGCDWebServerHTTPStatusCode_Processing = 102 -}; - -/** - * Convenience constants for "successful" HTTP status codes. - */ -typedef NS_ENUM(NSInteger, GCDWebServerSuccessfulHTTPStatusCode) { - kGCDWebServerHTTPStatusCode_OK = 200, - kGCDWebServerHTTPStatusCode_Created = 201, - kGCDWebServerHTTPStatusCode_Accepted = 202, - kGCDWebServerHTTPStatusCode_NonAuthoritativeInformation = 203, - kGCDWebServerHTTPStatusCode_NoContent = 204, - kGCDWebServerHTTPStatusCode_ResetContent = 205, - kGCDWebServerHTTPStatusCode_PartialContent = 206, - kGCDWebServerHTTPStatusCode_MultiStatus = 207, - kGCDWebServerHTTPStatusCode_AlreadyReported = 208 -}; - -/** - * Convenience constants for "redirection" HTTP status codes. - */ -typedef NS_ENUM(NSInteger, GCDWebServerRedirectionHTTPStatusCode) { - kGCDWebServerHTTPStatusCode_MultipleChoices = 300, - kGCDWebServerHTTPStatusCode_MovedPermanently = 301, - kGCDWebServerHTTPStatusCode_Found = 302, - kGCDWebServerHTTPStatusCode_SeeOther = 303, - kGCDWebServerHTTPStatusCode_NotModified = 304, - kGCDWebServerHTTPStatusCode_UseProxy = 305, - kGCDWebServerHTTPStatusCode_TemporaryRedirect = 307, - kGCDWebServerHTTPStatusCode_PermanentRedirect = 308 -}; - -/** - * Convenience constants for "client error" HTTP status codes. - */ -typedef NS_ENUM(NSInteger, GCDWebServerClientErrorHTTPStatusCode) { - kGCDWebServerHTTPStatusCode_BadRequest = 400, - kGCDWebServerHTTPStatusCode_Unauthorized = 401, - kGCDWebServerHTTPStatusCode_PaymentRequired = 402, - kGCDWebServerHTTPStatusCode_Forbidden = 403, - kGCDWebServerHTTPStatusCode_NotFound = 404, - kGCDWebServerHTTPStatusCode_MethodNotAllowed = 405, - kGCDWebServerHTTPStatusCode_NotAcceptable = 406, - kGCDWebServerHTTPStatusCode_ProxyAuthenticationRequired = 407, - kGCDWebServerHTTPStatusCode_RequestTimeout = 408, - kGCDWebServerHTTPStatusCode_Conflict = 409, - kGCDWebServerHTTPStatusCode_Gone = 410, - kGCDWebServerHTTPStatusCode_LengthRequired = 411, - kGCDWebServerHTTPStatusCode_PreconditionFailed = 412, - kGCDWebServerHTTPStatusCode_RequestEntityTooLarge = 413, - kGCDWebServerHTTPStatusCode_RequestURITooLong = 414, - kGCDWebServerHTTPStatusCode_UnsupportedMediaType = 415, - kGCDWebServerHTTPStatusCode_RequestedRangeNotSatisfiable = 416, - kGCDWebServerHTTPStatusCode_ExpectationFailed = 417, - kGCDWebServerHTTPStatusCode_UnprocessableEntity = 422, - kGCDWebServerHTTPStatusCode_Locked = 423, - kGCDWebServerHTTPStatusCode_FailedDependency = 424, - kGCDWebServerHTTPStatusCode_UpgradeRequired = 426, - kGCDWebServerHTTPStatusCode_PreconditionRequired = 428, - kGCDWebServerHTTPStatusCode_TooManyRequests = 429, - kGCDWebServerHTTPStatusCode_RequestHeaderFieldsTooLarge = 431 -}; - -/** - * Convenience constants for "server error" HTTP status codes. - */ -typedef NS_ENUM(NSInteger, GCDWebServerServerErrorHTTPStatusCode) { - kGCDWebServerHTTPStatusCode_InternalServerError = 500, - kGCDWebServerHTTPStatusCode_NotImplemented = 501, - kGCDWebServerHTTPStatusCode_BadGateway = 502, - kGCDWebServerHTTPStatusCode_ServiceUnavailable = 503, - kGCDWebServerHTTPStatusCode_GatewayTimeout = 504, - kGCDWebServerHTTPStatusCode_HTTPVersionNotSupported = 505, - kGCDWebServerHTTPStatusCode_InsufficientStorage = 507, - kGCDWebServerHTTPStatusCode_LoopDetected = 508, - kGCDWebServerHTTPStatusCode_NotExtended = 510, - kGCDWebServerHTTPStatusCode_NetworkAuthenticationRequired = 511 -}; diff --git a/src/ios/GCDWebServer/Core/GCDWebServerPrivate.h b/src/ios/GCDWebServer/Core/GCDWebServerPrivate.h deleted file mode 100755 index e1e6353..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerPrivate.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import -#import - -/** - * All GCDWebServer headers. - */ - -#import "GCDWebServerHTTPStatusCodes.h" -#import "GCDWebServerFunctions.h" - -#import "GCDWebServer.h" -#import "GCDWebServerConnection.h" - -#import "GCDWebServerDataRequest.h" -#import "GCDWebServerFileRequest.h" -#import "GCDWebServerMultiPartFormRequest.h" -#import "GCDWebServerURLEncodedFormRequest.h" - -#import "GCDWebServerDataResponse.h" -#import "GCDWebServerErrorResponse.h" -#import "GCDWebServerFileResponse.h" -#import "GCDWebServerStreamedResponse.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * Check if a custom logging facility should be used instead. - */ - -#if defined(__GCDWEBSERVER_LOGGING_HEADER__) - -#define __GCDWEBSERVER_LOGGING_FACILITY_CUSTOM__ - -#import __GCDWEBSERVER_LOGGING_HEADER__ - -/** - * Automatically detect if XLFacility is available and if so use it as a - * logging facility. - */ - -#elif defined(__has_include) && __has_include("XLFacilityMacros.h") - -#define __GCDWEBSERVER_LOGGING_FACILITY_XLFACILITY__ - -#undef XLOG_TAG -#define XLOG_TAG @"gcdwebserver.internal" - -#import "XLFacilityMacros.h" - -#define GWS_LOG_DEBUG(...) XLOG_DEBUG(__VA_ARGS__) -#define GWS_LOG_VERBOSE(...) XLOG_VERBOSE(__VA_ARGS__) -#define GWS_LOG_INFO(...) XLOG_INFO(__VA_ARGS__) -#define GWS_LOG_WARNING(...) XLOG_WARNING(__VA_ARGS__) -#define GWS_LOG_ERROR(...) XLOG_ERROR(__VA_ARGS__) - -#define GWS_DCHECK(__CONDITION__) XLOG_DEBUG_CHECK(__CONDITION__) -#define GWS_DNOT_REACHED() XLOG_DEBUG_UNREACHABLE() - -/** - * Automatically detect if CocoaLumberJack is available and if so use - * it as a logging facility. - */ - -#elif defined(__has_include) && __has_include("CocoaLumberjack/CocoaLumberjack.h") - -#import - -#define __GCDWEBSERVER_LOGGING_FACILITY_COCOALUMBERJACK__ - -#undef LOG_LEVEL_DEF -#define LOG_LEVEL_DEF GCDWebServerLogLevel -extern DDLogLevel GCDWebServerLogLevel; - -#define GWS_LOG_DEBUG(...) DDLogDebug(__VA_ARGS__) -#define GWS_LOG_VERBOSE(...) DDLogVerbose(__VA_ARGS__) -#define GWS_LOG_INFO(...) DDLogInfo(__VA_ARGS__) -#define GWS_LOG_WARNING(...) DDLogWarn(__VA_ARGS__) -#define GWS_LOG_ERROR(...) DDLogError(__VA_ARGS__) - -/** - * If all of the above fail, then use GCDWebServer built-in - * logging facility. - */ - -#else - -#define __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__ - -typedef NS_ENUM(int, GCDWebServerLoggingLevel) { - kGCDWebServerLoggingLevel_Debug = 0, - kGCDWebServerLoggingLevel_Verbose, - kGCDWebServerLoggingLevel_Info, - kGCDWebServerLoggingLevel_Warning, - kGCDWebServerLoggingLevel_Error -}; - -extern GCDWebServerLoggingLevel GCDWebServerLogLevel; -extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) NS_FORMAT_FUNCTION(2, 3); - -#if DEBUG -#define GWS_LOG_DEBUG(...) \ - do { \ - if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Debug) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Debug, __VA_ARGS__); \ - } while (0) -#else -#define GWS_LOG_DEBUG(...) -#endif -#define GWS_LOG_VERBOSE(...) \ - do { \ - if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Verbose) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Verbose, __VA_ARGS__); \ - } while (0) -#define GWS_LOG_INFO(...) \ - do { \ - if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Info) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Info, __VA_ARGS__); \ - } while (0) -#define GWS_LOG_WARNING(...) \ - do { \ - if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Warning) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Warning, __VA_ARGS__); \ - } while (0) -#define GWS_LOG_ERROR(...) \ - do { \ - if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Error) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Error, __VA_ARGS__); \ - } while (0) - -#endif - -/** - * Consistency check macros used when building Debug only. - */ - -#if !defined(GWS_DCHECK) || !defined(GWS_DNOT_REACHED) - -#if DEBUG - -#define GWS_DCHECK(__CONDITION__) \ - do { \ - if (!(__CONDITION__)) { \ - abort(); \ - } \ - } while (0) -#define GWS_DNOT_REACHED() abort() - -#else - -#define GWS_DCHECK(__CONDITION__) -#define GWS_DNOT_REACHED() - -#endif - -#endif - -/** - * GCDWebServer internal constants and APIs. - */ - -#define kGCDWebServerDefaultMimeType @"application/octet-stream" -#define kGCDWebServerErrorDomain @"GCDWebServerErrorDomain" - -static inline BOOL GCDWebServerIsValidByteRange(NSRange range) { - return ((range.location != NSUIntegerMax) || (range.length > 0)); -} - -static inline NSError* GCDWebServerMakePosixError(int code) { - return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithUTF8String:strerror(code)]}]; -} - -extern void GCDWebServerInitializeFunctions(); -extern NSString* _Nullable GCDWebServerNormalizeHeaderValue(NSString* _Nullable value); -extern NSString* _Nullable GCDWebServerTruncateHeaderValue(NSString* _Nullable value); -extern NSString* _Nullable GCDWebServerExtractHeaderValueParameter(NSString* _Nullable value, NSString* attribute); -extern NSStringEncoding GCDWebServerStringEncodingFromCharset(NSString* charset); -extern BOOL GCDWebServerIsTextContentType(NSString* type); -extern NSString* GCDWebServerDescribeData(NSData* data, NSString* contentType); -extern NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) NS_FORMAT_FUNCTION(1, 2); -extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL includeService); - -@interface GCDWebServerConnection () -- (instancetype)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket; -@end - -@interface GCDWebServer () -@property(nonatomic, readonly) NSMutableArray* handlers; -@property(nonatomic, readonly) NSString* serverName; -@property(nonatomic, readonly) NSString* authenticationRealm; -@property(nonatomic, readonly) NSMutableDictionary* authenticationBasicAccounts; -@property(nonatomic, readonly) NSMutableDictionary* authenticationDigestAccounts; -@property(nonatomic, readonly) BOOL shouldAutomaticallyMapHEADToGET; -@property(nonatomic, readonly) dispatch_queue_priority_t dispatchQueuePriority; -- (void)willStartConnection:(GCDWebServerConnection*)connection; -- (void)didEndConnection:(GCDWebServerConnection*)connection; -@end - -@interface GCDWebServerHandler : NSObject -@property(nonatomic, readonly) GCDWebServerMatchBlock matchBlock; -@property(nonatomic, readonly) GCDWebServerAsyncProcessBlock asyncProcessBlock; -@end - -@interface GCDWebServerRequest () -@property(nonatomic, readonly) BOOL usesChunkedTransferEncoding; -@property(nonatomic) NSData* localAddressData; -@property(nonatomic) NSData* remoteAddressData; -- (void)prepareForWriting; -- (BOOL)performOpen:(NSError**)error; -- (BOOL)performWriteData:(NSData*)data error:(NSError**)error; -- (BOOL)performClose:(NSError**)error; -- (void)setAttribute:(nullable id)attribute forKey:(NSString*)key; -@end - -@interface GCDWebServerResponse () -@property(nonatomic, readonly) NSDictionary* additionalHeaders; -@property(nonatomic, readonly) BOOL usesChunkedTransferEncoding; -- (void)prepareForReading; -- (BOOL)performOpen:(NSError**)error; -- (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block; -- (void)performClose; -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Core/GCDWebServerRequest.h b/src/ios/GCDWebServer/Core/GCDWebServerRequest.h deleted file mode 100755 index 3fe9029..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerRequest.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - * Attribute key to retrieve an NSArray containing NSStrings from a GCDWebServerRequest - * with the contents of any regular expression captures done on the request path. - * - * @warning This attribute will only be set on the request if adding a handler using - * -addHandlerForMethod:pathRegex:requestClass:processBlock:. - */ -extern NSString* const GCDWebServerRequestAttribute_RegexCaptures; - -/** - * This protocol is used by the GCDWebServerConnection to communicate with - * the GCDWebServerRequest and write the received HTTP body data. - * - * Note that multiple GCDWebServerBodyWriter objects can be chained together - * internally e.g. to automatically decode gzip encoded content before - * passing it on to the GCDWebServerRequest. - * - * @warning These methods can be called on any GCD thread. - */ -@protocol GCDWebServerBodyWriter - -/** - * This method is called before any body data is received. - * - * It should return YES on success or NO on failure and set the "error" argument - * which is guaranteed to be non-NULL. - */ -- (BOOL)open:(NSError**)error; - -/** - * This method is called whenever body data has been received. - * - * It should return YES on success or NO on failure and set the "error" argument - * which is guaranteed to be non-NULL. - */ -- (BOOL)writeData:(NSData*)data error:(NSError**)error; - -/** - * This method is called after all body data has been received. - * - * It should return YES on success or NO on failure and set the "error" argument - * which is guaranteed to be non-NULL. - */ -- (BOOL)close:(NSError**)error; - -@end - -/** - * The GCDWebServerRequest class is instantiated by the GCDWebServerConnection - * after the HTTP headers have been received. Each instance wraps a single HTTP - * request. If a body is present, the methods from the GCDWebServerBodyWriter - * protocol will be called by the GCDWebServerConnection to receive it. - * - * The default implementation of the GCDWebServerBodyWriter protocol on the class - * simply ignores the body data. - * - * @warning GCDWebServerRequest instances can be created and used on any GCD thread. - */ -@interface GCDWebServerRequest : NSObject - -/** - * Returns the HTTP method for the request. - */ -@property(nonatomic, readonly) NSString* method; - -/** - * Returns the URL for the request. - */ -@property(nonatomic, readonly) NSURL* URL; - -/** - * Returns the HTTP headers for the request. - */ -@property(nonatomic, readonly) NSDictionary* headers; - -/** - * Returns the path component of the URL for the request. - */ -@property(nonatomic, readonly) NSString* path; - -/** - * Returns the parsed and unescaped query component of the URL for the request. - * - * @warning This property will be nil if there is no query in the URL. - */ -@property(nonatomic, readonly, nullable) NSDictionary* query; - -/** - * Returns the content type for the body of the request parsed from the - * "Content-Type" header. - * - * This property will be nil if the request has no body or set to - * "application/octet-stream" if a body is present but there was no - * "Content-Type" header. - */ -@property(nonatomic, readonly, nullable) NSString* contentType; - -/** - * Returns the content length for the body of the request parsed from the - * "Content-Length" header. - * - * This property will be set to "NSUIntegerMax" if the request has no body or - * if there is a body but no "Content-Length" header, typically because - * chunked transfer encoding is used. - */ -@property(nonatomic, readonly) NSUInteger contentLength; - -/** - * Returns the parsed "If-Modified-Since" header or nil if absent or malformed. - */ -@property(nonatomic, readonly, nullable) NSDate* ifModifiedSince; - -/** - * Returns the parsed "If-None-Match" header or nil if absent or malformed. - */ -@property(nonatomic, readonly, nullable) NSString* ifNoneMatch; - -/** - * Returns the parsed "Range" header or (NSUIntegerMax, 0) if absent or malformed. - * The range will be set to (offset, length) if expressed from the beginning - * of the entity body, or (NSUIntegerMax, length) if expressed from its end. - */ -@property(nonatomic, readonly) NSRange byteRange; - -/** - * Returns YES if the client supports gzip content encoding according to the - * "Accept-Encoding" header. - */ -@property(nonatomic, readonly) BOOL acceptsGzipContentEncoding; - -/** - * Returns the address of the local peer (i.e. server) for the request - * as a raw "struct sockaddr". - */ -@property(nonatomic, readonly) NSData* localAddressData; - -/** - * Returns the address of the local peer (i.e. server) for the request - * as a string. - */ -@property(nonatomic, readonly) NSString* localAddressString; - -/** - * Returns the address of the remote peer (i.e. client) for the request - * as a raw "struct sockaddr". - */ -@property(nonatomic, readonly) NSData* remoteAddressData; - -/** - * Returns the address of the remote peer (i.e. client) for the request - * as a string. - */ -@property(nonatomic, readonly) NSString* remoteAddressString; - -/** - * This method is the designated initializer for the class. - */ -- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(nullable NSDictionary*)query; - -/** - * Convenience method that checks if the contentType property is defined. - */ -- (BOOL)hasBody; - -/** - * Convenience method that checks if the byteRange property is defined. - */ -- (BOOL)hasByteRange; - -/** - * Retrieves an attribute associated with this request using the given key. - * - * @return The attribute value for the key. - */ -- (nullable id)attributeForKey:(NSString*)key; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Core/GCDWebServerRequest.m b/src/ios/GCDWebServer/Core/GCDWebServerRequest.m deleted file mode 100755 index 05988cd..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerRequest.m +++ /dev/null @@ -1,303 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import - -#import "GCDWebServerPrivate.h" - -NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerRequestAttribute_RegexCaptures"; - -#define kZlibErrorDomain @"ZlibErrorDomain" -#define kGZipInitialBufferSize (256 * 1024) - -@interface GCDWebServerBodyDecoder : NSObject -@end - -@interface GCDWebServerGZipDecoder : GCDWebServerBodyDecoder -@end - -@implementation GCDWebServerBodyDecoder { - GCDWebServerRequest* __unsafe_unretained _request; - id __unsafe_unretained _writer; -} - -- (instancetype)initWithRequest:(GCDWebServerRequest* _Nonnull)request writer:(id _Nonnull)writer { - if ((self = [super init])) { - _request = request; - _writer = writer; - } - return self; -} - -- (BOOL)open:(NSError**)error { - return [_writer open:error]; -} - -- (BOOL)writeData:(NSData*)data error:(NSError**)error { - return [_writer writeData:data error:error]; -} - -- (BOOL)close:(NSError**)error { - return [_writer close:error]; -} - -@end - -@implementation GCDWebServerGZipDecoder { - z_stream _stream; - BOOL _finished; -} - -- (BOOL)open:(NSError**)error { - int result = inflateInit2(&_stream, 15 + 16); - if (result != Z_OK) { - if (error) { - *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil]; - } - return NO; - } - if (![super open:error]) { - inflateEnd(&_stream); - return NO; - } - return YES; -} - -- (BOOL)writeData:(NSData*)data error:(NSError**)error { - GWS_DCHECK(!_finished); - _stream.next_in = (Bytef*)data.bytes; - _stream.avail_in = (uInt)data.length; - NSMutableData* decodedData = [[NSMutableData alloc] initWithLength:kGZipInitialBufferSize]; - if (decodedData == nil) { - GWS_DNOT_REACHED(); - return NO; - } - NSUInteger length = 0; - while (1) { - NSUInteger maxLength = decodedData.length - length; - _stream.next_out = (Bytef*)((char*)decodedData.mutableBytes + length); - _stream.avail_out = (uInt)maxLength; - int result = inflate(&_stream, Z_NO_FLUSH); - if ((result != Z_OK) && (result != Z_STREAM_END)) { - if (error) { - *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil]; - } - return NO; - } - length += maxLength - _stream.avail_out; - if (_stream.avail_out > 0) { - if (result == Z_STREAM_END) { - _finished = YES; - } - break; - } - decodedData.length = 2 * decodedData.length; // zlib has used all the output buffer so resize it and try again in case more data is available - } - decodedData.length = length; - BOOL success = length ? [super writeData:decodedData error:error] : YES; // No need to call writer if we have no data yet - return success; -} - -- (BOOL)close:(NSError**)error { - GWS_DCHECK(_finished); - inflateEnd(&_stream); - return [super close:error]; -} - -@end - -@implementation GCDWebServerRequest { - BOOL _opened; - NSMutableArray* _decoders; - id __unsafe_unretained _writer; - NSMutableDictionary* _attributes; -} - -- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { - if ((self = [super init])) { - _method = [method copy]; - _URL = url; - _headers = headers; - _path = [path copy]; - _query = query; - - _contentType = GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Content-Type"]); - _usesChunkedTransferEncoding = [GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Transfer-Encoding"]) isEqualToString:@"chunked"]; - NSString* lengthHeader = [_headers objectForKey:@"Content-Length"]; - if (lengthHeader) { - NSInteger length = [lengthHeader integerValue]; - if (_usesChunkedTransferEncoding || (length < 0)) { - GWS_LOG_WARNING(@"Invalid 'Content-Length' header '%@' for '%@' request on \"%@\"", lengthHeader, _method, _URL); - GWS_DNOT_REACHED(); - return nil; - } - _contentLength = length; - if (_contentType == nil) { - _contentType = kGCDWebServerDefaultMimeType; - } - } else if (_usesChunkedTransferEncoding) { - if (_contentType == nil) { - _contentType = kGCDWebServerDefaultMimeType; - } - _contentLength = NSUIntegerMax; - } else { - if (_contentType) { - GWS_LOG_WARNING(@"Ignoring 'Content-Type' header for '%@' request on \"%@\"", _method, _URL); - _contentType = nil; // Content-Type without Content-Length or chunked-encoding doesn't make sense - } - _contentLength = NSUIntegerMax; - } - - NSString* modifiedHeader = [_headers objectForKey:@"If-Modified-Since"]; - if (modifiedHeader) { - _ifModifiedSince = [GCDWebServerParseRFC822(modifiedHeader) copy]; - } - _ifNoneMatch = [_headers objectForKey:@"If-None-Match"]; - - _byteRange = NSMakeRange(NSUIntegerMax, 0); - NSString* rangeHeader = GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Range"]); - if (rangeHeader) { - if ([rangeHeader hasPrefix:@"bytes="]) { - NSArray* components = [[rangeHeader substringFromIndex:6] componentsSeparatedByString:@","]; - if (components.count == 1) { - components = [[components firstObject] componentsSeparatedByString:@"-"]; - if (components.count == 2) { - NSString* startString = [components objectAtIndex:0]; - NSInteger startValue = [startString integerValue]; - NSString* endString = [components objectAtIndex:1]; - NSInteger endValue = [endString integerValue]; - if (startString.length && (startValue >= 0) && endString.length && (endValue >= startValue)) { // The second 500 bytes: "500-999" - _byteRange.location = startValue; - _byteRange.length = endValue - startValue + 1; - } else if (startString.length && (startValue >= 0)) { // The bytes after 9500 bytes: "9500-" - _byteRange.location = startValue; - _byteRange.length = NSUIntegerMax; - } else if (endString.length && (endValue > 0)) { // The final 500 bytes: "-500" - _byteRange.location = NSUIntegerMax; - _byteRange.length = endValue; - } - } - } - } - if ((_byteRange.location == NSUIntegerMax) && (_byteRange.length == 0)) { // Ignore "Range" header if syntactically invalid - GWS_LOG_WARNING(@"Failed to parse 'Range' header \"%@\" for url: %@", rangeHeader, url); - } - } - - if ([[_headers objectForKey:@"Accept-Encoding"] rangeOfString:@"gzip"].location != NSNotFound) { - _acceptsGzipContentEncoding = YES; - } - - _decoders = [[NSMutableArray alloc] init]; - _attributes = [[NSMutableDictionary alloc] init]; - } - return self; -} - -- (BOOL)hasBody { - return _contentType ? YES : NO; -} - -- (BOOL)hasByteRange { - return GCDWebServerIsValidByteRange(_byteRange); -} - -- (id)attributeForKey:(NSString*)key { - return [_attributes objectForKey:key]; -} - -- (BOOL)open:(NSError**)error { - return YES; -} - -- (BOOL)writeData:(NSData*)data error:(NSError**)error { - return YES; -} - -- (BOOL)close:(NSError**)error { - return YES; -} - -- (void)prepareForWriting { - _writer = self; - if ([GCDWebServerNormalizeHeaderValue([self.headers objectForKey:@"Content-Encoding"]) isEqualToString:@"gzip"]) { - GCDWebServerGZipDecoder* decoder = [[GCDWebServerGZipDecoder alloc] initWithRequest:self writer:_writer]; - [_decoders addObject:decoder]; - _writer = decoder; - } -} - -- (BOOL)performOpen:(NSError**)error { - GWS_DCHECK(_contentType); - GWS_DCHECK(_writer); - if (_opened) { - GWS_DNOT_REACHED(); - return NO; - } - _opened = YES; - return [_writer open:error]; -} - -- (BOOL)performWriteData:(NSData*)data error:(NSError**)error { - GWS_DCHECK(_opened); - return [_writer writeData:data error:error]; -} - -- (BOOL)performClose:(NSError**)error { - GWS_DCHECK(_opened); - return [_writer close:error]; -} - -- (void)setAttribute:(id)attribute forKey:(NSString*)key { - [_attributes setValue:attribute forKey:key]; -} - -- (NSString*)localAddressString { - return GCDWebServerStringFromSockAddr(_localAddressData.bytes, YES); -} - -- (NSString*)remoteAddressString { - return GCDWebServerStringFromSockAddr(_remoteAddressData.bytes, YES); -} - -- (NSString*)description { - NSMutableString* description = [NSMutableString stringWithFormat:@"%@ %@", _method, _path]; - for (NSString* argument in [[_query allKeys] sortedArrayUsingSelector:@selector(compare:)]) { - [description appendFormat:@"\n %@ = %@", argument, [_query objectForKey:argument]]; - } - [description appendString:@"\n"]; - for (NSString* header in [[_headers allKeys] sortedArrayUsingSelector:@selector(compare:)]) { - [description appendFormat:@"\n%@: %@", header, [_headers objectForKey:header]]; - } - return description; -} - -@end diff --git a/src/ios/GCDWebServer/Core/GCDWebServerResponse.h b/src/ios/GCDWebServer/Core/GCDWebServerResponse.h deleted file mode 100755 index 1e5e8c9..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerResponse.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerBodyReaderCompletionBlock is passed by GCDWebServer to the - * GCDWebServerBodyReader object when reading data from it asynchronously. - */ -typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* _Nullable error); - -/** - * This protocol is used by the GCDWebServerConnection to communicate with - * the GCDWebServerResponse and read the HTTP body data to send. - * - * Note that multiple GCDWebServerBodyReader objects can be chained together - * internally e.g. to automatically apply gzip encoding to the content before - * passing it on to the GCDWebServerResponse. - * - * @warning These methods can be called on any GCD thread. - */ -@protocol GCDWebServerBodyReader - -@required - -/** - * This method is called before any body data is sent. - * - * It should return YES on success or NO on failure and set the "error" argument - * which is guaranteed to be non-NULL. - */ -- (BOOL)open:(NSError**)error; - -/** - * This method is called whenever body data is sent. - * - * It should return a non-empty NSData if there is body data available, - * or an empty NSData there is no more body data, or nil on error and set - * the "error" argument which is guaranteed to be non-NULL. - */ -- (nullable NSData*)readData:(NSError**)error; - -/** - * This method is called after all body data has been sent. - */ -- (void)close; - -@optional - -/** - * If this method is implemented, it will be preferred over -readData:. - * - * It must call the passed block when data is available, passing a non-empty - * NSData if there is body data available, or an empty NSData there is no more - * body data, or nil on error and pass an NSError along. - */ -- (void)asyncReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block; - -@end - -/** - * The GCDWebServerResponse class is used to wrap a single HTTP response. - * It is instantiated by the handler of the GCDWebServer that handled the request. - * If a body is present, the methods from the GCDWebServerBodyReader protocol - * will be called by the GCDWebServerConnection to send it. - * - * The default implementation of the GCDWebServerBodyReader protocol - * on the class simply returns an empty body. - * - * @warning GCDWebServerResponse instances can be created and used on any GCD thread. - */ -@interface GCDWebServerResponse : NSObject - -/** - * Sets the content type for the body of the response. - * - * The default value is nil i.e. the response has no body. - * - * @warning This property must be set if a body is present. - */ -@property(nonatomic, copy, nullable) NSString* contentType; - -/** - * Sets the content length for the body of the response. If a body is present - * but this property is set to "NSUIntegerMax", this means the length of the body - * cannot be known ahead of time. Chunked transfer encoding will be - * automatically enabled by the GCDWebServerConnection to comply with HTTP/1.1 - * specifications. - * - * The default value is "NSUIntegerMax" i.e. the response has no body or its length - * is undefined. - */ -@property(nonatomic) NSUInteger contentLength; - -/** - * Sets the HTTP status code for the response. - * - * The default value is 200 i.e. "OK". - */ -@property(nonatomic) NSInteger statusCode; - -/** - * Sets the caching hint for the response using the "Cache-Control" header. - * This value is expressed in seconds. - * - * The default value is 0 i.e. "no-cache". - */ -@property(nonatomic) NSUInteger cacheControlMaxAge; - -/** - * Sets the last modified date for the response using the "Last-Modified" header. - * - * The default value is nil. - */ -@property(nonatomic, nullable) NSDate* lastModifiedDate; - -/** - * Sets the ETag for the response using the "ETag" header. - * - * The default value is nil. - */ -@property(nonatomic, copy, nullable) NSString* eTag; - -/** - * Enables gzip encoding for the response body. - * - * The default value is NO. - * - * @warning Enabling gzip encoding will remove any "Content-Length" header - * since the length of the body is not known anymore. The client will still - * be able to determine the body length when connection is closed per - * HTTP/1.1 specifications. - */ -@property(nonatomic, getter=isGZipContentEncodingEnabled) BOOL gzipContentEncodingEnabled; - -/** - * Creates an empty response. - */ -+ (instancetype)response; - -/** - * This method is the designated initializer for the class. - */ -- (instancetype)init; - -/** - * Sets an additional HTTP header on the response. - * Pass a nil value to remove an additional header. - * - * @warning Do not attempt to override the primary headers used - * by GCDWebServerResponse like "Content-Type", "ETag", etc... - */ -- (void)setValue:(nullable NSString*)value forAdditionalHeader:(NSString*)header; - -/** - * Convenience method that checks if the contentType property is defined. - */ -- (BOOL)hasBody; - -@end - -@interface GCDWebServerResponse (Extensions) - -/** - * Creates a empty response with a specific HTTP status code. - */ -+ (instancetype)responseWithStatusCode:(NSInteger)statusCode; - -/** - * Creates an HTTP redirect response to a new URL. - */ -+ (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent; - -/** - * Initializes an empty response with a specific HTTP status code. - */ -- (instancetype)initWithStatusCode:(NSInteger)statusCode; - -/** - * Initializes an HTTP redirect response to a new URL. - */ -- (instancetype)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Core/GCDWebServerResponse.m b/src/ios/GCDWebServer/Core/GCDWebServerResponse.m deleted file mode 100755 index 9153ff6..0000000 --- a/src/ios/GCDWebServer/Core/GCDWebServerResponse.m +++ /dev/null @@ -1,284 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import - -#import "GCDWebServerPrivate.h" - -#define kZlibErrorDomain @"ZlibErrorDomain" -#define kGZipInitialBufferSize (256 * 1024) - -@interface GCDWebServerBodyEncoder : NSObject -@end - -@interface GCDWebServerGZipEncoder : GCDWebServerBodyEncoder -@end - -@implementation GCDWebServerBodyEncoder { - GCDWebServerResponse* __unsafe_unretained _response; - id __unsafe_unretained _reader; -} - -- (instancetype)initWithResponse:(GCDWebServerResponse* _Nonnull)response reader:(id _Nonnull)reader { - if ((self = [super init])) { - _response = response; - _reader = reader; - } - return self; -} - -- (BOOL)open:(NSError**)error { - return [_reader open:error]; -} - -- (NSData*)readData:(NSError**)error { - return [_reader readData:error]; -} - -- (void)close { - [_reader close]; -} - -@end - -@implementation GCDWebServerGZipEncoder { - z_stream _stream; - BOOL _finished; -} - -- (instancetype)initWithResponse:(GCDWebServerResponse* _Nonnull)response reader:(id _Nonnull)reader { - if ((self = [super initWithResponse:response reader:reader])) { - response.contentLength = NSUIntegerMax; // Make sure "Content-Length" header is not set since we don't know it - [response setValue:@"gzip" forAdditionalHeader:@"Content-Encoding"]; - } - return self; -} - -- (BOOL)open:(NSError**)error { - int result = deflateInit2(&_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); - if (result != Z_OK) { - if (error) { - *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil]; - } - return NO; - } - if (![super open:error]) { - deflateEnd(&_stream); - return NO; - } - return YES; -} - -- (NSData*)readData:(NSError**)error { - NSMutableData* encodedData; - if (_finished) { - encodedData = [[NSMutableData alloc] init]; - } else { - encodedData = [[NSMutableData alloc] initWithLength:kGZipInitialBufferSize]; - if (encodedData == nil) { - GWS_DNOT_REACHED(); - return nil; - } - NSUInteger length = 0; - do { - NSData* data = [super readData:error]; - if (data == nil) { - return nil; - } - _stream.next_in = (Bytef*)data.bytes; - _stream.avail_in = (uInt)data.length; - while (1) { - NSUInteger maxLength = encodedData.length - length; - _stream.next_out = (Bytef*)((char*)encodedData.mutableBytes + length); - _stream.avail_out = (uInt)maxLength; - int result = deflate(&_stream, data.length ? Z_NO_FLUSH : Z_FINISH); - if (result == Z_STREAM_END) { - _finished = YES; - } else if (result != Z_OK) { - if (error) { - *error = [NSError errorWithDomain:kZlibErrorDomain code:result userInfo:nil]; - } - return nil; - } - length += maxLength - _stream.avail_out; - if (_stream.avail_out > 0) { - break; - } - encodedData.length = 2 * encodedData.length; // zlib has used all the output buffer so resize it and try again in case more data is available - } - GWS_DCHECK(_stream.avail_in == 0); - } while (length == 0); // Make sure we don't return an empty NSData if not in finished state - encodedData.length = length; - } - return encodedData; -} - -- (void)close { - deflateEnd(&_stream); - [super close]; -} - -@end - -@implementation GCDWebServerResponse { - BOOL _opened; - NSMutableArray* _encoders; - id __unsafe_unretained _reader; -} - -+ (instancetype)response { - return [[[self class] alloc] init]; -} - -- (instancetype)init { - if ((self = [super init])) { - _contentType = nil; - _contentLength = NSUIntegerMax; - _statusCode = kGCDWebServerHTTPStatusCode_OK; - _cacheControlMaxAge = 0; - _additionalHeaders = [[NSMutableDictionary alloc] init]; - _encoders = [[NSMutableArray alloc] init]; - } - return self; -} - -- (void)setValue:(NSString*)value forAdditionalHeader:(NSString*)header { - [_additionalHeaders setValue:value forKey:header]; -} - -- (BOOL)hasBody { - return _contentType ? YES : NO; -} - -- (BOOL)usesChunkedTransferEncoding { - return (_contentType != nil) && (_contentLength == NSUIntegerMax); -} - -- (BOOL)open:(NSError**)error { - return YES; -} - -- (NSData*)readData:(NSError**)error { - return [NSData data]; -} - -- (void)close { - ; -} - -- (void)prepareForReading { - _reader = self; - if (_gzipContentEncodingEnabled) { - GCDWebServerGZipEncoder* encoder = [[GCDWebServerGZipEncoder alloc] initWithResponse:self reader:_reader]; - [_encoders addObject:encoder]; - _reader = encoder; - } -} - -- (BOOL)performOpen:(NSError**)error { - GWS_DCHECK(_contentType); - GWS_DCHECK(_reader); - if (_opened) { - GWS_DNOT_REACHED(); - return NO; - } - _opened = YES; - return [_reader open:error]; -} - -- (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block { - GWS_DCHECK(_opened); - if ([_reader respondsToSelector:@selector(asyncReadDataWithCompletion:)]) { - [_reader asyncReadDataWithCompletion:[block copy]]; - } else { - NSError* error = nil; - NSData* data = [_reader readData:&error]; - block(data, error); - } -} - -- (void)performClose { - GWS_DCHECK(_opened); - [_reader close]; -} - -- (NSString*)description { - NSMutableString* description = [NSMutableString stringWithFormat:@"Status Code = %i", (int)_statusCode]; - if (_contentType) { - [description appendFormat:@"\nContent Type = %@", _contentType]; - } - if (_contentLength != NSUIntegerMax) { - [description appendFormat:@"\nContent Length = %lu", (unsigned long)_contentLength]; - } - [description appendFormat:@"\nCache Control Max Age = %lu", (unsigned long)_cacheControlMaxAge]; - if (_lastModifiedDate) { - [description appendFormat:@"\nLast Modified Date = %@", _lastModifiedDate]; - } - if (_eTag) { - [description appendFormat:@"\nETag = %@", _eTag]; - } - if (_additionalHeaders.count) { - [description appendString:@"\n"]; - for (NSString* header in [[_additionalHeaders allKeys] sortedArrayUsingSelector:@selector(compare:)]) { - [description appendFormat:@"\n%@: %@", header, [_additionalHeaders objectForKey:header]]; - } - } - return description; -} - -@end - -@implementation GCDWebServerResponse (Extensions) - -+ (instancetype)responseWithStatusCode:(NSInteger)statusCode { - return [[self alloc] initWithStatusCode:statusCode]; -} - -+ (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent { - return [[self alloc] initWithRedirect:location permanent:permanent]; -} - -- (instancetype)initWithStatusCode:(NSInteger)statusCode { - if ((self = [self init])) { - self.statusCode = statusCode; - } - return self; -} - -- (instancetype)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent { - if ((self = [self init])) { - self.statusCode = permanent ? kGCDWebServerHTTPStatusCode_MovedPermanently : kGCDWebServerHTTPStatusCode_TemporaryRedirect; - [self setValue:[location absoluteString] forAdditionalHeader:@"Location"]; - } - return self; -} - -@end diff --git a/src/ios/GCDWebServer/Requests/GCDWebServerDataRequest.h b/src/ios/GCDWebServer/Requests/GCDWebServerDataRequest.h deleted file mode 100755 index f21a4b7..0000000 --- a/src/ios/GCDWebServer/Requests/GCDWebServerDataRequest.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GCDWebServerRequest.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerDataRequest subclass of GCDWebServerRequest stores the body - * of the HTTP request in memory. - */ -@interface GCDWebServerDataRequest : GCDWebServerRequest - -/** - * Returns the data for the request body. - */ -@property(nonatomic, readonly) NSData* data; - -@end - -@interface GCDWebServerDataRequest (Extensions) - -/** - * Returns the data for the request body interpreted as text. If the content - * type of the body is not a text one, or if an error occurs, nil is returned. - * - * The text encoding used to interpret the data is extracted from the - * "Content-Type" header or defaults to UTF-8. - */ -@property(nonatomic, readonly, nullable) NSString* text; - -/** - * Returns the data for the request body interpreted as a JSON object. If the - * content type of the body is not JSON, or if an error occurs, nil is returned. - */ -@property(nonatomic, readonly, nullable) id jsonObject; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Requests/GCDWebServerDataRequest.m b/src/ios/GCDWebServer/Requests/GCDWebServerDataRequest.m deleted file mode 100755 index 3ea9bba..0000000 --- a/src/ios/GCDWebServer/Requests/GCDWebServerDataRequest.m +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import "GCDWebServerPrivate.h" - -@interface GCDWebServerDataRequest () -@property(nonatomic) NSMutableData* data; -@end - -@implementation GCDWebServerDataRequest { - NSString* _text; - id _jsonObject; -} - -- (BOOL)open:(NSError**)error { - if (self.contentLength != NSUIntegerMax) { - _data = [[NSMutableData alloc] initWithCapacity:self.contentLength]; - } else { - _data = [[NSMutableData alloc] init]; - } - if (_data == nil) { - if (error) { - *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed allocating memory" }]; - } - return NO; - } - return YES; -} - -- (BOOL)writeData:(NSData*)data error:(NSError**)error { - [_data appendData:data]; - return YES; -} - -- (BOOL)close:(NSError**)error { - return YES; -} - -- (NSString*)description { - NSMutableString* description = [NSMutableString stringWithString:[super description]]; - if (_data) { - [description appendString:@"\n\n"]; - [description appendString:GCDWebServerDescribeData(_data, (NSString*)self.contentType)]; - } - return description; -} - -@end - -@implementation GCDWebServerDataRequest (Extensions) - -- (NSString*)text { - if (_text == nil) { - if ([self.contentType hasPrefix:@"text/"]) { - NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); - _text = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)]; - } else { - GWS_DNOT_REACHED(); - } - } - return _text; -} - -- (id)jsonObject { - if (_jsonObject == nil) { - NSString* mimeType = GCDWebServerTruncateHeaderValue(self.contentType); - if ([mimeType isEqualToString:@"application/json"] || [mimeType isEqualToString:@"text/json"] || [mimeType isEqualToString:@"text/javascript"]) { - _jsonObject = [NSJSONSerialization JSONObjectWithData:_data options:0 error:NULL]; - } else { - GWS_DNOT_REACHED(); - } - } - return _jsonObject; -} - -@end diff --git a/src/ios/GCDWebServer/Requests/GCDWebServerFileRequest.h b/src/ios/GCDWebServer/Requests/GCDWebServerFileRequest.h deleted file mode 100755 index 8aceae4..0000000 --- a/src/ios/GCDWebServer/Requests/GCDWebServerFileRequest.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GCDWebServerRequest.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerFileRequest subclass of GCDWebServerRequest stores the body - * of the HTTP request to a file on disk. - */ -@interface GCDWebServerFileRequest : GCDWebServerRequest - -/** - * Returns the path to the temporary file containing the request body. - * - * @warning This temporary file will be automatically deleted when the - * GCDWebServerFileRequest is deallocated. If you want to preserve this file, - * you must move it to a different location beforehand. - */ -@property(nonatomic, readonly) NSString* temporaryPath; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Requests/GCDWebServerFileRequest.m b/src/ios/GCDWebServer/Requests/GCDWebServerFileRequest.m deleted file mode 100755 index 8a47fcc..0000000 --- a/src/ios/GCDWebServer/Requests/GCDWebServerFileRequest.m +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import "GCDWebServerPrivate.h" - -@implementation GCDWebServerFileRequest { - int _file; -} - -- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { - if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) { - _temporaryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; - } - return self; -} - -- (void)dealloc { - unlink([_temporaryPath fileSystemRepresentation]); -} - -- (BOOL)open:(NSError**)error { - _file = open([_temporaryPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (_file <= 0) { - if (error) { - *error = GCDWebServerMakePosixError(errno); - } - return NO; - } - return YES; -} - -- (BOOL)writeData:(NSData*)data error:(NSError**)error { - if (write(_file, data.bytes, data.length) != (ssize_t)data.length) { - if (error) { - *error = GCDWebServerMakePosixError(errno); - } - return NO; - } - return YES; -} - -- (BOOL)close:(NSError**)error { - if (close(_file) < 0) { - if (error) { - *error = GCDWebServerMakePosixError(errno); - } - return NO; - } -#ifdef __GCDWEBSERVER_ENABLE_TESTING__ - NSString* creationDateHeader = [self.headers objectForKey:@"X-GCDWebServer-CreationDate"]; - if (creationDateHeader) { - NSDate* date = GCDWebServerParseISO8601(creationDateHeader); - if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileCreationDate : date} ofItemAtPath:_temporaryPath error:error]) { - return NO; - } - } - NSString* modifiedDateHeader = [self.headers objectForKey:@"X-GCDWebServer-ModifiedDate"]; - if (modifiedDateHeader) { - NSDate* date = GCDWebServerParseRFC822(modifiedDateHeader); - if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileModificationDate : date} ofItemAtPath:_temporaryPath error:error]) { - return NO; - } - } -#endif - return YES; -} - -- (NSString*)description { - NSMutableString* description = [NSMutableString stringWithString:[super description]]; - [description appendFormat:@"\n\n{%@}", _temporaryPath]; - return description; -} - -@end diff --git a/src/ios/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h b/src/ios/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h deleted file mode 100755 index 93ac179..0000000 --- a/src/ios/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GCDWebServerRequest.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerMultiPart class is an abstract class that wraps the content - * of a part. - */ -@interface GCDWebServerMultiPart : NSObject - -/** - * Returns the control name retrieved from the part headers. - */ -@property(nonatomic, readonly) NSString* controlName; - -/** - * Returns the content type retrieved from the part headers or "text/plain" - * if not available (per HTTP specifications). - */ -@property(nonatomic, readonly) NSString* contentType; - -/** - * Returns the MIME type component of the content type for the part. - */ -@property(nonatomic, readonly) NSString* mimeType; - -@end - -/** - * The GCDWebServerMultiPartArgument subclass of GCDWebServerMultiPart wraps - * the content of a part as data in memory. - */ -@interface GCDWebServerMultiPartArgument : GCDWebServerMultiPart - -/** - * Returns the data for the part. - */ -@property(nonatomic, readonly) NSData* data; - -/** - * Returns the data for the part interpreted as text. If the content - * type of the part is not a text one, or if an error occurs, nil is returned. - * - * The text encoding used to interpret the data is extracted from the - * "Content-Type" header or defaults to UTF-8. - */ -@property(nonatomic, readonly, nullable) NSString* string; - -@end - -/** - * The GCDWebServerMultiPartFile subclass of GCDWebServerMultiPart wraps - * the content of a part as a file on disk. - */ -@interface GCDWebServerMultiPartFile : GCDWebServerMultiPart - -/** - * Returns the file name retrieved from the part headers. - */ -@property(nonatomic, readonly) NSString* fileName; - -/** - * Returns the path to the temporary file containing the part data. - * - * @warning This temporary file will be automatically deleted when the - * GCDWebServerMultiPartFile is deallocated. If you want to preserve this file, - * you must move it to a different location beforehand. - */ -@property(nonatomic, readonly) NSString* temporaryPath; - -@end - -/** - * The GCDWebServerMultiPartFormRequest subclass of GCDWebServerRequest - * parses the body of the HTTP request as a multipart encoded form. - */ -@interface GCDWebServerMultiPartFormRequest : GCDWebServerRequest - -/** - * Returns the argument parts from the multipart encoded form as - * name / GCDWebServerMultiPartArgument pairs. - */ -@property(nonatomic, readonly) NSArray* arguments; - -/** - * Returns the files parts from the multipart encoded form as - * name / GCDWebServerMultiPartFile pairs. - */ -@property(nonatomic, readonly) NSArray* files; - -/** - * Returns the MIME type for multipart encoded forms - * i.e. "multipart/form-data". - */ -+ (NSString*)mimeType; - -/** - * Returns the first argument for a given control name or nil if not found. - */ -- (nullable GCDWebServerMultiPartArgument*)firstArgumentForControlName:(NSString*)name; - -/** - * Returns the first file for a given control name or nil if not found. - */ -- (nullable GCDWebServerMultiPartFile*)firstFileForControlName:(NSString*)name; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m b/src/ios/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m deleted file mode 100755 index 4e6bf09..0000000 --- a/src/ios/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m +++ /dev/null @@ -1,405 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import "GCDWebServerPrivate.h" - -#define kMultiPartBufferSize (256 * 1024) - -typedef enum { - kParserState_Undefined = 0, - kParserState_Start, - kParserState_Headers, - kParserState_Content, - kParserState_End -} ParserState; - -@interface GCDWebServerMIMEStreamParser : NSObject -@end - -static NSData* _newlineData = nil; -static NSData* _newlinesData = nil; -static NSData* _dashNewlineData = nil; - -@implementation GCDWebServerMultiPart - -- (instancetype)initWithControlName:(NSString* _Nonnull)name contentType:(NSString* _Nonnull)type { - if ((self = [super init])) { - _controlName = [name copy]; - _contentType = [type copy]; - _mimeType = (NSString*)GCDWebServerTruncateHeaderValue(_contentType); - } - return self; -} - -@end - -@implementation GCDWebServerMultiPartArgument - -- (instancetype)initWithControlName:(NSString* _Nonnull)name contentType:(NSString* _Nonnull)type data:(NSData* _Nonnull)data { - if ((self = [super initWithControlName:name contentType:type])) { - _data = data; - - if ([self.contentType hasPrefix:@"text/"]) { - NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); - _string = [[NSString alloc] initWithData:_data encoding:GCDWebServerStringEncodingFromCharset(charset)]; - } - } - return self; -} - -- (NSString*)description { - return [NSString stringWithFormat:@"<%@ | '%@' | %lu bytes>", [self class], self.mimeType, (unsigned long)_data.length]; -} - -@end - -@implementation GCDWebServerMultiPartFile - -- (instancetype)initWithControlName:(NSString* _Nonnull)name contentType:(NSString* _Nonnull)type fileName:(NSString* _Nonnull)fileName temporaryPath:(NSString* _Nonnull)temporaryPath { - if ((self = [super initWithControlName:name contentType:type])) { - _fileName = [fileName copy]; - _temporaryPath = [temporaryPath copy]; - } - return self; -} - -- (void)dealloc { - unlink([_temporaryPath fileSystemRepresentation]); -} - -- (NSString*)description { - return [NSString stringWithFormat:@"<%@ | '%@' | '%@>'", [self class], self.mimeType, _fileName]; -} - -@end - -@implementation GCDWebServerMIMEStreamParser { - NSData* _boundary; - NSString* _defaultcontrolName; - ParserState _state; - NSMutableData* _data; - NSMutableArray* _arguments; - NSMutableArray* _files; - - NSString* _controlName; - NSString* _fileName; - NSString* _contentType; - NSString* _tmpPath; - int _tmpFile; - GCDWebServerMIMEStreamParser* _subParser; -} - -+ (void)initialize { - if (_newlineData == nil) { - _newlineData = [[NSData alloc] initWithBytes:"\r\n" length:2]; - GWS_DCHECK(_newlineData); - } - if (_newlinesData == nil) { - _newlinesData = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4]; - GWS_DCHECK(_newlinesData); - } - if (_dashNewlineData == nil) { - _dashNewlineData = [[NSData alloc] initWithBytes:"--\r\n" length:4]; - GWS_DCHECK(_dashNewlineData); - } -} - -- (instancetype)initWithBoundary:(NSString* _Nonnull)boundary defaultControlName:(NSString* _Nullable)name arguments:(NSMutableArray* _Nonnull)arguments files:(NSMutableArray* _Nonnull)files { - NSData* data = boundary.length ? [[NSString stringWithFormat:@"--%@", boundary] dataUsingEncoding:NSASCIIStringEncoding] : nil; - if (data == nil) { - GWS_DNOT_REACHED(); - return nil; - } - if ((self = [super init])) { - _boundary = data; - _defaultcontrolName = name; - _arguments = arguments; - _files = files; - _data = [[NSMutableData alloc] initWithCapacity:kMultiPartBufferSize]; - _state = kParserState_Start; - } - return self; -} - -- (void)dealloc { - if (_tmpFile > 0) { - close(_tmpFile); - unlink([_tmpPath fileSystemRepresentation]); - } -} - -// http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 -- (BOOL)_parseData { - BOOL success = YES; - - if (_state == kParserState_Headers) { - NSRange range = [_data rangeOfData:_newlinesData options:0 range:NSMakeRange(0, _data.length)]; - if (range.location != NSNotFound) { - _controlName = nil; - _fileName = nil; - _contentType = nil; - _tmpPath = nil; - _subParser = nil; - NSString* headers = [[NSString alloc] initWithData:[_data subdataWithRange:NSMakeRange(0, range.location)] encoding:NSUTF8StringEncoding]; - if (headers) { - for (NSString* header in [headers componentsSeparatedByString:@"\r\n"]) { - NSRange subRange = [header rangeOfString:@":"]; - if (subRange.location != NSNotFound) { - NSString* name = [header substringToIndex:subRange.location]; - NSString* value = [[header substringFromIndex:(subRange.location + subRange.length)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - if ([name caseInsensitiveCompare:@"Content-Type"] == NSOrderedSame) { - _contentType = GCDWebServerNormalizeHeaderValue(value); - } else if ([name caseInsensitiveCompare:@"Content-Disposition"] == NSOrderedSame) { - NSString* contentDisposition = GCDWebServerNormalizeHeaderValue(value); - if ([GCDWebServerTruncateHeaderValue(contentDisposition) isEqualToString:@"form-data"]) { - _controlName = GCDWebServerExtractHeaderValueParameter(contentDisposition, @"name"); - _fileName = GCDWebServerExtractHeaderValueParameter(contentDisposition, @"filename"); - } else if ([GCDWebServerTruncateHeaderValue(contentDisposition) isEqualToString:@"file"]) { - _controlName = _defaultcontrolName; - _fileName = GCDWebServerExtractHeaderValueParameter(contentDisposition, @"filename"); - } - } - } else { - GWS_DNOT_REACHED(); - } - } - if (_contentType == nil) { - _contentType = @"text/plain"; - } - } else { - GWS_LOG_ERROR(@"Failed decoding headers in part of 'multipart/form-data'"); - GWS_DNOT_REACHED(); - } - if (_controlName) { - if ([GCDWebServerTruncateHeaderValue(_contentType) isEqualToString:@"multipart/mixed"]) { - NSString* boundary = GCDWebServerExtractHeaderValueParameter(_contentType, @"boundary"); - _subParser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:_controlName arguments:_arguments files:_files]; - if (_subParser == nil) { - GWS_DNOT_REACHED(); - success = NO; - } - } else if (_fileName) { - NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; - _tmpFile = open([path fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (_tmpFile > 0) { - _tmpPath = [path copy]; - } else { - GWS_DNOT_REACHED(); - success = NO; - } - } - } else { - GWS_DNOT_REACHED(); - success = NO; - } - - [_data replaceBytesInRange:NSMakeRange(0, range.location + range.length) withBytes:NULL length:0]; - _state = kParserState_Content; - } - } - - if ((_state == kParserState_Start) || (_state == kParserState_Content)) { - NSRange range = [_data rangeOfData:_boundary options:0 range:NSMakeRange(0, _data.length)]; - if (range.location != NSNotFound) { - NSRange subRange = NSMakeRange(range.location + range.length, _data.length - range.location - range.length); - NSRange subRange1 = [_data rangeOfData:_newlineData options:NSDataSearchAnchored range:subRange]; - NSRange subRange2 = [_data rangeOfData:_dashNewlineData options:NSDataSearchAnchored range:subRange]; - if ((subRange1.location != NSNotFound) || (subRange2.location != NSNotFound)) { - if (_state == kParserState_Content) { - const void* dataBytes = _data.bytes; - NSUInteger dataLength = range.location - 2; - if (_subParser) { - if (![_subParser appendBytes:dataBytes length:(dataLength + 2)] || ![_subParser isAtEnd]) { - GWS_DNOT_REACHED(); - success = NO; - } - _subParser = nil; - } else if (_tmpPath) { - ssize_t result = write(_tmpFile, dataBytes, dataLength); - if (result == (ssize_t)dataLength) { - if (close(_tmpFile) == 0) { - _tmpFile = 0; - GCDWebServerMultiPartFile* file = [[GCDWebServerMultiPartFile alloc] initWithControlName:_controlName contentType:_contentType fileName:_fileName temporaryPath:_tmpPath]; - [_files addObject:file]; - } else { - GWS_DNOT_REACHED(); - success = NO; - } - } else { - GWS_DNOT_REACHED(); - success = NO; - } - _tmpPath = nil; - } else { - NSData* data = [[NSData alloc] initWithBytes:(void*)dataBytes length:dataLength]; - GCDWebServerMultiPartArgument* argument = [[GCDWebServerMultiPartArgument alloc] initWithControlName:_controlName contentType:_contentType data:data]; - [_arguments addObject:argument]; - } - } - - if (subRange1.location != NSNotFound) { - [_data replaceBytesInRange:NSMakeRange(0, subRange1.location + subRange1.length) withBytes:NULL length:0]; - _state = kParserState_Headers; - success = [self _parseData]; - } else { - _state = kParserState_End; - } - } - } else { - NSUInteger margin = 2 * _boundary.length; - if (_data.length > margin) { - NSUInteger length = _data.length - margin; - if (_subParser) { - if ([_subParser appendBytes:_data.bytes length:length]) { - [_data replaceBytesInRange:NSMakeRange(0, length) withBytes:NULL length:0]; - } else { - GWS_DNOT_REACHED(); - success = NO; - } - } else if (_tmpPath) { - ssize_t result = write(_tmpFile, _data.bytes, length); - if (result == (ssize_t)length) { - [_data replaceBytesInRange:NSMakeRange(0, length) withBytes:NULL length:0]; - } else { - GWS_DNOT_REACHED(); - success = NO; - } - } - } - } - } - - return success; -} - -- (BOOL)appendBytes:(const void*)bytes length:(NSUInteger)length { - [_data appendBytes:bytes length:length]; - return [self _parseData]; -} - -- (BOOL)isAtEnd { - return (_state == kParserState_End); -} - -@end - -@interface GCDWebServerMultiPartFormRequest () -@property(nonatomic) NSMutableArray* arguments; -@property(nonatomic) NSMutableArray* files; -@end - -@implementation GCDWebServerMultiPartFormRequest { - GCDWebServerMIMEStreamParser* _parser; -} - -+ (NSString*)mimeType { - return @"multipart/form-data"; -} - -- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { - if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) { - _arguments = [[NSMutableArray alloc] init]; - _files = [[NSMutableArray alloc] init]; - } - return self; -} - -- (BOOL)open:(NSError**)error { - NSString* boundary = GCDWebServerExtractHeaderValueParameter(self.contentType, @"boundary"); - _parser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:nil arguments:_arguments files:_files]; - if (_parser == nil) { - if (error) { - *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed starting to parse multipart form data" }]; - } - return NO; - } - return YES; -} - -- (BOOL)writeData:(NSData*)data error:(NSError**)error { - if (![_parser appendBytes:data.bytes length:data.length]) { - if (error) { - *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed continuing to parse multipart form data" }]; - } - return NO; - } - return YES; -} - -- (BOOL)close:(NSError**)error { - BOOL atEnd = [_parser isAtEnd]; - _parser = nil; - if (!atEnd) { - if (error) { - *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed finishing to parse multipart form data" }]; - } - return NO; - } - return YES; -} - -- (GCDWebServerMultiPartArgument*)firstArgumentForControlName:(NSString*)name { - for (GCDWebServerMultiPartArgument* argument in _arguments) { - if ([argument.controlName isEqualToString:name]) { - return argument; - } - } - return nil; -} - -- (GCDWebServerMultiPartFile*)firstFileForControlName:(NSString*)name { - for (GCDWebServerMultiPartFile* file in _files) { - if ([file.controlName isEqualToString:name]) { - return file; - } - } - return nil; -} - -- (NSString*)description { - NSMutableString* description = [NSMutableString stringWithString:[super description]]; - if (_arguments.count) { - [description appendString:@"\n"]; - for (GCDWebServerMultiPartArgument* argument in _arguments) { - [description appendFormat:@"\n%@ (%@)\n", argument.controlName, argument.contentType]; - [description appendString:GCDWebServerDescribeData(argument.data, argument.contentType)]; - } - } - if (_files.count) { - [description appendString:@"\n"]; - for (GCDWebServerMultiPartFile* file in _files) { - [description appendFormat:@"\n%@ (%@): %@\n{%@}", file.controlName, file.contentType, file.fileName, file.temporaryPath]; - } - } - return description; -} - -@end diff --git a/src/ios/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h b/src/ios/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h deleted file mode 100755 index fcf177e..0000000 --- a/src/ios/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GCDWebServerDataRequest.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerURLEncodedFormRequest subclass of GCDWebServerRequest - * parses the body of the HTTP request as a URL encoded form using - * GCDWebServerParseURLEncodedForm(). - */ -@interface GCDWebServerURLEncodedFormRequest : GCDWebServerDataRequest - -/** - * Returns the unescaped control names and values for the URL encoded form. - * - * The text encoding used to interpret the data is extracted from the - * "Content-Type" header or defaults to UTF-8. - */ -@property(nonatomic, readonly) NSDictionary* arguments; - -/** - * Returns the MIME type for URL encoded forms - * i.e. "application/x-www-form-urlencoded". - */ -+ (NSString*)mimeType; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m b/src/ios/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m deleted file mode 100755 index 7e0137f..0000000 --- a/src/ios/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import "GCDWebServerPrivate.h" - -@implementation GCDWebServerURLEncodedFormRequest - -+ (NSString*)mimeType { - return @"application/x-www-form-urlencoded"; -} - -- (BOOL)close:(NSError**)error { - if (![super close:error]) { - return NO; - } - - NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); - NSString* string = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)]; - _arguments = GCDWebServerParseURLEncodedForm(string); - return YES; -} - -- (NSString*)description { - NSMutableString* description = [NSMutableString stringWithString:[super description]]; - [description appendString:@"\n"]; - for (NSString* argument in [[_arguments allKeys] sortedArrayUsingSelector:@selector(compare:)]) { - [description appendFormat:@"\n%@ = %@", argument, [_arguments objectForKey:argument]]; - } - return description; -} - -@end diff --git a/src/ios/GCDWebServer/Responses/GCDWebServerDataResponse.h b/src/ios/GCDWebServer/Responses/GCDWebServerDataResponse.h deleted file mode 100755 index 783f596..0000000 --- a/src/ios/GCDWebServer/Responses/GCDWebServerDataResponse.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GCDWebServerResponse.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerDataResponse subclass of GCDWebServerResponse reads the body - * of the HTTP response from memory. - */ -@interface GCDWebServerDataResponse : GCDWebServerResponse -@property(nonatomic, copy) NSString* contentType; // Redeclare as non-null - -/** - * Creates a response with data in memory and a given content type. - */ -+ (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type; - -/** - * This method is the designated initializer for the class. - */ -- (instancetype)initWithData:(NSData*)data contentType:(NSString*)type; - -@end - -@interface GCDWebServerDataResponse (Extensions) - -/** - * Creates a data response from text encoded using UTF-8. - */ -+ (nullable instancetype)responseWithText:(NSString*)text; - -/** - * Creates a data response from HTML encoded using UTF-8. - */ -+ (nullable instancetype)responseWithHTML:(NSString*)html; - -/** - * Creates a data response from an HTML template encoded using UTF-8. - * See -initWithHTMLTemplate:variables: for details. - */ -+ (nullable instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; - -/** - * Creates a data response from a serialized JSON object and the default - * "application/json" content type. - */ -+ (nullable instancetype)responseWithJSONObject:(id)object; - -/** - * Creates a data response from a serialized JSON object and a custom - * content type. - */ -+ (nullable instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type; - -/** - * Initializes a data response from text encoded using UTF-8. - */ -- (nullable instancetype)initWithText:(NSString*)text; - -/** - * Initializes a data response from HTML encoded using UTF-8. - */ -- (nullable instancetype)initWithHTML:(NSString*)html; - -/** - * Initializes a data response from an HTML template encoded using UTF-8. - * - * All occurences of "%variable%" within the HTML template are replaced with - * their corresponding values. - */ -- (nullable instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; - -/** - * Initializes a data response from a serialized JSON object and the default - * "application/json" content type. - */ -- (nullable instancetype)initWithJSONObject:(id)object; - -/** - * Initializes a data response from a serialized JSON object and a custom - * content type. - */ -- (nullable instancetype)initWithJSONObject:(id)object contentType:(NSString*)type; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Responses/GCDWebServerDataResponse.m b/src/ios/GCDWebServer/Responses/GCDWebServerDataResponse.m deleted file mode 100755 index b496847..0000000 --- a/src/ios/GCDWebServer/Responses/GCDWebServerDataResponse.m +++ /dev/null @@ -1,136 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import "GCDWebServerPrivate.h" - -@implementation GCDWebServerDataResponse { - NSData* _data; - BOOL _done; -} - -@dynamic contentType; - -+ (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type { - return [[[self class] alloc] initWithData:data contentType:type]; -} - -- (instancetype)initWithData:(NSData*)data contentType:(NSString*)type { - if ((self = [super init])) { - _data = data; - - self.contentType = type; - self.contentLength = data.length; - } - return self; -} - -- (NSData*)readData:(NSError**)error { - NSData* data; - if (_done) { - data = [NSData data]; - } else { - data = _data; - _done = YES; - } - return data; -} - -- (NSString*)description { - NSMutableString* description = [NSMutableString stringWithString:[super description]]; - [description appendString:@"\n\n"]; - [description appendString:GCDWebServerDescribeData(_data, self.contentType)]; - return description; -} - -@end - -@implementation GCDWebServerDataResponse (Extensions) - -+ (instancetype)responseWithText:(NSString*)text { - return [[self alloc] initWithText:text]; -} - -+ (instancetype)responseWithHTML:(NSString*)html { - return [[self alloc] initWithHTML:html]; -} - -+ (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables { - return [[self alloc] initWithHTMLTemplate:path variables:variables]; -} - -+ (instancetype)responseWithJSONObject:(id)object { - return [[self alloc] initWithJSONObject:object]; -} - -+ (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type { - return [[self alloc] initWithJSONObject:object contentType:type]; -} - -- (instancetype)initWithText:(NSString*)text { - NSData* data = [text dataUsingEncoding:NSUTF8StringEncoding]; - if (data == nil) { - GWS_DNOT_REACHED(); - return nil; - } - return [self initWithData:data contentType:@"text/plain; charset=utf-8"]; -} - -- (instancetype)initWithHTML:(NSString*)html { - NSData* data = [html dataUsingEncoding:NSUTF8StringEncoding]; - if (data == nil) { - GWS_DNOT_REACHED(); - return nil; - } - return [self initWithData:data contentType:@"text/html; charset=utf-8"]; -} - -- (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables { - NSMutableString* html = [[NSMutableString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; - [variables enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) { - [html replaceOccurrencesOfString:[NSString stringWithFormat:@"%%%@%%", key] withString:value options:0 range:NSMakeRange(0, html.length)]; - }]; - return [self initWithHTML:html]; -} - -- (instancetype)initWithJSONObject:(id)object { - return [self initWithJSONObject:object contentType:@"application/json"]; -} - -- (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type { - NSData* data = [NSJSONSerialization dataWithJSONObject:object options:0 error:NULL]; - if (data == nil) { - GWS_DNOT_REACHED(); - return nil; - } - return [self initWithData:data contentType:type]; -} - -@end diff --git a/src/ios/GCDWebServer/Responses/GCDWebServerErrorResponse.h b/src/ios/GCDWebServer/Responses/GCDWebServerErrorResponse.h deleted file mode 100755 index 92c834c..0000000 --- a/src/ios/GCDWebServer/Responses/GCDWebServerErrorResponse.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GCDWebServerDataResponse.h" -#import "GCDWebServerHTTPStatusCodes.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerDataResponse subclass of GCDWebServerDataResponse generates - * an HTML body from an HTTP status code and an error message. - */ -@interface GCDWebServerErrorResponse : GCDWebServerDataResponse - -/** - * Creates a client error response with the corresponding HTTP status code. - */ -+ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3); - -/** - * Creates a server error response with the corresponding HTTP status code. - */ -+ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3); - -/** - * Creates a client error response with the corresponding HTTP status code - * and an underlying NSError. - */ -+ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(nullable NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3, 4); - -/** - * Creates a server error response with the corresponding HTTP status code - * and an underlying NSError. - */ -+ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(nullable NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3, 4); - -/** - * Initializes a client error response with the corresponding HTTP status code. - */ -- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3); - -/** - * Initializes a server error response with the corresponding HTTP status code. - */ -- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3); - -/** - * Initializes a client error response with the corresponding HTTP status code - * and an underlying NSError. - */ -- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(nullable NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3, 4); - -/** - * Initializes a server error response with the corresponding HTTP status code - * and an underlying NSError. - */ -- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(nullable NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3, 4); - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Responses/GCDWebServerErrorResponse.m b/src/ios/GCDWebServer/Responses/GCDWebServerErrorResponse.m deleted file mode 100755 index f1cd202..0000000 --- a/src/ios/GCDWebServer/Responses/GCDWebServerErrorResponse.m +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import "GCDWebServerPrivate.h" - -@implementation GCDWebServerErrorResponse - -+ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { - GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); - va_list arguments; - va_start(arguments, format); - GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; - va_end(arguments); - return response; -} - -+ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { - GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); - va_list arguments; - va_start(arguments, format); - GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; - va_end(arguments); - return response; -} - -+ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { - GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); - va_list arguments; - va_start(arguments, format); - GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; - va_end(arguments); - return response; -} - -+ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { - GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); - va_list arguments; - va_start(arguments, format); - GCDWebServerErrorResponse* response = [[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; - va_end(arguments); - return response; -} - -static inline NSString* _EscapeHTMLString(NSString* string) { - return [string stringByReplacingOccurrencesOfString:@"\"" withString:@"""]; -} - -- (instancetype)initWithStatusCode:(NSInteger)statusCode underlyingError:(NSError*)underlyingError messageFormat:(NSString*)format arguments:(va_list)arguments { - NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments]; - NSString* title = [NSString stringWithFormat:@"HTTP Error %i", (int)statusCode]; - NSString* error = underlyingError ? [NSString stringWithFormat:@"[%@] %@ (%li)", underlyingError.domain, _EscapeHTMLString(underlyingError.localizedDescription), (long)underlyingError.code] : @""; - NSString* html = [NSString stringWithFormat:@"%@

%@: %@

%@

", - title, title, _EscapeHTMLString(message), error]; - if ((self = [self initWithHTML:html])) { - self.statusCode = statusCode; - } - return self; -} - -- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { - GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); - va_list arguments; - va_start(arguments, format); - self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; - va_end(arguments); - return self; -} - -- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { - GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); - va_list arguments; - va_start(arguments, format); - self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]; - va_end(arguments); - return self; -} - -- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { - GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500)); - va_list arguments; - va_start(arguments, format); - self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; - va_end(arguments); - return self; -} - -- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... { - GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600)); - va_list arguments; - va_start(arguments, format); - self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]; - va_end(arguments); - return self; -} - -@end diff --git a/src/ios/GCDWebServer/Responses/GCDWebServerFileResponse.h b/src/ios/GCDWebServer/Responses/GCDWebServerFileResponse.h deleted file mode 100755 index 9403835..0000000 --- a/src/ios/GCDWebServer/Responses/GCDWebServerFileResponse.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GCDWebServerResponse.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerFileResponse subclass of GCDWebServerResponse reads the body - * of the HTTP response from a file on disk. - * - * It will automatically set the contentType, lastModifiedDate and eTag - * properties of the GCDWebServerResponse according to the file extension and - * metadata. - */ -@interface GCDWebServerFileResponse : GCDWebServerResponse -@property(nonatomic, copy) NSString* contentType; // Redeclare as non-null -@property(nonatomic) NSDate* lastModifiedDate; // Redeclare as non-null -@property(nonatomic, copy) NSString* eTag; // Redeclare as non-null - -/** - * Creates a response with the contents of a file. - */ -+ (nullable instancetype)responseWithFile:(NSString*)path; - -/** - * Creates a response like +responseWithFile: and sets the "Content-Disposition" - * HTTP header for a download if the "attachment" argument is YES. - */ -+ (nullable instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment; - -/** - * Creates a response like +responseWithFile: but restricts the file contents - * to a specific byte range. - * - * See -initWithFile:byteRange: for details. - */ -+ (nullable instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range; - -/** - * Creates a response like +responseWithFile:byteRange: and sets the - * "Content-Disposition" HTTP header for a download if the "attachment" - * argument is YES. - */ -+ (nullable instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; - -/** - * Initializes a response with the contents of a file. - */ -- (nullable instancetype)initWithFile:(NSString*)path; - -/** - * Initializes a response like +responseWithFile: and sets the - * "Content-Disposition" HTTP header for a download if the "attachment" - * argument is YES. - */ -- (nullable instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment; - -/** - * Initializes a response like -initWithFile: but restricts the file contents - * to a specific byte range. This range should be set to (NSUIntegerMax, 0) for - * the full file, (offset, length) if expressed from the beginning of the file, - * or (NSUIntegerMax, length) if expressed from the end of the file. The "offset" - * and "length" values will be automatically adjusted to be compatible with the - * actual size of the file. - * - * This argument would typically be set to the value of the byteRange property - * of the current GCDWebServerRequest. - */ -- (nullable instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range; - -/** - * This method is the designated initializer for the class. - * - * If MIME type overrides are specified, they allow to customize the built-in - * mapping from extensions to MIME types. Keys of the dictionary must be lowercased - * file extensions without the period, and the values must be the corresponding - * MIME types. - */ -- (nullable instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(nullable NSDictionary*)overrides; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Responses/GCDWebServerFileResponse.m b/src/ios/GCDWebServer/Responses/GCDWebServerFileResponse.m deleted file mode 100755 index bd07518..0000000 --- a/src/ios/GCDWebServer/Responses/GCDWebServerFileResponse.m +++ /dev/null @@ -1,185 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import - -#import "GCDWebServerPrivate.h" - -#define kFileReadBufferSize (32 * 1024) - -@implementation GCDWebServerFileResponse { - NSString* _path; - NSUInteger _offset; - NSUInteger _size; - int _file; -} - -@dynamic contentType, lastModifiedDate, eTag; - -+ (instancetype)responseWithFile:(NSString*)path { - return [[[self class] alloc] initWithFile:path]; -} - -+ (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment { - return [[[self class] alloc] initWithFile:path isAttachment:attachment]; -} - -+ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range { - return [[[self class] alloc] initWithFile:path byteRange:range]; -} - -+ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment { - return [[[self class] alloc] initWithFile:path byteRange:range isAttachment:attachment mimeTypeOverrides:nil]; -} - -- (instancetype)initWithFile:(NSString*)path { - return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:NO mimeTypeOverrides:nil]; -} - -- (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment { - return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:attachment mimeTypeOverrides:nil]; -} - -- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range { - return [self initWithFile:path byteRange:range isAttachment:NO mimeTypeOverrides:nil]; -} - -static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) { - return [NSDate dateWithTimeIntervalSince1970:((NSTimeInterval)t->tv_sec + (NSTimeInterval)t->tv_nsec / 1000000000.0)]; -} - -- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(NSDictionary*)overrides { - struct stat info; - if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) { - GWS_DNOT_REACHED(); - return nil; - } -#ifndef __LP64__ - if (info.st_size >= (off_t)4294967295) { // In 32 bit mode, we can't handle files greater than 4 GiBs (don't use "NSUIntegerMax" here to avoid potential unsigned to signed conversion issues) - GWS_DNOT_REACHED(); - return nil; - } -#endif - NSUInteger fileSize = (NSUInteger)info.st_size; - - BOOL hasByteRange = GCDWebServerIsValidByteRange(range); - if (hasByteRange) { - if (range.location != NSUIntegerMax) { - range.location = MIN(range.location, fileSize); - range.length = MIN(range.length, fileSize - range.location); - } else { - range.length = MIN(range.length, fileSize); - range.location = fileSize - range.length; - } - if (range.length == 0) { - return nil; // TODO: Return 416 status code and "Content-Range: bytes */{file length}" header - } - } else { - range.location = 0; - range.length = fileSize; - } - - if ((self = [super init])) { - _path = [path copy]; - _offset = range.location; - _size = range.length; - if (hasByteRange) { - [self setStatusCode:kGCDWebServerHTTPStatusCode_PartialContent]; - [self setValue:[NSString stringWithFormat:@"bytes %lu-%lu/%lu", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), (unsigned long)fileSize] forAdditionalHeader:@"Content-Range"]; - GWS_LOG_DEBUG(@"Using content bytes range [%lu-%lu] for file \"%@\"", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), path); - } - - if (attachment) { - NSString* fileName = [path lastPathComponent]; - NSData* data = [[fileName stringByReplacingOccurrencesOfString:@"\"" withString:@""] dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:YES]; - NSString* lossyFileName = data ? [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding] : nil; - if (lossyFileName) { - NSString* value = [NSString stringWithFormat:@"attachment; filename=\"%@\"; filename*=UTF-8''%@", lossyFileName, GCDWebServerEscapeURLString(fileName)]; - [self setValue:value forAdditionalHeader:@"Content-Disposition"]; - } else { - GWS_DNOT_REACHED(); - } - } - - self.contentType = GCDWebServerGetMimeTypeForExtension([_path pathExtension], overrides); - self.contentLength = _size; - self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec); - self.eTag = [NSString stringWithFormat:@"%llu/%li/%li", info.st_ino, info.st_mtimespec.tv_sec, info.st_mtimespec.tv_nsec]; - } - return self; -} - -- (BOOL)open:(NSError**)error { - _file = open([_path fileSystemRepresentation], O_NOFOLLOW | O_RDONLY); - if (_file <= 0) { - if (error) { - *error = GCDWebServerMakePosixError(errno); - } - return NO; - } - if (lseek(_file, _offset, SEEK_SET) != (off_t)_offset) { - if (error) { - *error = GCDWebServerMakePosixError(errno); - } - close(_file); - return NO; - } - return YES; -} - -- (NSData*)readData:(NSError**)error { - size_t length = MIN((NSUInteger)kFileReadBufferSize, _size); - NSMutableData* data = [[NSMutableData alloc] initWithLength:length]; - ssize_t result = read(_file, data.mutableBytes, length); - if (result < 0) { - if (error) { - *error = GCDWebServerMakePosixError(errno); - } - return nil; - } - if (result > 0) { - [data setLength:result]; - _size -= result; - } - return data; -} - -- (void)close { - close(_file); -} - -- (NSString*)description { - NSMutableString* description = [NSMutableString stringWithString:[super description]]; - [description appendFormat:@"\n\n{%@}", _path]; - return description; -} - -@end diff --git a/src/ios/GCDWebServer/Responses/GCDWebServerStreamedResponse.h b/src/ios/GCDWebServer/Responses/GCDWebServerStreamedResponse.h deleted file mode 100755 index bb48e66..0000000 --- a/src/ios/GCDWebServer/Responses/GCDWebServerStreamedResponse.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GCDWebServerResponse.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * The GCDWebServerStreamBlock is called to stream the data for the HTTP body. - * The block must return either a chunk of data, an empty NSData when done, or - * nil on error and set the "error" argument which is guaranteed to be non-NULL. - */ -typedef NSData* _Nullable (^GCDWebServerStreamBlock)(NSError** error); - -/** - * The GCDWebServerAsyncStreamBlock works like the GCDWebServerStreamBlock - * except the streamed data can be returned at a later time allowing for - * truly asynchronous generation of the data. - * - * The block must call "completionBlock" passing the new chunk of data when ready, - * an empty NSData when done, or nil on error and pass a NSError. - * - * The block cannot call "completionBlock" more than once per invocation. - */ -typedef void (^GCDWebServerAsyncStreamBlock)(GCDWebServerBodyReaderCompletionBlock completionBlock); - -/** - * The GCDWebServerStreamedResponse subclass of GCDWebServerResponse streams - * the body of the HTTP response using a GCD block. - */ -@interface GCDWebServerStreamedResponse : GCDWebServerResponse -@property(nonatomic, copy) NSString* contentType; // Redeclare as non-null - -/** - * Creates a response with streamed data and a given content type. - */ -+ (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block; - -/** - * Creates a response with async streamed data and a given content type. - */ -+ (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block; - -/** - * Initializes a response with streamed data and a given content type. - */ -- (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block; - -/** - * This method is the designated initializer for the class. - */ -- (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/Responses/GCDWebServerStreamedResponse.m b/src/ios/GCDWebServer/Responses/GCDWebServerStreamedResponse.m deleted file mode 100755 index 9387263..0000000 --- a/src/ios/GCDWebServer/Responses/GCDWebServerStreamedResponse.m +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (c) 2012-2015, Pierre-Olivier Latour - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The name of Pierre-Olivier Latour may not be used to endorse - or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !__has_feature(objc_arc) -#error GCDWebServer requires ARC -#endif - -#import "GCDWebServerPrivate.h" - -@implementation GCDWebServerStreamedResponse { - GCDWebServerAsyncStreamBlock _block; -} - -@dynamic contentType; - -+ (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block { - return [[[self class] alloc] initWithContentType:type streamBlock:block]; -} - -+ (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block { - return [[[self class] alloc] initWithContentType:type asyncStreamBlock:block]; -} - -- (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block { - return [self initWithContentType:type - asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) { - - NSError* error = nil; - NSData* data = block(&error); - completionBlock(data, error); - - }]; -} - -- (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block { - if ((self = [super init])) { - _block = [block copy]; - - self.contentType = type; - } - return self; -} - -- (void)asyncReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block { - _block(block); -} - -- (NSString*)description { - NSMutableString* description = [NSMutableString stringWithString:[super description]]; - [description appendString:@"\n\n"]; - return description; -} - -@end