diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..001cb6f --- /dev/null +++ b/.gitignore @@ -0,0 +1,185 @@ + +# Created by https://www.gitignore.io/api/osx,linux,webstorm,sublimetext,node + +### OSX ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon +# Thumbnails +._* +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + + +### WebStorm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/workspace.xml +.idea/tasks.xml + +# Sensitive or high-churn files: +.idea/dataSources/ +.idea/dataSources.ids +.idea/dataSources.xml +.idea/dataSources.local.xml +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# Gradle: +.idea/gradle.xml +.idea/libraries + +# Mongo Explorer plugin: +.idea/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### WebStorm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + + +### SublimeText ### +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + + +### Node ### +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# Custom +.idea +deployer.test.js + + +# End of https://www.gitignore.io/api/osx,linux,webstorm,sublimetext,node diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..7769c1f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "启动程序", + "program": "${workspaceFolder}\\deployer.test" + } + ] +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9cecc1d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a821305 --- /dev/null +++ b/README.md @@ -0,0 +1,94 @@ +# huaweicloud-obs-sync + +同步本地文件目录到华为云OBS文件夹。 + +## 特性说明 + +1. 支持增量同步本地文件目录到华为云OBS文件夹 +1. 支持设置是否同步删除OBS文件和目录 +1. 支持指定OBS同步目录 +1. 支持设置本地过滤文件和OBS过滤文件 + +## 安装说明 + +``` bash +npm install huaweicloud-obs-sync --save +``` + +## 使用说明 + +``` javascript +var obsSync = require('huaweicloud-obs-sync'); + +// 同步整个本地目录 +obsSync.syncFolderToOBS({ + server : "https://obs.cn-north-1.myhwclouds.com", + bucket: "obs-2f97", + accessKeyId: "R7DYQD3DQRRLTDWYtE3S", + secretAccessKey: "TERHf0NGpDrbhsbc1h3xymB9w22wK8lLgOFkgjCB2", + localDir: "D:\\public", + localFilesIgnorePattern: "^\\..*", + remoteDir: "/", + syncDeletedFiles: "yes", + syncDeletedFilesIgnorePattern: "^\\..*", + }) + +//同步本地目录下的单个文件 +obsSync.syncFileToOBS("D:\\public\\images\\avast.png", { + server : "https://obs.cn-north-1.myhwclouds.com", + bucket: "obs-2f97", + accessKeyId: "R7DYQD3DQRRLTDWYtE3S", + secretAccessKey: "TERHf0NGpDrbhsbc1h3xymB9w22wK8lLgOFkgjCB2" + localFileName: "D:\\public\\images\\avast.png", + remoteFileName: "images/avast.png" + }) +``` + +### syncFolderToOBS(options) + +同步整个本地目录到OBS + +| 名称 | 必选 | 默认值 | 描述 | +| -- | -- | -- |-- | +| server | 必填 | null | OBS服务器地址,以`https://`开头,不包含桶名称,比如`https://obs.cn-north-1.myhwclouds.com` | +| bucket |必填 | null | OBS桶名称 | +| accessKeyId | 必填 | null | 访问OBS的accessKeyId | +| secretAccessKey | 必填 | null | 访问OBS的secretAccessKey | +| localDir | 必填 | null | 本地同步目录的绝对路径 | +| localFilesIgnorePattern | 可选 | "^\\..*" | 本地忽略文件的正则表达式,该正则表达式会应用到文件相对于`localDir`的相对路径,路径分隔符为`/` | +| remoteDir | 可选 | / | 同步到远端的目录,路径分隔符为`/` | +| syncDeletedFiles | 可选 | yes | `yes`或者`no`, 如果是`yes`,则本地文件删除后,OBS中的文件也会对应删除,但是`syncDeletedFilesIgnorePattern`匹配上的文件除外 | +| syncDeletedFilesIgnorePattern | 可选 | "^\\..*" | 远端忽略文件的正则表达式,该正则表达式会应用到文件相对于`remoteDir`的相对路径,路径分隔符为`/` | + +### syncFileToOBS(options) + +同步本地目录的单个文件到OBS目录 + +| 名称 | 必选 | 默认值 | 描述 | +| -- | -- | -- |-- | +| server | 必填 | null | OBS服务器地址,以`https://`开头,不包含桶名称,比如`https://obs.cn-north-1.myhwclouds.com` | +| bucket |必填 | null | OBS桶名称 | +| accessKeyId | 必填 | null | 访问OBS的accessKeyId | +| secretAccessKey | 必填 | null | 访问OBS的secretAccessKey | +| localFileName | 必填 | null | 本地文件的绝对路径 | +| remoteFileName | 必填 | null | OBS中的全路径,路径分隔符为`/` | + +## 应用场景 + +### 1. Hexo插件 + +使用Hexo将文件发布到OBS,然后运用OBS的静态网站功能对外提供服务,参考: + +### 2. VSCode插件 + +使用VSCode编辑博客,粘贴图片自动将文件上传至OBS并自动在博客中插入图片地址,参考: + +## 3. 定期备份 + +定期备份本地目录到OBS + +## 相关资料 + +华为云OBS的SDK地址: https://developer.huaweicloud.com/sdk?OBS + +Hexo插件中心地址: https://hexo.io/plugins/ \ No newline at end of file diff --git a/lib/obs-sdk-3.0.0/enums.js b/lib/obs-sdk-3.0.0/enums.js new file mode 100644 index 0000000..ed46c18 --- /dev/null +++ b/lib/obs-sdk-3.0.0/enums.js @@ -0,0 +1,44 @@ +'use strict'; + +exports.AclPrivate = 'private'; +exports.AclPublicRead = 'public-read'; +exports.AclPublicReadWrite = 'public-read-write'; +exports.AclPublicReadDelivered = 'public-read-delivered'; +exports.AclPublicReadWriteDelivered = 'public-read-write-delivered'; +exports.AclAuthenticatedRead = 'authenticated-read'; +exports.AclBucketOwnerRead = 'bucket-owner-read'; +exports.AclBucketOwnerFullControl = 'bucket-owner-full-control'; +exports.AclLogDeliveryWrite = 'log-delivery-write'; + +exports.StorageClassStandard = 'STANDARD'; +exports.StorageClassWarm = 'WARM'; +exports.StorageClassCold = 'COLD'; + +exports.PermissionRead = 'READ'; +exports.PermissionWrite = 'WRITE'; +exports.PermissionReadAcp = 'READ_ACP'; +exports.PermissionWriteAcp = 'WRITE_ACP'; +exports.PermissionFullControl = 'FULL_CONTROL'; + +exports.GroupAllUsers = 'AllUsers'; +exports.GroupAuthenticatedUsers = 'AuthenticatedUsers'; +exports.GroupLogDelivery = 'LogDelivery'; + +exports.RestoreTierExpedited = 'Expedited'; +exports.RestoreTierStandard = 'Standard'; +exports.RestoreTierBulk = 'Bulk'; + +exports.GranteeGroup = 'Group'; +exports.GranteeUser = 'CanonicalUser'; + +exports.CopyMetadata = 'COPY'; +exports.ReplaceMetadata = 'REPLACE'; + +exports.EventObjectCreatedAll = 'ObjectCreated:*'; +exports.EventObjectCreatedPut = 'ObjectCreated:Put'; +exports.EventObjectCreatedPost = 'ObjectCreated:Post'; +exports.EventObjectCreatedCopy = 'ObjectCreated:Copy'; +exports.EventObjectCreatedCompleteMultipartUpload = 'ObjectCreated:CompleteMultipartUpload'; +exports.EventObjectRemovedAll = 'ObjectRemoved:*'; +exports.EventObjectRemovedDelete = 'ObjectRemoved:Delete'; +exports.EventObjectRemovedDeleteMarkerCreated = 'ObjectRemoved:DeleteMarkerCreated'; diff --git a/lib/obs-sdk-3.0.0/log.js b/lib/obs-sdk-3.0.0/log.js new file mode 100644 index 0000000..13a61dc --- /dev/null +++ b/lib/obs-sdk-3.0.0/log.js @@ -0,0 +1,135 @@ + +'use strict'; + +const os = require('os'); +const fs = require('fs'); +const process = require('process'); +const path = require('path'); +const log4js = require('log4js'); + +function checkAndCreateDir(dir,path){ + if(!fs.existsSync(dir)){ + let rout = path.dirname(dir); + if(!fs.existsSync(rout)){ + checkAndCreateDir(rout); + } + fs.mkdirSync(dir); + } +} + +function LogUtil(){ + this.loggerInf = null; + this.loggerRun = null; + this.consoleLog = null; +} + +LogUtil.prototype.initLog = function(filename, maxLogSize, backups, level, logToConsole, name){ + process.on('uncaughtException', function (err) { + console.log(err); + }); + var dir = path.dirname(filename); + checkAndCreateDir(dir,path); + var ext = path.extname(filename); + var file = path.basename(filename, ext); + if(!ext){ + ext = '.log'; + } + + level = level === undefined ? 'info' : String(level); + maxLogSize = maxLogSize === undefined ? 102400 : parseInt(maxLogSize); + backups = backups === undefined ? 10 : parseInt(backups); + + var fileInterface = path.join(dir, file + ext); + var layoutFormat = '%d{yyyy/MM/dd hh:mm:ss SSS}|%c|%-5p|%m'; + var cateInterface = 'sdk-file'; + var cateConsole = 'sdk-console'; + if(name){ + cateInterface += ':' + String(name); + cateConsole += ':' + String(name); + } + + if(log4js.appenders.file){ + log4js.addAppender(log4js.appenders.file( + fileInterface, + log4js.layouts.patternLayout(layoutFormat), + maxLogSize, + backups), cateInterface); + }else{ + log4js.configure({ + appenders:[ + { + type:'file', + category:cateInterface, + filename:fileInterface, + maxLogSize:maxLogSize, + backups:backups, + layout : { + type:'pattern', + pattern: layoutFormat + } + }, + ] + }); + } + + this.loggerInf = log4js.getLogger(cateInterface); + this.loggerInf.setLevel(level.toLowerCase()); + if(logToConsole){ + if(!log4js.appenders.console){ + log4js.loadAppender('console'); + } + log4js.addAppender(log4js.appenders.console(log4js.layouts.patternLayout(layoutFormat)), cateConsole); + this.consoleLog = log4js.getLogger(cateConsole); + this.consoleLog.setLevel(level.toLowerCase()); + } +}; + +LogUtil.prototype._doLog = function(level, form){ + if(level.toLowerCase() === 'debug'){ + if(this.loggerInf){ + this.loggerInf.debug(form); + } + if(this.consoleLog){ + this.consoleLog.debug(form); + } + }else if(level.toLowerCase() === 'info'){ + if(this.loggerInf){ + this.loggerInf.info(form); + } + if(this.consoleLog){ + this.consoleLog.info(form); + } + }else if(level.toLowerCase() === 'warn'){ + if(this.loggerInf){ + this.loggerInf.warn(form); + } + if(this.consoleLog){ + this.consoleLog.warn(form); + } + }else if(level.toLowerCase() === 'error'){ + if(this.loggerInf){ + this.loggerInf.error(form); + } + if(this.consoleLog){ + this.consoleLog.error(form); + } + } +}; + +LogUtil.prototype.isLevelEnabled = function(level){ + return (this.loggerInf && this.loggerInf.isLevelEnabled(level)) || (this.consoleLog && this.consoleLog.isLevelEnabled(level)); +}; + +LogUtil.prototype.runLog = function(level, methodName, msg){ + if(!this.loggerInf && !this.consoleLog){ + return; + } + var form = methodName + '|' + msg; + this._doLog(level, form); +}; + + +module.exports = LogUtil; + + + diff --git a/lib/obs-sdk-3.0.0/obs.js b/lib/obs-sdk-3.0.0/obs.js new file mode 100644 index 0000000..3ffd7b4 --- /dev/null +++ b/lib/obs-sdk-3.0.0/obs.js @@ -0,0 +1,1239 @@ + +'use strict'; + +const Utils = require('./utils'); +const LogUtil = require('./log'); +const enums = require('./enums'); + +function ObsClient(param){ + this.factory(param); +} + +function capitalize(key){ + return key.slice(0,1).toUpperCase() + key.slice(1); +} + +const methods = [ + 'createBucket', + 'listBuckets', + 'headBucket', + 'getBucketMetadata', + 'deleteBucket', + 'setBucketQuota', + 'getBucketQuota', + 'getBucketStorageInfo', + 'setBucketPolicy', + 'getBucketPolicy', + 'deleteBucketPolicy', + 'setBucketVersioningConfiguration', + 'getBucketVersioningConfiguration', + 'getBucketLocation', + 'listVersions', + 'listObjects', + 'setBucketLifecycleConfiguration', + 'getBucketLifecycleConfiguration', + 'deleteBucketLifecycleConfiguration', + 'setBucketAcl', + 'getBucketAcl', + 'setBucketLoggingConfiguration', + 'getBucketLoggingConfiguration', + 'setBucketWebsiteConfiguration', + 'getBucketWebsiteConfiguration', + 'deleteBucketWebsiteConfiguration', + 'setBucketNotification', + 'getBucketNotification', + 'setBucketTagging', + 'deleteBucketTagging', + 'getBucketTagging', + 'setBucketReplication', + 'deleteBucketReplication', + 'getBucketReplication', + 'getObject', + 'getObjectMetadata', + 'setObjectAcl', + 'getObjectAcl', + 'deleteObject', + 'deleteObjects', + 'listMultipartUploads', + 'listParts', + 'abortMultipartUpload', + 'completeMultipartUpload', + 'setBucketCors', + 'getBucketCors', + 'deleteBucketCors', + 'optionsBucket', + 'optionsObject', + 'setBucketStoragePolicy', + 'getBucketStoragePolicy' +]; + +for(let i=0;i 0){ + val = this.util.encodeURIWithSafe(val.slice(0, index)) + val.slice(index); + }else{ + param[key] = this.util.encodeURIWithSafe(val); + } + } + this.exec('CopyObject', param, callback); +}; + +ObsClient.prototype.copyPart = function(param, callback){ + let key = 'CopySource'; + if(key in param){ + let val = param[key]; + let index = val.lastIndexOf('?versionId='); + if(index > 0){ + val = this.util.encodeURIWithSafe(val.slice(0, index)) + val.slice(index); + }else{ + param[key] = this.util.encodeURIWithSafe(val); + } + } + this.exec('CopyPart', param, callback); +}; + +ObsClient.prototype.restoreObject = function(param, callback){ + this.exec('RestoreObject', param, function(err, result){ + if(!err && result.InterfaceResult && result.CommonMsg.Status < 300){ + result.InterfaceResult.RestoreStatus = result.CommonMsg.Status === 200 ? 'AVALIABLE' : 'INPROGRESS'; + } + callback(err, result); + }); +}; + +ObsClient.prototype.initiateMultipartUpload = function(param, callback){ + if(!('ContentType' in param) && 'Key' in param){ + param.ContentType = this.util.mimeTypes[param.Key.substring(param.Key.lastIndexOf('.') + 1)]; + } + this.exec('InitiateMultipartUpload', param, callback); +}; + + +ObsClient.prototype.uploadPart = function(param, callback){ + if(('Body' in param) && ('SourceFile' in param)){ + let err = 'the input body and sourcefile exist at same time,please specify one of eigther a string or file to be send!'; + if(this.log.isLevelEnabled('error')){ + this.log.runLog('error', 'UploadPart', err); + } + callback(err, null); + return; + } + this.exec('UploadPart', param, callback); +}; + + +ObsClient.prototype.uploadFile = function(param, callback){ + param = param || {}; + var _log = this.log; + var obsClient = this; + var funcName = 'uploadFile'; + var start = new Date().getTime(); + callback = callback || function(){}; + var _callback = function(code, message, result){ + if(_log.isLevelEnabled('info')){ + _log.runLog('info', funcName, 'ObsClient cost ' + (new Date().getTime()-start) + ' ms'); + } + if(typeof code === 'string'){ + if(message){ + code += ':' + String(message); + } + callback(code, result); + }else{ + callback(code ? (code.CommonMsg.Code + ':' + code.CommonMsg.Message) : null, result); + } + }; + + if(_log.isLevelEnabled('info')){ + _log.runLog('info', funcName, 'enter ' + funcName + '...' ); + } + + var bucket = param.Bucket; + if(!bucket){ + _callback('InvalidArgument','Bucket is a required element!'); + return; + } + bucket = String(bucket); + + var key = param.Key; + if(!key){ + _callback('InvalidArgument', 'Key is a required element!'); + return; + } + key = String(key); + + var uploadFile = param.UploadFile; + if(!uploadFile){ + _callback('InvalidArgument', 'UploadFile is a required element!'); + return; + } + var fs = require('fs'); + uploadFile = String(uploadFile); + + if(!fs.existsSync(uploadFile)){ + _callback('InvalidArgument', 'UploadFile does not exist!'); + return; + } + var fstat = fs.statSync(uploadFile); + if(!fstat.isFile()){ + _callback('InvalidArgument', 'UploadFile is not a file!'); + return; + } + + var fileSize = fstat.size; + + var enableCheckpoint = Boolean(param.EnableCheckpoint); + var checkpointFile = null; + var enableCheckSum = false; + + var taskNum = parseInt(param.TaskNum) || 20; + + if(enableCheckpoint){ + checkpointFile = param.CheckpointFile; + checkpointFile = (checkpointFile && checkpointFile !== '') ? String(checkpointFile) : uploadFile + '.upload_record'; + let pathLib = require('path'); + let fileDir = pathLib.dirname(checkpointFile); + if(!fs.existsSync(fileDir)){ + let mkdirsSync = function(dirname){ + if(fs.existsSync(dirname)){ + return true; + }else{ + if(mkdirsSync(pathLib.dirname(dirname))){ + fs.mkdirSync(dirname); + return true; + } + } + }; + mkdirsSync(fileDir); + } + enableCheckSum = Boolean(param.EnableCheckSum); + } + if(_log.isLevelEnabled('debug')){ + _log.runLog('debug', funcName, 'Begin to uploadFile to OBS from file:' + uploadFile); + } + + var events = require('events'); + var eventEmitter = new events.EventEmitter(); + + var calculateUploadCheckpointMD5 = function(uploadCheckpoint){ + let data = []; + data.push(uploadCheckpoint.bucketName); + data.push(uploadCheckpoint.objectKey); + data.push(uploadCheckpoint.uploadFile); + data.push(String(uploadCheckpoint.partSize)); + data.push(String(uploadCheckpoint.partCount)); + if(uploadCheckpoint.contentType){ + data.push(uploadCheckpoint.contentType); + } + if(uploadCheckpoint.acl){ + data.push(uploadCheckpoint.acl); + } + if(uploadCheckpoint.websiteRedirectLocation){ + data.push(uploadCheckpoint.websiteRedirectLocation); + } + if(uploadCheckpoint.sseKms){ + data.push(uploadCheckpoint.sseKms); + } + if(uploadCheckpoint.sseKmsKey){ + data.push(uploadCheckpoint.sseKmsKey); + } + if(uploadCheckpoint.sseC){ + data.push(uploadCheckpoint.sseC); + } + if(uploadCheckpoint.sseCKey){ + data.push(uploadCheckpoint.sseCKey); + } + if(uploadCheckpoint.metadata){ + data.push(JSON.stringify(uploadCheckpoint.metadata)); + } + if(uploadCheckpoint.uploadId){ + data.push(uploadCheckpoint.uploadId); + } + if(uploadCheckpoint.partsMeta && (uploadCheckpoint.partsMeta instanceof Object)){ + for(let key in uploadCheckpoint.partsMeta){ + data.push(String(key)); + let partMeta = uploadCheckpoint.partsMeta[key]; + if(partMeta){ + data.push(String(partMeta.offset)); + data.push(String(partMeta.partSize)); + data.push(String(partMeta.isCompleted)); + data.push(String(partMeta.etag)); + } + } + } + return obsClient.util.bufMD5(Buffer.from(data.join(''), 'utf8')); + }; + + var writeCheckpointFileSync = function(checkpointFile, uploadCheckpoint){ + try{ + fs.writeFileSync(checkpointFile, JSON.stringify(uploadCheckpoint)); + return true; + }catch(e){ + _callback('WriteCheckpointFileError', e); + if(_log.isLevelEnabled('debug')){ + _log.runLog('debug', funcName, 'Write checkpoint file failed and abort upload, uploadId ' + uploadCheckpoint.uploadId); + } + if(uploadCheckpoint.uploadId){ + obsClient.abortMultipartUpload({ + Bucket:uploadCheckpoint.bucketName, + Key:uploadCheckpoint.objectKey, + UploadId:uploadCheckpoint.uploadId, + },function(e, r){ + if(!e && (r.CommonMsg.Status < 300 || r.CommonMsg.Status === 404)){ + fs.unlink(checkpointFile, function(){}); + } + }); + }else{ + fs.unlink(checkpointFile, function(){}); + } + return false; + } + }; + + var abortRequest = function(uploadCheckpoint, checkpointFile, code, message){ + if(uploadCheckpoint && uploadCheckpoint.uploadId){ + obsClient.abortMultipartUpload({ + Bucket:uploadCheckpoint.bucketName, + Key:uploadCheckpoint.objectKey, + UploadId:uploadCheckpoint.uploadId, + },function(e, r){ + if(!e && (r.CommonMsg.Status < 300 || r.CommonMsg.Status === 404)){ + if(checkpointFile){ + fs.unlink(checkpointFile, function(){}); + } + } + _callback(code, message); + }); + }else{ + if(checkpointFile){ + fs.unlink(checkpointFile, function(){}); + } + _callback(code, message); + } + }; + + var transResultToError = function(result){ + let ret = []; + if(result && result.CommonMsg){ + ret.push('Status:' + result.CommonMsg.Status); + ret.push('Code:' + result.CommonMsg.Code); + ret.push('Message:' + result.CommonMsg.Message); + } + return ret.join(','); + }; + + eventEmitter.on('start to uploadFile', function(uploadCheckpoint){ + if(!uploadCheckpoint){ + uploadCheckpoint = {}; + } + if(!uploadCheckpoint.partsMeta){ + uploadCheckpoint.partsMeta = {}; + } + var startToUploadFile = function(uploadId){ + let finishedCount = 0; + let hasError = false; + let isAbort = false; + let completedRequest = function(){ + if(finishedCount === uploadCheckpoint.partCount){ + if(!hasError){ + let parts = []; + for(let partNumber in uploadCheckpoint.partsMeta){ + parts.push({ + PartNumber : partNumber, + ETag : uploadCheckpoint.partsMeta[partNumber].etag + }); + } + obsClient.completeMultipartUpload({ + Bucket: uploadCheckpoint.bucketName, + Key : uploadCheckpoint.objectKey, + UploadId : uploadId, + Parts: parts + }, function(err, result){ + if(err || result.CommonMsg.Status >= 500){ + if(checkpointFile){ + _callback('IncompletedUpload', err ? err : transResultToError(result)); + }else{ + abortRequest(uploadCheckpoint, checkpointFile, 'UploadFileFailed', err ? err : transResultToError(result)); + } + }else if(result.CommonMsg.Status >= 300 && result.CommonMsg.Status < 500){ + abortRequest(uploadCheckpoint, checkpointFile, result.CommonMsg.Code, result.CommonMsg.Message); + }else{ + if(checkpointFile){ + fs.unlink(checkpointFile, function(){}); + } + _callback(null, null, result); + } + }); + }else{ + if(checkpointFile){ + _callback('IncompletedUpload','UploadFile finished with error, you can retry with the same parameters'); + }else{ + abortRequest(uploadCheckpoint, checkpointFile, 'UploadFileFailed', 'UploadFile finished with error!'); + } + } + } + }; + + eventEmitter.on('doUpload', function(currentGroupIndex, groupCount, taskNum){ + let start = (currentGroupIndex - 1) * taskNum; + let end = (currentGroupIndex === groupCount) ? uploadCheckpoint.partCount : currentGroupIndex * taskNum; + let finishedCountGroup = 0; + while(start= 500){ + partMeta.isCompleted = false; + hasError = true; + }else if(result.CommonMsg.Status >= 300 && result.CommonMsg.Status < 500){ + isAbort = true; + abortRequest(uploadCheckpoint, checkpointFile, result.CommonMsg.Code, result.CommonMsg.Message); + return; + }else{ + partMeta.etag = result.InterfaceResult.ETag; + partMeta.isCompleted = true; + } + uploadCheckpoint.partsMeta[partNumber] = partMeta; + if(_log.isLevelEnabled('debug')){ + _log.runLog('debug', funcName, 'Part ' + String(partNumber) + ' is finished, uploadId ' + uploadId); + } + uploadCheckpoint.md5 = calculateUploadCheckpointMD5(uploadCheckpoint); + if(checkpointFile && !writeCheckpointFileSync(checkpointFile, uploadCheckpoint)){ + return; + } + finishedCount++; + finishedCountGroup++; + let _taskNum = (currentGroupIndex === groupCount) ? (uploadCheckpoint.partCount - (currentGroupIndex - 1) * taskNum) : taskNum; + if(finishedCountGroup === _taskNum && finishedCount < uploadCheckpoint.partCount){ + eventEmitter.emit('doUpload', currentGroupIndex + 1, groupCount, taskNum); + } + completedRequest(); + }); + } + start++; + } + }); + + let groupCount = (uploadCheckpoint.partCount % taskNum === 0) ? (uploadCheckpoint.partCount / taskNum) : (Math.floor(uploadCheckpoint.partCount / taskNum) + 1); + eventEmitter.emit('doUpload', 1, groupCount, taskNum); + }; + + let uploadId = uploadCheckpoint.uploadId; + if(!uploadId){ + let contentType = uploadCheckpoint.contentType ? uploadCheckpoint.contentType : obsClient.util.mimeTypes[key.substring(key.lastIndexOf('.') + 1)]; + + if(!contentType){ + contentType = obsClient.util.mimeTypes[uploadFile.substring(uploadFile.lastIndexOf('.') + 1)]; + } + + obsClient.initiateMultipartUpload({ + Bucket : uploadCheckpoint.bucketName, + Key : uploadCheckpoint.objectKey, + ACL : uploadCheckpoint.acl, + Metadata : uploadCheckpoint.metadata, + WebsiteRedirectLocation : uploadCheckpoint.websiteRedirectLocation, + ContentType : contentType, + SseKms : uploadCheckpoint.sseKms, + SseKmsKey : uploadCheckpoint.sseKmsKey, + SseC : uploadCheckpoint.sseC, + SseCKey : uploadCheckpoint.sseCKey + }, function(err, result){ + if(err){ + if(checkpointFile){ + fs.unlink(checkpointFile, function(){}); + } + _callback('InitateMultipartUploadFailed',err); + return; + } + if(result.CommonMsg.Status >= 300){ + if(checkpointFile){ + fs.unlink(checkpointFile, function(){}); + } + _callback(result); + return; + } + + uploadId = result.InterfaceResult.UploadId; + uploadCheckpoint.uploadId = uploadId; + uploadCheckpoint.md5 = calculateUploadCheckpointMD5(uploadCheckpoint); + if(_log.isLevelEnabled('debug')){ + _log.runLog('debug', funcName, 'Claim a new upload id ' + uploadId); + } + if(checkpointFile && !writeCheckpointFileSync(checkpointFile, uploadCheckpoint)){ + return; + } + startToUploadFile(uploadId); + }); + }else{ + startToUploadFile(uploadId); + } + }); + + var uploadCheckpoint; + var partSize = parseInt(param.PartSize); + var partCount; + if(fileSize === 0){ + partSize = 0; + partCount = 1; + }else{ + partSize = isNaN(partSize) ? 5 * 1024 * 1024 : (partSize < 5 * 1024 * 1024 ? 5 * 1024 * 1024 : (partSize > 5 * 1024 * 1024 * 1024 ? 5 * 1024 * 1024 * 1024 : partSize)); + partCount = Math.floor(fileSize / partSize); + if(fileSize % partSize !== 0){ + partCount++; + } + } + if(_log.isLevelEnabled('debug')){ + _log.runLog('debug', funcName, 'Total parts count ' + partCount); + } + uploadCheckpoint = {bucketName: bucket, objectKey: key, uploadFile : uploadFile, partSize : partSize, partCount : partCount}; + uploadCheckpoint.contentType = param.ContentType; + uploadCheckpoint.acl = param.ACL; + uploadCheckpoint.websiteRedirectLocation = param.WebsiteRedirectLocation; + uploadCheckpoint.sseKms = param.SseKms; + uploadCheckpoint.sseKmsKey = param.SseKmsKey; + uploadCheckpoint.sseC = param.sseC; + uploadCheckpoint.sseCKey = param.SseCKey; + uploadCheckpoint.metadata = param.Metadata; + uploadCheckpoint.md5 = calculateUploadCheckpointMD5(uploadCheckpoint); + uploadCheckpoint.uploadFileStat = {fileSize : fileSize, lastModified : fstat.mtime.toUTCString()}; + + if(checkpointFile){ + if(!fs.existsSync(checkpointFile)){// call uploadFile first time + eventEmitter.on('start to writeFile', function(){ + fs.writeFile(checkpointFile, JSON.stringify(uploadCheckpoint), function(err){ + if(err){ + _callback('WriteCheckpointFileError',err); + return; + } + eventEmitter.emit('start to uploadFile', uploadCheckpoint); + }); + }); + if(enableCheckSum){ + obsClient.util.fileMD5(uploadFile, function(err, checkSum){ + if(err){ + checkSum = ''; + } + uploadCheckpoint.uploadFileStat.checkSum = checkSum; + eventEmitter.emit('start to writeFile'); + }); + }else{ + eventEmitter.emit('start to writeFile'); + } + }else{ + fs.readFile(checkpointFile, function(err, data){ + if(err){ + fs.unlink(checkpointFile, function(){}); + _callback('ReadCheckpointFileError',err); + return; + } + try{ + uploadCheckpoint = JSON.parse(data); + }catch(e){ + fs.unlink(checkpointFile, function(){}); + _callback('ParseCheckpointFileError', e); + return; + } + if(!uploadCheckpoint || uploadCheckpoint.bucketName !== bucket || uploadCheckpoint.objectKey !== key || uploadCheckpoint.uploadFile !== uploadFile || + !uploadCheckpoint.uploadFileStat || uploadCheckpoint.uploadFileStat.fileSize !== fstat.size || uploadCheckpoint.uploadFileStat.lastModified !== fstat.mtime.toUTCString() || + uploadCheckpoint.md5 !== calculateUploadCheckpointMD5(uploadCheckpoint)){ + abortRequest(uploadCheckpoint, checkpointFile, 'CheckpointFileInvalid', 'CheckpointFile is invalid!'); + return; + } + + if(uploadCheckpoint.uploadFileStat.checkSum){ + obsClient.util.fileMD5(uploadFile, function(err, checkSum){ + if(err || checkSum !== uploadCheckpoint.uploadFileStat.checkSum){ + abortRequest(uploadCheckpoint, checkpointFile, 'CheckpointFileInvalid','CheckpointFile is invalid!'); + return; + } + eventEmitter.emit('start to uploadFile', uploadCheckpoint); + }); + }else{ + eventEmitter.emit('start to uploadFile', uploadCheckpoint); + } + }); + } + }else{ + eventEmitter.emit('start to uploadFile', uploadCheckpoint); + } +}; + +ObsClient.prototype.downloadFile = function(param, callback){ + param = param || {}; + var _log = this.log; + var obsClient = this; + var funcName = 'downloadFile'; + var start = new Date().getTime(); + callback = callback || function(){}; + var _callback = function(code, message, result){ + if(_log.isLevelEnabled('info')){ + _log.runLog('info', funcName, 'ObsClient cost ' + (new Date().getTime() - start) + ' ms'); + } + if(typeof code === 'string'){ + if(message){ + code += ':' + String(message); + } + callback(code, result); + }else{ + callback(code ? (code.CommonMsg.Code + ':' + code.CommonMsg.Message) : null, result); + } + }; + + if(_log.isLevelEnabled('info')){ + _log.runLog('info', funcName, 'enter ' + funcName + '...' ); + } + + var bucket = param.Bucket; + if(!bucket){ + _callback('InvalidArgument','Bucket is a required element!'); + return; + } + bucket = String(bucket); + + var key = param.Key; + if(!key){ + _callback('InvalidArgument', 'Key is a required element!'); + return; + } + key = String(key); + + var pathLib = require('path'); + + var downloadFile; + if(!param.DownloadFile){ + downloadFile = require('process').cwd() + pathLib.sep + key; + if(_log.isLevelEnabled('info')){ + _log.runLog('info', funcName, 'DownloadFile is not set, will put file to path:' + downloadFile); + } + }else{ + downloadFile = String(param.DownloadFile); + } + var downloadTempFile = downloadFile + '.temp'; + var fs = require('fs'); + + var taskNum = parseInt(param.TaskNum) || 20; + + obsClient.getObjectMetadata({ + Bucket : bucket, + Key : key, + VersionId : param.VersionId, + }, function(err, result){ + + let enableCheckpoint = Boolean(param.EnableCheckpoint); + let checkpointFile = null; + let mkdirsSync = function(dirname){ + if(fs.existsSync(dirname)){ + return true; + }else{ + if(mkdirsSync(pathLib.dirname(dirname))){ + fs.mkdirSync(dirname); + return true; + } + } + }; + if(enableCheckpoint){ + checkpointFile = param.CheckpointFile; + checkpointFile = (checkpointFile && checkpointFile !== '') ? String(checkpointFile) : downloadFile + '.download_record'; + let checkPointFileDir = pathLib.dirname(checkpointFile); + if(!fs.existsSync(checkPointFileDir)){ + mkdirsSync(checkPointFileDir); + } + } + + let tempFileDir = pathLib.dirname(downloadTempFile); + if(!fs.existsSync(tempFileDir)){ + mkdirsSync(tempFileDir); + } + + if(err || result.CommonMsg.Status >= 500){ + _callback('GetObjectSizeError', err); + return; + } + + if(result.CommonMsg.Status >= 300 && result.CommonMsg.Status < 500){ + fs.unlink(downloadTempFile, function(){}); + if(checkpointFile){ + fs.unlink(checkpointFile, function(){}); + } + _callback(result); + return; + } + + let objectSize = parseInt(result.InterfaceResult.ContentLength); + + if(objectSize === 0){ + fs.writeFileSync(downloadFile, Buffer.from('')); + callback(null, result); + return; + } + + let objestStat = result; + + let events = require('events'); + let eventEmitter = new events.EventEmitter(); + + let calculateDownloadCheckpointMD5 = function(downloadCheckpoint){ + let data = []; + data.push(downloadCheckpoint.bucketName); + data.push(downloadCheckpoint.objectKey); + data.push(downloadCheckpoint.downloadFile); + data.push(String(downloadCheckpoint.partSize)); + data.push(String(downloadCheckpoint.partCount)); + if(downloadCheckpoint.versionId){ + data.push(downloadCheckpoint.versionId); + } + if(downloadCheckpoint.ifMatch){ + data.push(downloadCheckpoint.ifMatch); + } + if(downloadCheckpoint.ifModifiedSince){ + data.push(downloadCheckpoint.ifModifiedSince); + } + if(downloadCheckpoint.ifNoneMatch){ + data.push(downloadCheckpoint.ifNoneMatch); + } + if(downloadCheckpoint.ifUnmodifiedSince){ + data.push(downloadCheckpoint.ifUnmodifiedSince); + } + if(downloadCheckpoint.sseC){ + data.push(downloadCheckpoint.sseC); + } + if(downloadCheckpoint.sseCKey){ + data.push(downloadCheckpoint.sseCKey); + } + if(downloadCheckpoint.partsMeta && (downloadCheckpoint.partsMeta instanceof Object)){ + for(let key in downloadCheckpoint.partsMeta){ + data.push(String(key)); + let partMeta = downloadCheckpoint.partsMeta[key]; + if(partMeta){ + data.push(String(partMeta.startPos)); + data.push(String(partMeta.endPos)); + data.push(String(partMeta.isCompleted)); + } + } + } + return obsClient.util.bufMD5(Buffer.from(data.join(''), 'utf8')); + }; + + let writeCheckpointFileSync = function(checkpointFile, downloadCheckpoint){ + try{ + if(fs.existsSync(downloadTempFile)){ + let tempFileStat = fs.statSync(downloadTempFile); + if(!downloadCheckpoint.tempFileStatus){ + downloadCheckpoint.tempFileStatus = {}; + } + downloadCheckpoint.tempFileStatus.fileSize = tempFileStat.size; + downloadCheckpoint.tempFileStatus.lastModified = tempFileStat.mtime.toUTCString(); + } + fs.writeFileSync(checkpointFile, JSON.stringify(downloadCheckpoint)); + return true; + }catch(e){ + fs.unlink(checkpointFile, function(){}); + fs.unlink(downloadTempFile, function(){}); + _callback('WriteCheckpointFileError', e); + if(_log.isLevelEnabled('warn')){ + _log.runLog('warn', funcName, 'Write checkpoint file failed'); + } + return false; + } + }; + + eventEmitter.on('start to downloadFile', function(downloadCheckpoint){ + + if(!downloadCheckpoint){ + downloadCheckpoint = {}; + } + + if(!downloadCheckpoint.partsMeta){ + downloadCheckpoint.partsMeta = {}; + } + if(_log.isLevelEnabled('debug')){ + _log.runLog('debug', funcName, 'Begin to downloadFile from OBS to:' + downloadFile); + } + + fs.open(downloadTempFile, 'a', function(err, fd){ + if(err){ + if(checkpointFile){ + fs.unlink(checkpointFile, function(){}); + } + _callback('OpenDownloadTempFileError',err); + return; + } + let finishedCount = 0; + let hasError = false; + let isAbort = false; + + let completedDownload = function(result){ + if(finishedCount === downloadCheckpoint.partCount){ + try{ + fs.closeSync(fd); + }catch(e){ + if(_log.isLevelEnabled('debug')){ + _log.runLog('debug', funcName, 'Close temp file error :' + e); + } + } + if(!hasError){ + fs.rename(downloadTempFile, downloadFile, function(err){ + if(err){ + if(checkpointFile){ + if(!writeCheckpointFileSync(checkpointFile, downloadCheckpoint)){ + return; + } + _callback('IncompletedDownload','DownloadFile finished but rename temp file error, you can retry with the same parameters, err:' + err); + }else{ + fs.unlink(downloadTempFile, function(){}); + _callback('DownloadFileFailed','DownloadFile finished but rename temp file error'); + } + return; + } + if(checkpointFile){ + fs.unlink(checkpointFile, function(){}); + } + if(result && result.InterfaceResult){ + delete result.InterfaceResult.ContentLength; + } + _callback(null, null, result); + }); + }else{ + if(checkpointFile){ + if(!writeCheckpointFileSync(checkpointFile, downloadCheckpoint)){ + return; + } + _callback('IncompletedDownload','DownloadFile finished with error, you can retry with the same parameters'); + }else{ + fs.unlink(downloadTempFile, function(){}); + _callback('DownloadFileFailed','DownloadFile finished with error'); + } + } + } + }; + + eventEmitter.on('doDownload', function(currentGroupIndex, groupCount, taskNum){ + let start = (currentGroupIndex - 1) * taskNum; + let end = (currentGroupIndex === groupCount) ? downloadCheckpoint.partCount : currentGroupIndex * taskNum; + let finishedCountGroup = 0; + while(start < end){ + if(isAbort){ + return; + } + let i = start + 1; + if(downloadCheckpoint.partsMeta[i] && downloadCheckpoint.partsMeta[i].isCompleted){ + finishedCount++; + finishedCountGroup++; + let _taskNum = (currentGroupIndex === groupCount) ? (downloadCheckpoint.partCount - (currentGroupIndex - 1) * taskNum) : taskNum; + if(finishedCountGroup === _taskNum && finishedCount < downloadCheckpoint.partCount){ + eventEmitter.emit('doDownload', currentGroupIndex + 1, groupCount, taskNum); + } + completedDownload(); + }else{ + let startPos = (i-1) * downloadCheckpoint.partSize; + let endPos = (i === downloadCheckpoint.partCount) ? (downloadCheckpoint.objectStatus.objectSize-1) : (i * downloadCheckpoint.partSize - 1); + obsClient.getObject({ + Bucket: downloadCheckpoint.bucketName, + Key: downloadCheckpoint.objectKey, + VersionId : downloadCheckpoint.versionId, + Range: 'bytes=' + startPos + '-' + endPos, + SaveAsStream : true, + IfMatch : downloadCheckpoint.ifMatch, + IfModifiedSince : downloadCheckpoint.ifModifiedSince, + IfNoneMatch : downloadCheckpoint.ifNoneMatch, + IfUnmodifiedSince : downloadCheckpoint.ifUnmodifiedSince, + SseC : downloadCheckpoint.sseC, + SseCKey : downloadCheckpoint.sseCKey + }, function(err, result) { + if(isAbort){ + return; + } + let partMeta = {startPos : startPos, endPos : endPos}; + if(err || result.CommonMsg.Status >= 500){ + partMeta.isCompleted = false; + hasError = true; + downloadCheckpoint.partsMeta[i] = partMeta; + downloadCheckpoint.md5 = calculateDownloadCheckpointMD5(downloadCheckpoint); + if(checkpointFile && !writeCheckpointFileSync(checkpointFile, downloadCheckpoint)){ + return; + } + finishedCount++; + finishedCountGroup++; + let _taskNum = (currentGroupIndex === groupCount) ? (downloadCheckpoint.partCount - (currentGroupIndex - 1) * taskNum) : taskNum; + if(finishedCountGroup === _taskNum && finishedCount < downloadCheckpoint.partCount){ + eventEmitter.emit('doDownload', currentGroupIndex + 1, groupCount, taskNum); + } + completedDownload(); + }else if(result.CommonMsg.Status >= 300 && result.CommonMsg.Status < 500){ + isAbort = true; + try{ + fs.closeSync(fd); + }catch(e){ + if(_log.isLevelEnabled('debug')){ + _log.runLog('debug', funcName, 'Close temp file error :' + e); + } + } + if(checkpointFile){ + fs.unlink(checkpointFile, function(){}); + } + fs.unlink(downloadTempFile, function(){}); + _callback(result); + return; + }else{ + let _startPos = startPos; + result.InterfaceResult.Content.on('data', function(data){ + fs.write(fd, data, 0, data.length, _startPos, function(err){ + if(err && partMeta.isCompleted === undefined){ + partMeta.isCompleted = false; + hasError = true; + downloadCheckpoint.partsMeta[i] = partMeta; + downloadCheckpoint.md5 = calculateDownloadCheckpointMD5(downloadCheckpoint); + if(checkpointFile && !writeCheckpointFileSync(checkpointFile, downloadCheckpoint)){ + return; + } + finishedCount++; + finishedCountGroup++; + let _taskNum = (currentGroupIndex === groupCount) ? (downloadCheckpoint.partCount - (currentGroupIndex - 1) * taskNum) : taskNum; + if(finishedCountGroup === _taskNum && finishedCount < downloadCheckpoint.partCount){ + eventEmitter.emit('doDownload', currentGroupIndex + 1, groupCount, taskNum); + } + completedDownload(); + return; + } + }); + _startPos += data.length; + }).on('error', function(){ + if(partMeta.isCompleted === undefined){ + partMeta.isCompleted = false; + hasError = true; + downloadCheckpoint.partsMeta[i] = partMeta; + downloadCheckpoint.md5 = calculateDownloadCheckpointMD5(downloadCheckpoint); + if(checkpointFile && !writeCheckpointFileSync(checkpointFile, downloadCheckpoint)){ + return; + } + finishedCount++; + finishedCountGroup++; + let _taskNum = (currentGroupIndex === groupCount) ? (downloadCheckpoint.partCount - (currentGroupIndex - 1) * taskNum) : taskNum; + if(finishedCountGroup === _taskNum && finishedCount < downloadCheckpoint.partCount){ + eventEmitter.emit('doDownload', currentGroupIndex + 1, groupCount, taskNum); + } + completedDownload(); + } + }).on('end',function(){ + if(partMeta.isCompleted === undefined){ + partMeta.isCompleted = true; + downloadCheckpoint.partsMeta[i] = partMeta; + downloadCheckpoint.md5 = calculateDownloadCheckpointMD5(downloadCheckpoint); + if(checkpointFile && !writeCheckpointFileSync(checkpointFile, downloadCheckpoint)){ + return; + } + finishedCount++; + finishedCountGroup++; + let _taskNum = (currentGroupIndex === groupCount) ? (downloadCheckpoint.partCount - (currentGroupIndex - 1) * taskNum) : taskNum; + if(finishedCountGroup === _taskNum && finishedCount < downloadCheckpoint.partCount){ + eventEmitter.emit('doDownload', currentGroupIndex + 1, groupCount, taskNum); + } + delete result.InterfaceResult.Content; + completedDownload(result); + } + }); + } + }); + } + start++; + } + + }); + let groupCount = (downloadCheckpoint.partCount % taskNum === 0) ? (downloadCheckpoint.partCount / taskNum) : (Math.floor(downloadCheckpoint.partCount / taskNum) + 1); + eventEmitter.emit('doDownload', 1, groupCount, taskNum); + }); + + }); + + let downloadCheckpoint; + let partSize = parseInt(param.PartSize); + partSize = isNaN(partSize) ? 5 * 1024 * 1024 : (partSize > 0 ? partSize : 5 * 1024 * 1024); + let partCount = objectSize % partSize === 0 ? Math.floor(objectSize / partSize) : Math.floor(objectSize / partSize) + 1; + if(_log.isLevelEnabled('debug')){ + _log.runLog('debug', funcName, 'Total parts count ' + partCount); + } + downloadCheckpoint = {bucketName: bucket, objectKey: key, downloadFile : downloadFile, partSize : partSize, partCount : partCount}; + downloadCheckpoint.versionId = param.VersionId; + downloadCheckpoint.ifMatch = param.IfMatch; + downloadCheckpoint.ifModifiedSince = param.IfModifiedSince; + downloadCheckpoint.ifNoneMatch = param.IfNoneMatch; + downloadCheckpoint.ifUnmodifiedSince = param.IfUnmodifiedSince; + downloadCheckpoint.sseC = param.SseC; + downloadCheckpoint.sseCKey = param.SseCKey; + downloadCheckpoint.md5 = calculateDownloadCheckpointMD5(downloadCheckpoint); + downloadCheckpoint.objectStatus = {objectSize : objectSize, lastModified : objestStat.InterfaceResult.LastModified, etag: objestStat.InterfaceResult.ETag}; + + if(checkpointFile){ + if(!fs.existsSync(checkpointFile)){// call downloadFile first time + if(fs.existsSync(downloadTempFile)){ + try{ + fs.unlinkSync(downloadTempFile); + }catch(e){ + _callback('DeleteTempFileError', e); + return; + } + } + fs.writeFile(checkpointFile, JSON.stringify(downloadCheckpoint), function(err){ + if(err){ + _callback('WriteCheckpointFileError',err); + return; + } + eventEmitter.emit('start to downloadFile', downloadCheckpoint); + }); + }else{ + fs.readFile(checkpointFile, function(err, data){ + if(err){ + fs.unlink(checkpointFile, function(){}); + fs.unlink(downloadTempFile, function(){}); + _callback('ReadCheckpointFileError',err); + return; + } + try{ + downloadCheckpoint = JSON.parse(data); + }catch(e){ + fs.unlink(checkpointFile, function(){}); + fs.unlink(downloadTempFile, function(){}); + _callback('ParseCheckpointFileError', e); + return; + } + // check if temp file is valid + let verifyTempFileStatus = function(tempFileStatus){ + if(!tempFileStatus){ + return true; + } + if(!fs.existsSync(downloadTempFile)){ + return false; + } + return true; + // Do not verify the tempFileStatus so as to support program crash situation +// let fstat = fs.statSync(downloadTempFile); +// return tempFileStatus.fileSize === fstat.size && tempFileStatus.lastModified === fstat.mtime.toUTCString(); + }; + //verify + if(!downloadCheckpoint || downloadCheckpoint.bucketName !== bucket || downloadCheckpoint.objectKey !== key || downloadCheckpoint.downloadFile !== downloadFile || + !downloadCheckpoint.objectStatus || downloadCheckpoint.objectStatus.objectSize !== objectSize || downloadCheckpoint.objectStatus.lastModified !== objestStat.InterfaceResult.LastModified || + downloadCheckpoint.objectStatus.etag !== objestStat.InterfaceResult.ETag || !verifyTempFileStatus(downloadCheckpoint.tempFileStatus) || downloadCheckpoint.md5 !== calculateDownloadCheckpointMD5(downloadCheckpoint)){ + fs.unlink(checkpointFile, function(){}); + fs.unlink(downloadTempFile, function(){}); + _callback('CheckpointFileError', 'CheckpointFile is invalid!'); + return; + } + eventEmitter.emit('start to downloadFile', downloadCheckpoint); + }); + } + }else{ + if(fs.existsSync(downloadTempFile)){ + try{ + fs.unlinkSync(downloadTempFile); + }catch(e){ + _callback('DeleteTempFileError', e); + return; + } + } + eventEmitter.emit('start to downloadFile', downloadCheckpoint); + } + }); +}; + +function isFunction(obj){ + return Object.prototype.toString.call(obj) === '[object Function]'; +} + +for(let key in ObsClient.prototype){ + let current = ObsClient.prototype[key]; + ObsClient.prototype[key] = function(param, callback){ + if(isFunction(param)){ + current.call(this, null, param); + return; + } + if(isFunction(callback)){ + current.call(this, param, callback); + }else{ + let that = this; + return new Promise(function(resolve, reject) { + current.call(that, param, function(err, result){ + if(err){ + reject(err); + return; + } + resolve(result); + }); + }); + } + }; +} + +ObsClient.prototype.close = function(){ + if(this.util){ + this.util.close(); + delete this.util; + } +}; + +ObsClient.prototype.exec = function(funcName, param, callback){ + var _log = this.log; + if(_log.isLevelEnabled('info')){ + _log.runLog('info', funcName, 'enter ' + funcName + '...' ); + } + var start = new Date().getTime(); + param = param || {}; + var _callback = function(err, msg){ + if(_log.isLevelEnabled('info')){ + _log.runLog('info', funcName, 'ObsClient cost ' + (new Date().getTime() - start) + ' ms'); + } + callback(err, msg); + }; + var opt = this.util.makeParam(funcName, param); + if('err' in opt){ + _callback(opt['err'], null); + return; + } + this.util.sendRequest(funcName, opt, _callback); +}; + +ObsClient.prototype.initLog = function(param){ + param = param || {}; + this.log.initLog(param.file_full_path, param.max_log_size, param.backups, param.level, param.log_to_console, param.name); + if(this.log.isLevelEnabled('warn')){ + var msg = ['[OBS SDK Version=' + this.util.obsSdkVersion]; + if(this.util.server){ + let port = this.util.port ? ':' + this.util.port : ''; + msg.push('Endpoint=' + (this.util.is_secure? 'https' : 'http') + '://' + this.util.server + port); + } + msg.push('Access Mode=' + (this.util.path_style ? 'Path' : 'Virtual Hosting') + ']'); + this.log.runLog('warn', 'init', msg.join('];[')); + } +}; + +ObsClient.prototype.factory = function(param){ + this.log = new LogUtil(); + this.util = new Utils(this.log); + param = param || {}; + this.util.initFactory(param.access_key_id, param.secret_access_key, param.is_secure, + param.server, param.path_style, param.signature, param.region, param.port, param.max_retry_count, + param.timeout, param.ssl_verify, param.long_conn_param, param.security_token); +}; + +ObsClient.prototype.refresh = function(access_key_id, secret_access_key, security_token){ + this.util.refresh(access_key_id, secret_access_key, security_token); +}; + +ObsClient.prototype.enums = enums; + +ObsClient.prototype.createV2SignedUrlSync = function(param){ + return this.util.createV2SignedUrlSync(param); +}; + +ObsClient.prototype.createV4SignedUrlSync = function(param){ + return this.util.createV4SignedUrlSync(param); +}; + + +ObsClient.prototype.createSignedUrlSync = function(param){ + return this.util.createSignedUrlSync(param); +}; + +ObsClient.prototype.createV4PostSignatureSync = function(param){ + return this.util.createV4PostSignatureSync(param); +}; + +ObsClient.prototype.createPostSignatureSync = function(param){ + return this.util.createPostSignatureSync(param); +}; + +for(let key in ObsClient.prototype){ + ObsClient.prototype[capitalize(key)] = ObsClient.prototype[key]; +} + +for(let key in ObsClient.prototype){ + let index = key.indexOf('Configuration'); + if(index > 0 && index + 'Configuration'.length === key.length){ + ObsClient.prototype[key.slice(0, index)] = ObsClient.prototype[key]; + } +} + +module.exports = ObsClient; + diff --git a/lib/obs-sdk-3.0.0/obsModel.js b/lib/obs-sdk-3.0.0/obsModel.js new file mode 100644 index 0000000..0558d5f --- /dev/null +++ b/lib/obs-sdk-3.0.0/obsModel.js @@ -0,0 +1,3247 @@ +'use strict'; + +const owner = { + 'type' : 'object', + 'location' : 'xml', + 'sentAs' : 'Owner', + 'parameters' : { + 'ID' : { + 'sentAs' : 'ID', + } + } +}; + +const initiator = { + 'type' : 'object', + 'location' : 'xml', + 'sentAs' : 'Initiator', + 'parameters' : { + 'ID' : { + 'sentAs' : 'ID', + }, + }, +}; +const commonPrefixes = { + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'CommonPrefixes', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Prefix' : { + 'sentAs' : 'Prefix', + }, + } + } +}; + +const grants = { + 'type' : 'array', + 'location' : 'xml', + 'wrapper' : 'AccessControlList', + 'sentAs' : 'Grant', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Grantee' : { + 'type' : 'object', + 'sentAs' : 'Grantee', + 'parameters' : { + 'Type' : { + 'type' : 'ignore', + }, + 'ID' : { + 'sentAs' : 'ID', + }, + 'URI' : { + 'sentAs' : 'Canned', + 'type' : 'adapter' + } + }, + }, + 'Permission' : { + 'sentAs' : 'Permission', + }, + 'Delivered' :{ + 'sentAs' : 'Delivered', + } + }, + }, +}; + +const loggingEnabled = { + 'type' : 'object', + 'location' : 'xml', + 'sentAs' : 'LoggingEnabled', + 'parameters' : { + 'TargetBucket' : { + 'sentAs' : 'TargetBucket', + }, + 'TargetPrefix' : { + 'sentAs' : 'TargetPrefix', + }, + 'TargetGrants' : { + 'type' : 'array', + 'wrapper' : 'TargetGrants', + 'sentAs' : 'Grant', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Grantee' : { + 'type' : 'object', + 'sentAs' : 'Grantee', + 'parameters' : { + 'Type' : { + 'type' : 'ignore', + }, + 'ID' : { + 'sentAs' : 'ID', + }, + 'URI' : { + 'sentAs' : 'Canned', + 'type' : 'adapter' + } + }, + }, + 'Permission' : { + 'sentAs' : 'Permission', + }, + }, + }, + }, + }, +}; + +const rules = { + 'required' : true, + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Rule', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'ID' : { + 'sentAs' : 'ID', + }, + 'Prefix' : { + 'sentAs' : 'Prefix', + }, + 'Status' : { + 'sentAs' : 'Status', + }, + 'Transitions' : { + 'type' : 'array', + 'sentAs' : 'Transition', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'StorageClass' :{ + 'sentAs' : 'StorageClass', + 'type' : 'adapter' + }, + 'Date' : { + 'sentAs' : 'Date', + }, + 'Days' : { + 'type' : 'number', + 'sentAs' : 'Days' + } + } + } + }, + 'Expiration' : { + 'type' : 'object', + 'sentAs' : 'Expiration', + 'parameters' : { + 'Date' : { + 'sentAs' : 'Date', + }, + 'Days' : { + 'type' : 'number', + 'sentAs' : 'Days' + }, + }, + }, + 'NoncurrentVersionTransitions' :{ + 'type' : 'array', + 'sentAs' : 'NoncurrentVersionTransition', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'StorageClass' :{ + 'sentAs' : 'StorageClass', + 'type' : 'adapter' + }, + 'NoncurrentDays' : { + 'type' : 'number', + 'sentAs' : 'NoncurrentDays' + } + } + } + }, + 'NoncurrentVersionExpiration' : { + 'type' : 'object', + 'sentAs' : 'NoncurrentVersionExpiration', + 'parameters' : { + 'NoncurrentDays' : { + 'type' : 'number', + 'sentAs' : 'NoncurrentDays', + }, + }, + } + }, + }, +}; + +const redirectAllRequestsTo = { + 'type' : 'object', + 'location' : 'xml', + 'sentAs' : 'RedirectAllRequestsTo', + 'parameters' : { + 'HostName' : { + 'sentAs' : 'HostName', + }, + 'Protocol' : { + 'sentAs' : 'Protocol', + }, + } +}; + +const routingRules = { + 'type' : 'array', + 'wrapper' : 'RoutingRules', + 'location' : 'xml', + 'sentAs' : 'RoutingRule', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Condition' : { + 'type' : 'object', + 'sentAs' : 'Condition', + 'parameters' : { + 'HttpErrorCodeReturnedEquals' : { + 'sentAs' : 'HttpErrorCodeReturnedEquals', + }, + 'KeyPrefixEquals' : { + 'sentAs' : 'KeyPrefixEquals', + }, + }, + }, + 'Redirect' : { + 'type' : 'object', + 'sentAs' : 'Redirect', + 'parameters' : { + 'HostName' : { + 'sentAs' : 'HostName', + }, + 'HttpRedirectCode' : { + 'sentAs' : 'HttpRedirectCode', + }, + 'Protocol' : { + 'sentAs' : 'Protocol', + }, + 'ReplaceKeyPrefixWith' : { + 'sentAs' : 'ReplaceKeyPrefixWith', + }, + 'ReplaceKeyWith' : { + 'sentAs' : 'ReplaceKeyWith', + } + } + }, + }, + }, +}; + +const indexDocument = { + 'type' : 'object', + 'location' : 'xml', + 'sentAs' : 'IndexDocument', + 'parameters' : { + 'Suffix' : { + 'sentAs' : 'Suffix', + }, + } +}; + +const errorDocument = { + 'type' : 'object', + 'location' : 'xml', + 'sentAs' : 'ErrorDocument', + 'parameters' : { + 'Key' : { + 'sentAs' : 'Key', + }, + } +}; + +const corsRule = { + 'required' : true, + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'CORSRule', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'ID' : { + 'sentAs' : 'ID', + }, + 'AllowedMethod' : { + 'type' : 'array', + 'sentAs' : 'AllowedMethod', + 'items' : { + 'type' : 'string', + }, + }, + 'AllowedOrigin' : { + 'type' : 'array', + 'sentAs' : 'AllowedOrigin', + 'items' : { + 'type' : 'string', + }, + }, + 'AllowedHeader' : { + 'type' : 'array', + 'sentAs' : 'AllowedHeader', + 'items' : { + 'type' : 'string', + }, + }, + 'MaxAgeSeconds' : { + 'type' : 'number', + 'sentAs' : 'MaxAgeSeconds', + }, + 'ExposeHeader' : { + 'type' : 'array', + 'sentAs' : 'ExposeHeader', + 'items' : { + 'type' : 'string', + }, + }, + }, + }, +}; + +const topicConfiguration = { + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'TopicConfiguration', + 'items' : { + 'type' : 'object', + 'location' : 'xml', + 'parameters' : { + 'ID' : { + 'sentAs' : 'Id' + }, + 'Filter' : { + 'type' : 'object', + 'parameters' : { + 'FilterRules' : { + 'wrapper' : 'Object', + 'type' : 'array', + 'sentAs' : 'FilterRule', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Name' : {}, + 'Value' : {} + } + } + } + } + }, + 'Topic' : {}, + + 'Event' : { + 'type' : 'array', + 'items' : { + 'type' : 'adapter', + } + } + } + } +}; + +const tagSet = { + 'required' : true, + 'type' : 'array', + 'location' : 'xml', + 'wrapper' : 'TagSet', + 'sentAs' : 'Tag', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Key' : { + 'sentAs' : 'Key', + }, + 'Value' : { + 'sentAs' : 'Value', + } + } + } +}; + +const replicationRules = { + 'required' : true, + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Rule', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'ID' : { + 'sentAs' : 'ID', + }, + 'Prefix' : { + 'sentAs' : 'Prefix', + }, + 'Status' : { + 'sentAs' : 'Status', + }, + 'Destination' :{ + 'type' : 'object', + 'sentAs' : 'Destination', + 'parameters' :{ + 'Bucket' : { + 'sentAs' : 'Bucket', + 'type' : 'adapter' + }, + 'StorageClass' :{ + 'sentAs' : 'StorageClass', + 'type' : 'adapter' + } + } + } + }, + } +}; + +const operations = { + 'CreateBucket' : { + 'httpMethod' : 'PUT', + 'data' : { + 'xmlRoot' : 'CreateBucketConfiguration', + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'ACL' : { + 'location' : 'header', + 'sentAs' : 'acl', + 'withPrefix' : true, + 'type' : 'adapter' + }, + 'StorageClass' : { + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true, + 'type' : 'adapter' + }, + 'Location' : { + 'location' : 'xml', + 'sentAs' : 'Location' + }, + 'GrantRead' : { + 'location' : 'header', + 'sentAs' : 'grant-read', + 'withPrefix' : true, + }, + + 'GrantWrite' : { + 'location' : 'header', + 'sentAs' : 'grant-write', + 'withPrefix' : true, + }, + + 'GrantReadAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-read-acp', + 'withPrefix' : true, + }, + + 'GrantWriteAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-write-acp', + 'withPrefix' : true, + }, + + 'GrantFullControl' : { + 'location' : 'header', + 'sentAs' : 'grant-full-control', + 'withPrefix' : true, + }, + + 'GrantReadDelivered' : { + 'location' : 'header', + 'sentAs' : 'grant-read-delivered', + 'withPrefix' : true, + }, + + 'GrantFullControlDelivered' : { + 'location' : 'header', + 'sentAs' : 'grant-full-control-delivered', + 'withPrefix' : true, + } + } + }, + + 'ListBuckets' : { + 'httpMethod' : 'GET', + 'parameters' : { + } + }, + + 'ListBucketsOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'ListAllMyBucketsResult', + }, + 'parameters' : { + 'Owner' : { + 'type' : 'object', + 'location' : 'xml', + 'sentAs' : 'Owner', + 'parameters' : { + 'ID' : { + 'sentAs' : 'ID', + }, + }, + + }, + 'Buckets' : { + 'type' : 'array', + 'location' : 'xml', + 'wrapper' : 'Buckets', + 'sentAs' : 'Bucket', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'BucketName' : { + 'sentAs' : 'Name', + }, + 'CreationDate' : { + 'type' : 'date', + 'sentAs' : 'CreationDate' + }, + 'Location' : { + 'sentAs' : 'Location' + } + }, + }, + }, + }, + }, + + 'HeadBucket' : { + 'httpMethod' : 'HEAD', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + + + 'GetBucketMetadata' : { + 'httpMethod' : 'HEAD', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + + 'Origin' : { + 'location' : 'header', + 'sentAs' : 'Origin' + }, + + 'RequestHeader' : { + 'location' : 'header', + 'sentAs' : 'Access-Control-Request-Headers' + } + }, + }, + + 'GetBucketMetadataOutput' : { + 'parameters' : { + 'StorageClass' : { + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true + }, + 'ObsVersion' : { + 'location' : 'header', + 'sentAs' : 'version', + 'withPrefix' : true + }, + 'Location' : { + 'location' : 'header', + 'sentAs' : 'bucket-location', + 'withPrefix' : true + }, + 'AllowOrigin' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-origin' + }, + 'MaxAgeSeconds' : { + 'location' : 'header', + 'sentAs' : 'access-control-max-age' + }, + 'ExposeHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-expose-headers' + }, + 'AllowMethod' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-methods' + }, + 'AllowHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-headers' + } + } + }, + + 'DeleteBucket' : { + 'httpMethod' : 'DELETE', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + + 'ListObjects' : { + 'httpMethod' : 'GET', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Prefix' : { + 'location' : 'urlPath', + 'sentAs' : 'prefix', + }, + 'Marker' : { + 'location' : 'urlPath', + 'sentAs' : 'marker', + }, + 'MaxKeys' : { + 'type' : 'number', + 'location' : 'urlPath', + 'sentAs' : 'max-keys', + }, + 'Delimiter' : { + 'location' : 'urlPath', + 'sentAs' : 'delimiter', + }, + }, + }, + + 'ListObjectsOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'ListBucketResult', + }, + 'parameters' : { + 'Location' : { + 'location' : 'header', + 'sentAs' : 'bucket-location', + 'withPrefix' : true + }, + 'Bucket' : { + 'location' : 'xml', + 'sentAs' : 'Name', + }, + 'Delimiter' : { + 'location' : 'xml', + 'sentAs' : 'Delimiter', + }, + 'IsTruncated' : { + 'location' : 'xml', + 'sentAs' : 'IsTruncated', + }, + 'Prefix' : { + 'location' : 'xml', + 'sentAs' : 'Prefix', + }, + 'Marker' : { + 'location' : 'xml', + 'sentAs' : 'Marker', + }, + 'NextMarker' : { + 'location' : 'xml', + 'sentAs' : 'NextMarker', + }, + 'MaxKeys' : { + 'location' : 'xml', + 'sentAs' : 'MaxKeys', + }, + 'Contents' : { + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Contents', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Key' : { + 'sentAs' : 'Key', + }, + 'LastModified' : { + 'type' : 'date', + 'sentAs' : 'LastModified', + }, + 'ETag' : { + 'sentAs' : 'ETag', + }, + 'Size' : { + 'sentAs' : 'Size', + }, + 'Type' :{ + 'sentAs' : 'Type' + }, + 'StorageClass' : { + 'sentAs' : 'StorageClass', + }, + 'Owner' : owner + }, + }, + + }, + 'CommonPrefixes' : commonPrefixes + }, + }, + + 'ListVersions' : { + 'httpMethod' : 'GET', + 'urlPath' : 'versions', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Prefix' : { + 'location' : 'urlPath', + 'sentAs' : 'prefix', + }, + 'KeyMarker' : { + 'location' : 'urlPath', + 'sentAs' : 'key-marker', + }, + 'MaxKeys' : { + 'type' : 'number', + 'location' : 'urlPath', + 'sentAs' : 'max-keys', + }, + 'Delimiter' : { + 'location' : 'urlPath', + 'sentAs' : 'delimiter', + }, + 'VersionIdMarker' : { + 'location' : 'urlPath', + 'sentAs' : 'version-id-marker', + }, + }, + }, + 'ListVersionsOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'ListVersionsResult', + }, + 'parameters' : { + 'Location' : { + 'location' : 'header', + 'sentAs' : 'bucket-location', + 'withPrefix' : true + }, + 'Bucket' : { + 'location' : 'xml', + 'sentAs' : 'Name', + }, + 'Prefix' : { + 'location' : 'xml', + 'sentAs' : 'Prefix', + }, + 'Delimiter' : { + 'location' : 'xml', + 'sentAs' : 'Delimiter', + }, + 'KeyMarker' : { + 'location' : 'xml', + 'sentAs' : 'KeyMarker', + }, + 'VersionIdMarker' : { + 'location' : 'xml', + 'sentAs' : 'VersionIdMarker', + }, + 'NextKeyMarker' : { + 'location' : 'xml', + 'sentAs' : 'NextKeyMarker', + }, + 'NextVersionIdMarker' : { + 'location' : 'xml', + 'sentAs' : 'NextVersionIdMarker', + }, + 'MaxKeys' : { + 'location' : 'xml', + 'sentAs' : 'MaxKeys', + }, + 'IsTruncated' : { + 'location' : 'xml', + 'sentAs' : 'IsTruncated', + }, + 'Versions' : { + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Version', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Key' : { + 'sentAs' : 'Key', + }, + 'VersionId' : { + 'sentAs' : 'VersionId', + }, + 'IsLatest' : { + 'sentAs' : 'IsLatest', + }, + 'LastModified' : { + 'type' : 'date', + 'sentAs' : 'LastModified', + }, + 'ETag' : { + 'sentAs' : 'ETag', + }, + 'Size' : { + 'sentAs' : 'Size', + }, + 'Type' :{ + 'sentAs' : 'Type' + }, + 'Owner' : owner, + 'StorageClass' : { + 'sentAs' : 'StorageClass', + } + } + }, + }, + 'DeleteMarkers' : { + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'DeleteMarker', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Key' : { + 'sentAs' : 'Key', + }, + 'VersionId' : { + 'sentAs' : 'VersionId', + }, + 'IsLatest' : { + 'sentAs' : 'IsLatest', + }, + 'LastModified' : { + 'type' : 'date', + 'sentAs' : 'LastModified', + }, + 'Owner' : owner + } + }, + }, + 'CommonPrefixes' : commonPrefixes + }, + }, + + 'GetBucketLocation' : { + 'httpMethod' : 'GET', + 'urlPath' : 'location', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + + 'GetBucketLocationOutput' : { + 'data' : { + 'type' : 'xml' + }, + 'parameters' : { + 'Location' : { + 'location' : 'xml', + 'sentAs' : 'Location' + }, + }, + }, + + 'GetBucketStorageInfo' : { + 'httpMethod' : 'GET', + 'urlPath' : 'storageinfo', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + 'GetBucketStorageInfoOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'GetBucketStorageInfoResult', + }, + 'parameters' : { + 'Size' : { + 'location' : 'xml', + 'sentAs' : 'Size', + }, + 'ObjectNumber' : { + 'location' : 'xml', + 'sentAs' : 'ObjectNumber', + }, + }, + }, + + 'SetBucketQuota' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'quota', + 'data' : { + 'xmlRoot' : 'Quota', + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'StorageQuota' : { + 'required' : true, + 'location' : 'xml', + 'sentAs' : 'StorageQuota', + }, + }, + }, + + 'GetBucketQuota' : { + 'httpMethod' : 'GET', + 'urlPath' : 'quota', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + + }, + }, + 'GetBucketQuotaOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'Quota', + }, + 'parameters' : { + 'StorageQuota' : { + 'location' : 'xml', + 'sentAs' : 'StorageQuota', + }, + }, + }, + + 'SetBucketAcl' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'acl', + 'data' : { + 'xmlRoot' : 'AccessControlPolicy', + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'ACL' : { + 'location' : 'header', + 'sentAs' : 'acl', + 'withPrefix' : true, + 'type' : 'adapter' + }, + 'Owner' : owner, + 'Grants' : grants + }, + }, + + 'GetBucketAcl' : { + 'httpMethod' : 'GET', + 'urlPath' : 'acl', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + 'GetBucketAclOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'AccessControlPolicy', + }, + 'parameters' : { + 'Owner' : owner, + 'Grants' : grants + } + }, + + 'SetBucketLoggingConfiguration' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'logging', + 'data' : { + 'xmlRoot' : 'BucketLoggingStatus', + 'xmlAllowEmpty' : true + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Agency' :{ + 'location' : 'xml', + 'sentAs' : 'Agency', + }, + 'LoggingEnabled' : loggingEnabled, + }, + }, + + 'GetBucketLoggingConfiguration' : { + 'httpMethod' : 'GET', + 'urlPath' : 'logging', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + 'GetBucketLoggingConfigurationOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'BucketLoggingStatus', + }, + 'parameters' : { + 'Agency' :{ + 'location' : 'xml', + 'sentAs' : 'Agency' + }, + 'LoggingEnabled' : loggingEnabled, + }, + }, + + 'SetBucketPolicy' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'policy', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Policy' : { + 'required' : true, + 'location' : 'body', + }, + }, + }, + + 'GetBucketPolicy' : { + 'httpMethod' : 'GET', + 'urlPath' : 'policy', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + 'GetBucketPolicyOutput' : { + 'data' : { + 'type' : 'body', + }, + 'parameters' : { + 'Policy' : { + 'location' : 'body', + }, + }, + }, + 'DeleteBucketPolicy' : { + 'httpMethod' : 'DELETE', + 'urlPath' : 'policy', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + + 'SetBucketLifecycleConfiguration' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'lifecycle', + 'data' : { + 'xmlRoot' : 'LifecycleConfiguration', + 'md5' : true + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Rules' : rules + }, + }, + + 'GetBucketLifecycleConfiguration' : { + 'httpMethod' : 'GET', + 'urlPath' : 'lifecycle', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + 'GetBucketLifecycleConfigurationOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'LifecycleConfiguration', + }, + 'parameters' : { + 'Rules' : rules + }, + }, + + 'DeleteBucketLifecycleConfiguration' : { + 'httpMethod' : 'DELETE', + 'urlPath' : 'lifecycle', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + + 'SetBucketWebsiteConfiguration' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'website', + 'data' : { + 'xmlRoot' : 'WebsiteConfiguration', + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'RedirectAllRequestsTo' : redirectAllRequestsTo, + 'IndexDocument' : indexDocument, + 'ErrorDocument' : errorDocument, + 'RoutingRules' : routingRules + }, + }, + + 'GetBucketWebsiteConfiguration' : { + 'httpMethod' : 'GET', + 'urlPath' : 'website', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + 'GetBucketWebsiteConfigurationOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'WebsiteConfiguration', + }, + 'parameters' : { + 'RedirectAllRequestsTo' : redirectAllRequestsTo, + 'IndexDocument' : indexDocument, + 'ErrorDocument' : errorDocument, + 'RoutingRules' : routingRules, + }, + }, + 'DeleteBucketWebsiteConfiguration' : { + 'httpMethod' : 'DELETE', + 'urlPath' : 'website', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + + 'SetBucketVersioningConfiguration' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'versioning', + 'data' : { + 'xmlRoot' : 'VersioningConfiguration', + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'VersionStatus' : { + 'required' : true, + 'location' : 'xml', + 'sentAs' : 'Status', + }, + }, + }, + + 'GetBucketVersioningConfiguration' : { + 'httpMethod' : 'GET', + 'urlPath' : 'versioning', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + 'GetBucketVersioningConfigurationOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'VersioningConfiguration', + }, + 'parameters' : { + 'VersionStatus' : { + 'location' : 'xml', + 'sentAs' : 'Status', + }, + }, + }, + + 'SetBucketCors' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'cors', + 'data' : { + 'xmlRoot' : 'CORSConfiguration', + 'md5' : true + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'CorsRules' : corsRule + }, + }, + 'GetBucketCors' : { + 'httpMethod' : 'GET', + 'urlPath' : 'cors', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + 'GetBucketCorsOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'CORSConfiguration', + }, + 'parameters' : { + 'CorsRules' : corsRule + }, + }, + 'DeleteBucketCors' : { + 'httpMethod' : 'DELETE', + 'urlPath' : 'cors', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + }, + }, + + 'SetBucketNotification' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'notification', + 'data' : { + 'xmlRoot' : 'NotificationConfiguration', + 'xmlAllowEmpty' : true + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri' + }, + 'TopicConfigurations' : topicConfiguration + } + }, + + + 'GetBucketNotification' : { + 'httpMethod' : 'GET', + 'urlPath' : 'notification', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + } + }, + + 'GetBucketNotificationOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'NotificationConfiguration', + }, + 'parameters' : { + 'TopicConfigurations' : topicConfiguration + }, + }, + + 'OptionsBucket' : { + 'httpMethod' : 'OPTIONS', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Origin' : { + 'required' : true, + 'location' : 'header', + 'sentAs' : 'Origin', + }, + 'AccessControlRequestMethods' : { + 'required' : true, + 'type' : 'array', + 'location' : 'header', + 'sentAs' : 'Access-Control-Request-Method', + 'items' : { + 'type' : 'string', + }, + }, + 'AccessControlRequestHeaders' : { + 'type' : 'array', + 'location' : 'header', + 'sentAs' : 'Access-Control-Request-Headers', + 'items' : { + 'type' : 'string', + }, + }, + }, + }, + 'OptionsBucketOutput' : { + 'parameters' : { + 'AllowOrigin' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-origin', + }, + 'AllowHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-headers', + }, + 'AllowMethod' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-methods', + }, + 'ExposeHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-expose-headers', + }, + 'MaxAgeSeconds' : { + 'location' : 'header', + 'sentAs' : 'access-control-max-age', + }, + }, + }, + + 'SetBucketTagging' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'tagging', + 'data' : { + 'xmlRoot' : 'Tagging', + 'md5' : true + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri' + }, + 'Tags' : tagSet + } + }, + + 'GetBucketTagging' : { + 'httpMethod' : 'GET', + 'urlPath' : 'tagging', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + } + }, + + 'GetBucketTaggingOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'Tagging', + }, + 'parameters' : { + 'Tags' : tagSet + } + }, + + 'DeleteBucketTagging' : { + 'httpMethod' : 'DELETE', + 'urlPath' : 'tagging', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + } + }, + + 'SetBucketStoragePolicy' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'storageClass', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'StorageClass' :{ + 'required' : true, + 'location' : 'xml', + 'type' : 'adapter', + 'sentAs' : 'StorageClass' + } + } + }, + + 'GetBucketStoragePolicy' :{ + 'httpMethod' : 'GET', + 'urlPath' : 'storageClass', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + } + }, + + 'GetBucketStoragePolicyOutput' :{ + 'data' : { + 'type' : 'xml', + }, + 'parameters' : { + 'StorageClass' : { + 'location' : 'xml', + 'type' : 'string', + 'sentAs' : 'StorageClass' + } + } + }, + + 'SetBucketReplication' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'replication', + 'data' : { + 'xmlRoot' : 'ReplicationConfiguration', + 'md5' : true + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri' + }, + 'Agency' :{ + 'location' : 'xml', + 'sentAs' : 'Agency' + }, + 'Rules' : replicationRules + } + }, + + 'GetBucketReplication' : { + 'httpMethod' : 'GET', + 'urlPath' : 'replication', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + } + }, + + 'GetBucketReplicationOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'ReplicationConfiguration', + }, + 'parameters' : { + 'Agency' :{ + 'location' : 'xml', + 'sentAs' : 'Agency' + }, + 'Rules' : replicationRules + } + }, + + 'DeleteBucketReplication' : { + 'httpMethod' : 'DELETE', + 'urlPath' : 'replication', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + } + }, + + 'PutObject' : { + 'httpMethod' : 'PUT', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'ContentMD5' : { + 'location' : 'header', + 'sentAs' : 'Content-MD5', + }, + 'ContentType' : { + 'location' : 'header', + 'sentAs' : 'Content-Type' + }, + 'Offset' : { + 'type' : 'plain' + }, + 'ContentLength' :{ + 'location' : 'header', + 'sentAs' : 'Content-Length', + 'type' : 'plain' + }, + 'ACL' : { + 'location' : 'header', + 'sentAs' : 'acl', + 'withPrefix' : true + }, + 'GrantRead' : { + 'location' : 'header', + 'sentAs' : 'grant-read', + 'withPrefix' : true, + }, + 'GrantReadAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-read-acp', + 'withPrefix' : true, + }, + 'GrantWriteAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-write-acp', + 'withPrefix' : true, + }, + 'GrantFullControl' : { + 'location' : 'header', + 'sentAs' : 'grant-full-control', + 'withPrefix' : true, + }, + 'StorageClass' : { + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true, + }, + 'Metadata' : { + 'type' : 'object', + 'location' : 'header', + 'sentAs' : 'meta-', + 'withPrefix' : true, + }, + 'WebsiteRedirectLocation' : { + 'location' : 'header', + 'sentAs' : 'website-redirect-location', + 'withPrefix' : true, + }, + 'Expires' : { + 'location' : 'header', + 'sentAs' : 'expires', + 'type' : 'number', + 'withPrefix' : true, + }, + 'SuccessActionRedirect':{ + 'location' : 'header', + 'sentAs' : 'success-action-redirect' + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true, + 'type' : 'adapter' + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true, + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true, + }, + 'SseCKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true, + }, + 'Body' : { + 'location' : 'body', + }, + 'SourceFile' : { + 'type' : 'srcFile', + } + }, + }, + 'PutObjectOutput' : { + 'parameters' : { + 'ETag' : { + 'location' : 'header', + 'sentAs' : 'etag', + }, + 'VersionId' : { + 'location' : 'header', + 'sentAs' : 'version-id', + 'withPrefix' : true, + }, + 'StorageClass' :{ + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true, + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true, + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true, + }, + 'SseCKeyMd5' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key-MD5', + 'withPrefix' : true, + } + }, + }, + + 'AppendObject' : { + 'httpMethod' : 'POST', + 'urlPath' : 'append', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'Position' : { + 'location' : 'urlPath', + 'sentAs' : 'position', + 'type' : 'number' + }, + 'ContentMD5' : { + 'location' : 'header', + 'sentAs' : 'Content-MD5', + }, + 'ContentType' : { + 'location' : 'header', + 'sentAs' : 'Content-Type' + }, + 'Offset' : { + 'type' : 'plain' + }, + 'ContentLength' :{ + 'location' : 'header', + 'sentAs' : 'Content-Length', + 'type' : 'plain' + }, + 'ACL' : { + 'location' : 'header', + 'sentAs' : 'acl', + 'withPrefix' : true + }, + 'GrantRead' : { + 'location' : 'header', + 'sentAs' : 'grant-read', + 'withPrefix' : true, + }, + 'GrantReadAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-read-acp', + 'withPrefix' : true, + }, + 'GrantWriteAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-write-acp', + 'withPrefix' : true, + }, + 'GrantFullControl' : { + 'location' : 'header', + 'sentAs' : 'grant-full-control', + 'withPrefix' : true, + }, + 'StorageClass' : { + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true, + }, + 'Metadata' : { + 'type' : 'object', + 'location' : 'header', + 'sentAs' : 'meta-', + 'withPrefix' : true, + }, + 'WebsiteRedirectLocation' : { + 'location' : 'header', + 'sentAs' : 'website-redirect-location', + 'withPrefix' : true, + }, + 'Expires' : { + 'location' : 'header', + 'sentAs' : 'expires', + 'type' : 'number', + 'withPrefix' : true, + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true, + 'type' : 'adapter' + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true, + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true, + }, + 'SseCKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true, + }, + 'Body' : { + 'location' : 'body', + }, + 'SourceFile' : { + 'type' : 'srcFile', + } + }, + }, + 'AppendObjectOutput' : { + 'parameters' : { + 'ETag' : { + 'location' : 'header', + 'sentAs' : 'etag', + }, + 'NextPosition' : { + 'location' : 'header', + 'sentAs' : 'next-append-position', + 'withPrefix' : true, + }, + 'StorageClass' :{ + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true, + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true, + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true, + }, + 'SseCKeyMd5' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key-MD5', + 'withPrefix' : true, + } + }, + }, + + 'GetObject' : { + 'httpMethod' : 'GET', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'ResponseCacheControl' : { + 'location' : 'urlPath', + 'sentAs' : 'response-cache-control', + }, + 'ResponseContentDisposition' : { + 'location' : 'urlPath', + 'sentAs' : 'response-content-disposition', + }, + 'ResponseContentEncoding' : { + 'location' : 'urlPath', + 'sentAs' : 'response-content-encoding', + }, + 'ResponseContentLanguage' : { + 'location' : 'urlPath', + 'sentAs' : 'response-content-language', + }, + 'ResponseContentType' : { + 'location' : 'urlPath', + 'sentAs' : 'response-content-type', + }, + 'ResponseExpires' : { + 'location' : 'urlPath', + 'sentAs' : 'response-expires', + }, + 'VersionId' : { + 'location' : 'urlPath', + 'sentAs' : 'versionId', + }, + 'ImageProcess' : { + 'location' : 'urlPath', + 'sentAs' : 'x-image-process', + }, + 'IfMatch' : { + 'location' : 'header', + 'sentAs' : 'If-Match', + }, + 'IfModifiedSince' : { + 'location' : 'header', + 'sentAs' : 'If-Modified-Since', + }, + 'IfNoneMatch' : { + 'location' : 'header', + 'sentAs' : 'If-None-Match', + }, + 'IfUnmodifiedSince' : { + 'location' : 'header', + 'sentAs' : 'If-Unmodified-Since', + }, + 'Range' : { + 'location' : 'header', + 'sentAs' : 'Range', + }, + 'Origin' :{ + 'location' : 'header', + 'sentAs' : 'Origin' + }, + 'RequestHeader' : { + 'location' : 'header', + 'sentAs' : 'Access-Control-Request-Headers' + }, + 'SaveAsFile' : { + 'type' : 'dstFile', + }, + 'SaveAsStream' : { + 'type' : 'plain' + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true + } + } + }, + 'GetObjectOutput' : { + 'data' : { + 'type' : 'body' + }, + 'parameters' : { + 'Content' : { + 'location' : 'body', + }, + 'Expiration' : { + 'location' : 'header', + 'sentAs' : 'expiration', + 'withPrefix' : true + }, + 'ETag' : { + 'location' : 'header', + 'sentAs' : 'etag', + }, + 'CacheControl' : { + 'location' : 'header', + 'sentAs' : 'Cache-Control', + }, + 'ContentDisposition' : { + 'location' : 'header', + 'sentAs' : 'Content-Disposition', + }, + 'ContentEncoding' : { + 'location' : 'header', + 'sentAs' : 'Content-Encoding', + }, + 'ContentLanguage' : { + 'location' : 'header', + 'sentAs' : 'Content-Language', + }, + 'ContentType' : { + 'location' : 'header', + 'sentAs' : 'Content-Type', + }, + 'Expires' : { + 'location' : 'header', + 'sentAs' : 'Expires', + }, + 'VersionId' : { + 'location' : 'header', + 'sentAs' : 'version-id', + 'withPrefix' : true + }, + 'ContentLength' : { + 'location' : 'header', + 'sentAs' : 'Content-Length', + }, + 'DeleteMarker' : { + 'location' : 'header', + 'sentAs' : 'delete-marker', + 'withPrefix' : true + }, + 'LastModified' : { + 'type' : 'date', + 'location' : 'header', + 'sentAs' : 'Last-Modified', + }, + 'WebsiteRedirectLocation' : { + 'location' : 'header', + 'sentAs' : 'website-redirect-location', + 'withPrefix' : true + }, + 'StorageClass' : { + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true + }, + 'Restore' : { + 'location' : 'header', + 'sentAs' : 'restore', + 'withPrefix' : true + }, + 'AllowOrigin' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-origin' + }, + 'MaxAgeSeconds' : { + 'location' : 'header', + 'sentAs' : 'access-control-max-age' + }, + 'ExposeHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-expose-headers' + }, + 'AllowMethod' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-methods' + }, + 'AllowHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-headers' + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKeyMd5' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key-MD5', + 'withPrefix' : true + }, + 'Metadata' : { + 'location' : 'header', + 'type' : 'object', + 'sentAs' : 'meta-', + 'withPrefix' : true + } + }, + }, + 'CopyObject' : { + 'httpMethod' : 'PUT', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'ACL' : { + 'location' : 'header', + 'sentAs' : 'acl', + 'withPrefix' : true + }, + 'GrantRead' : { + 'location' : 'header', + 'sentAs' : 'grant-read', + 'withPrefix' : true, + }, + 'GrantReadAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-read-acp', + 'withPrefix' : true, + }, + 'GrantWriteAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-write-acp', + 'withPrefix' : true, + }, + 'GrantFullControl' : { + 'location' : 'header', + 'sentAs' : 'grant-full-control', + 'withPrefix' : true, + }, + 'StorageClass' : { + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true + }, + 'CopySource' : { + 'required' : true, + 'location' : 'header', + 'sentAs' : 'copy-source', + 'withPrefix' : true, + 'skipEncoding' : true + }, + 'CopySourceIfMatch' : { + 'location' : 'header', + 'sentAs' : 'copy-source-if-match', + 'withPrefix' : true + }, + 'CopySourceIfModifiedSince' : { + 'location' : 'header', + 'sentAs' : 'copy-source-if-modified-since', + 'withPrefix' : true + }, + 'CopySourceIfNoneMatch' : { + 'location' : 'header', + 'sentAs' : 'copy-source-if-none-match', + 'withPrefix' : true + }, + 'CopySourceIfUnmodifiedSince' : { + 'location' : 'header', + 'sentAs' : 'copy-source-if-unmodified-since', + 'withPrefix' : true + }, + 'ContentType' : { + 'location' : 'header', + 'sentAs' : 'Content-Type' + }, + 'ContentEncoding' : { + 'location' : 'header', + 'sentAs' : 'content-encoding' + }, + 'ContentLanguage' : { + 'location' : 'header', + 'sentAs' : 'content-language' + }, + 'ContentDisposition' : { + 'location' : 'header', + 'sentAs' : 'content-disposition' + }, + 'CacheControl' : { + 'location' : 'header', + 'sentAs' : 'cache-control' + }, + 'Expires' : { + 'location' : 'header', + 'sentAs' : 'expires' + }, + 'Metadata' : { + 'type' : 'object', + 'location' : 'header', + 'sentAs' : 'meta-', + 'withPrefix' : true + }, + 'MetadataDirective' : { + 'location' : 'header', + 'sentAs' : 'metadata-directive', + 'withPrefix' : true + }, + 'WebsiteRedirectLocation' : { + 'location' : 'header', + 'sentAs' : 'website-redirect-location', + 'withPrefix' : true + }, + 'SuccessActionRedirect':{ + 'location' : 'header', + 'sentAs' : 'success-action-redirect' + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true, + 'type' : 'adapter' + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true + }, + 'CopySourceSseC' :{ + 'location' : 'header', + 'sentAs' : 'copy-source-server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'CopySourceSseCKey' :{ + 'location' : 'header', + 'sentAs' : 'copy-source-server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true + }, + }, + }, + 'CopyObjectOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'CopyObjectResult', + }, + 'parameters' : { + 'VersionId' : { + 'location' : 'header', + 'sentAs' : 'version-id', + 'withPrefix' : true + }, + 'CopySourceVersionId' : { + 'location' : 'header', + 'sentAs' : 'copy-source-version-id', + 'withPrefix' : true + }, + 'ETag' : { + 'location' : 'xml', + 'sentAs' : 'ETag', + }, + 'LastModified' : { + 'type' : 'date', + 'location' : 'xml', + 'sentAs' : 'LastModified', + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKeyMd5' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key-MD5', + 'withPrefix' : true + } + }, + }, + + 'RestoreObject' : { + 'httpMethod' : 'POST', + 'urlPath' : 'restore', + 'data' : { + 'xmlRoot' : 'RestoreRequest', + 'md5' : true + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'VersionId' : { + 'location' : 'urlPath', + 'sentAs' : 'versionId', + }, + 'Days' : { + 'location' : 'xml', + 'sentAs' : 'Days' + }, + 'Tier' : { + 'wrapper' : 'GlacierJobParameters', + 'location' : 'xml', + 'sentAs' : 'Tier', + } + } + }, + + 'GetObjectMetadata' : { + 'httpMethod' : 'HEAD', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'VersionId' : { + 'location' : 'urlPath', + 'sentAs' : 'versionId', + }, + 'Origin' : { + 'location' : 'header', + 'sentAs' : 'Origin' + }, + 'RequestHeader' : { + 'location' : 'header', + 'sentAs' : 'Access-Control-Request-Headers' + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true + }, + }, + }, + + 'GetObjectMetadataOutput' : { + 'parameters' : { + 'Expiration' : { + 'location' : 'header', + 'sentAs' : 'expiration', + 'withPrefix' : true + }, + 'LastModified' : { + 'type' : 'date', + 'location' : 'header', + 'sentAs' : 'Last-Modified', + }, + 'ContentLength' : { + 'location' : 'header', + 'sentAs' : 'Content-Length', + }, + 'ContentType' :{ + 'location' : 'header', + 'sentAs' : 'Content-Type' + }, + 'ETag' : { + 'location' : 'header', + 'sentAs' : 'etag', + }, + 'VersionId' : { + 'location' : 'header', + 'sentAs' : 'version-id', + 'withPrefix' : true + }, + 'WebsiteRedirectLocation' : { + 'location' : 'header', + 'sentAs' : 'website-redirect-location', + 'withPrefix' : true + }, + 'StorageClass' : { + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true + }, + 'Restore' : { + 'location' : 'header', + 'sentAs' : 'restore', + 'withPrefix' : true + }, + 'ObjectType' :{ + 'location' : 'header', + 'sentAs' : 'object-type', + 'withPrefix' : true + }, + 'NextPosition' :{ + 'location' : 'header', + 'sentAs' : 'next-append-position', + 'withPrefix' : true + }, + 'AllowOrigin' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-origin' + }, + 'MaxAgeSeconds' : { + 'location' : 'header', + 'sentAs' : 'access-control-max-age' + }, + 'ExposeHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-expose-headers' + }, + 'AllowMethod' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-methods' + }, + 'AllowHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-headers' + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKeyMd5' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key-MD5', + 'withPrefix' : true + }, + 'Metadata' : { + 'location' : 'header', + 'type' : 'object', + 'sentAs' : 'meta-', + 'withPrefix' : true + } + }, + }, + + 'SetObjectAcl' : { + 'httpMethod' : 'PUT', + 'urlPath' : 'acl', + 'data' : { + 'xmlRoot' : 'AccessControlPolicy', + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'VersionId' : { + 'location' : 'urlPath', + 'sentAs' : 'versionId', + }, + 'ACL' : { + 'location' : 'header', + 'sentAs' : 'acl', + 'withPrefix' : true, + 'type' : 'adapter' + }, + 'Delivered' :{ + 'location' : 'xml', + 'sentAs' : 'Delivered' + }, + 'Owner' : owner, + 'Grants' : grants + }, + }, + 'SetObjectAclOutput' : { + 'parameters' : { + 'VersionId' : { + 'location' : 'header', + 'sentAs' : 'version-id', + 'withPrefix' : true + }, + }, + }, + 'GetObjectAcl' : { + 'httpMethod' : 'GET', + 'urlPath' : 'acl', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'VersionId' : { + 'location' : 'urlPath', + 'sentAs' : 'versionId', + }, + }, + }, + 'GetObjectAclOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'AccessControlPolicy', + }, + 'parameters' : { + 'VersionId' : { + 'location' : 'header', + 'sentAs' : 'version-id', + 'withPrefix' : true + }, + 'Delivered' :{ + 'location' : 'xml', + 'sentAs' : 'Delivered' + }, + 'Owner' : owner, + 'Grants' : grants + }, + }, + 'DeleteObject' : { + 'httpMethod' : 'DELETE', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'VersionId' : { + 'location' : 'urlPath', + 'sentAs' : 'versionId', + }, + }, + }, + 'DeleteObjectOutput' : { + 'parameters' : { + 'VersionId' : { + 'location' : 'header', + 'sentAs' : 'version-id', + 'withPrefix' : true + }, + 'DeleteMarker' : { + 'location' : 'header', + 'sentAs' : 'delete-marker', + 'withPrefix' : true + }, + }, + }, + 'DeleteObjects' : { + 'httpMethod' : 'POST', + 'urlPath' : 'delete', + 'data' : { + 'xmlRoot' : 'Delete', + 'md5' : true + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Quiet' : { + 'location' : 'xml', + 'sentAs' : 'Quiet', + }, + 'Objects' : { + 'required' : true, + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Object', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Key' : { + 'sentAs' : 'Key', + }, + 'VersionId' : { + 'sentAs' : 'VersionId', + }, + }, + }, + }, + }, + }, + 'DeleteObjectsOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'DeleteResult', + }, + 'parameters' : { + 'Deleteds' : { + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Deleted', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Key' : { + 'sentAs' : 'Key', + }, + 'VersionId' : { + 'sentAs' : 'VersionId', + }, + 'DeleteMarker' : { + 'sentAs' : 'DeleteMarker', + }, + 'DeleteMarkerVersionId' : { + 'sentAs' : 'DeleteMarkerVersionId', + }, + } + }, + }, + 'Errors' : { + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Error', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'Key' : { + 'sentAs' : 'Key', + }, + 'VersionId' : { + 'sentAs' : 'VersionId', + }, + 'Code' : { + 'sentAs' : 'Code', + }, + 'Message' : { + 'sentAs' : 'Message', + }, + } + }, + }, + }, + }, + + 'InitiateMultipartUpload' : { + 'httpMethod' : 'POST', + 'urlPath' : 'uploads', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'ACL' : { + 'location' : 'header', + 'sentAs' : 'acl', + 'withPrefix' : true + }, + 'GrantRead' : { + 'location' : 'header', + 'sentAs' : 'grant-read', + 'withPrefix' : true, + }, + 'GrantReadAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-read-acp', + 'withPrefix' : true, + }, + 'GrantWriteAcp' : { + 'location' : 'header', + 'sentAs' : 'grant-write-acp', + 'withPrefix' : true, + }, + 'GrantFullControl' : { + 'location' : 'header', + 'sentAs' : 'grant-full-control', + 'withPrefix' : true, + }, + 'StorageClass' : { + 'location' : 'header', + 'sentAs' : 'storage-class', + 'withPrefix' : true + }, + 'Metadata' : { + 'type' : 'object', + 'location' : 'header', + 'sentAs' : 'meta-', + 'withPrefix' : true + }, + 'WebsiteRedirectLocation' : { + 'location' : 'header', + 'sentAs' : 'website-redirect-location', + 'withPrefix' : true + }, + 'Expires' : { + 'location' : 'header', + 'sentAs' : 'expires', + 'type' : 'number', + 'withPrefix' : true + }, + 'ContentType' : { + 'location' : 'header', + 'sentAs' : 'Content-Type' + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true, + 'type' : 'adapter' + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true + }, + }, + }, + 'InitiateMultipartUploadOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'InitiateMultipartUploadResult', + }, + 'parameters' : { + 'Bucket' : { + 'location' : 'xml', + 'sentAs' : 'Bucket', + }, + 'Key' : { + 'location' : 'xml', + 'sentAs' : 'Key', + }, + 'UploadId' : { + 'location' : 'xml', + 'sentAs' : 'UploadId', + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKeyMd5' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key-MD5', + 'withPrefix' : true + } + }, + }, + 'ListMultipartUploads' : { + 'httpMethod' : 'GET', + 'urlPath' : 'uploads', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Delimiter' : { + 'location' : 'urlPath', + 'sentAs' : 'delimiter', + }, + 'KeyMarker' : { + 'location' : 'urlPath', + 'sentAs' : 'key-marker', + }, + 'MaxUploads' : { + 'type' : 'number', + 'location' : 'urlPath', + 'sentAs' : 'max-uploads', + }, + 'Prefix' : { + 'location' : 'urlPath', + 'sentAs' : 'prefix', + }, + 'UploadIdMarker' : { + 'location' : 'urlPath', + 'sentAs' : 'upload-id-marker', + }, + }, + }, + 'ListMultipartUploadsOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'ListMultipartUploadsResult', + }, + 'parameters' : { + 'Bucket' : { + 'location' : 'xml', + 'sentAs' : 'Bucket', + }, + 'KeyMarker' : { + 'location' : 'xml', + 'sentAs' : 'KeyMarker', + }, + 'UploadIdMarker' : { + 'location' : 'xml', + 'sentAs' : 'UploadIdMarker', + }, + 'NextKeyMarker' : { + 'location' : 'xml', + 'sentAs' : 'NextKeyMarker', + }, + 'Prefix' : { + 'location' : 'xml', + 'sentAs' : 'Prefix', + }, + 'Delimiter' : { + 'location' : 'xml', + 'sentAs' : 'Delimiter', + }, + 'NextUploadIdMarker' : { + 'location' : 'xml', + 'sentAs' : 'NextUploadIdMarker', + }, + 'MaxUploads' : { + 'location' : 'xml', + 'sentAs' : 'MaxUploads', + }, + 'IsTruncated' : { + 'location' : 'xml', + 'sentAs' : 'IsTruncated', + }, + 'Uploads' : { + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Upload', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'UploadId' : { + 'sentAs' : 'UploadId', + }, + 'Key' : { + 'sentAs' : 'Key', + }, + 'Initiated' : { + 'sentAs' : 'Initiated', + }, + 'StorageClass' : { + 'sentAs' : 'StorageClass', + }, + 'Owner' : owner, + 'Initiator' : initiator + }, + }, + }, + 'CommonPrefixes' : commonPrefixes + }, + }, + 'UploadPart' : { + 'httpMethod' : 'PUT', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'PartNumber' : { + 'required' : true, + 'type' : 'number', + 'location' : 'urlPath', + 'sentAs' : 'partNumber', + }, + 'UploadId' : { + 'required' : true, + 'location' : 'urlPath', + 'sentAs' : 'uploadId', + }, + 'ContentMD5' : { + 'location' : 'header', + 'sentAs' : 'Content-MD5', + }, + 'Body' : { + 'location' : 'body', + }, + 'SourceFile' : { + 'type' : 'srcFile', + }, + 'Offset' : { + 'type' : 'plain' + }, + 'PartSize' : { + 'type' : 'plain' + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true + } + }, + }, + 'UploadPartOutput' : { + 'parameters' : { + 'ETag' : { + 'location' : 'header', + 'sentAs' : 'etag', + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKeyMd5' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key-MD5', + 'withPrefix' : true + } + }, + }, + 'ListParts' : { + 'httpMethod' : 'GET', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'UploadId' : { + 'required' : true, + 'location' : 'urlPath', + 'sentAs' : 'uploadId', + }, + 'MaxParts' : { + 'type' : 'number', + 'location' : 'urlPath', + 'sentAs' : 'max-parts', + }, + 'PartNumberMarker' : { + 'type' : 'number', + 'location' : 'urlPath', + 'sentAs' : 'part-number-marker', + }, + }, + }, + 'ListPartsOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'ListPartsResult', + }, + 'parameters' : { + 'Bucket' : { + 'location' : 'xml', + 'sentAs' : 'Bucket', + }, + 'Key' : { + 'location' : 'xml', + 'sentAs' : 'Key', + }, + 'UploadId' : { + 'location' : 'xml', + 'sentAs' : 'UploadId', + }, + 'PartNumberMarker' : { + 'location' : 'xml', + 'sentAs' : 'PartNumberMarker', + }, + 'NextPartNumberMarker' : { + 'location' : 'xml', + 'sentAs' : 'NextPartNumberMarker', + }, + 'MaxParts' : { + 'location' : 'xml', + 'sentAs' : 'MaxParts', + }, + 'IsTruncated' : { + 'location' : 'xml', + 'sentAs' : 'IsTruncated', + }, + 'StorageClass' : { + 'location' : 'xml', + 'sentAs' : 'StorageClass', + }, + 'Initiator':initiator, + 'Owner' : owner, + 'Parts' : { + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Part', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'PartNumber' : { + 'sentAs' : 'PartNumber', + }, + 'LastModified' : { + 'type' : 'date', + 'sentAs' : 'LastModified', + }, + 'ETag' : { + 'sentAs' : 'ETag', + }, + 'Size' : { + 'sentAs' : 'Size', + }, + }, + }, + } + }, + }, + 'CopyPart' : { + 'httpMethod' : 'PUT', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'PartNumber' : { + 'required' : true, + 'location' : 'urlPath', + 'sentAs' : 'partNumber', + 'type' : 'number', + }, + 'UploadId' : { + 'required' : true, + 'location' : 'urlPath', + 'sentAs' : 'uploadId', + }, + 'CopySource' : { + 'required' : true, + 'location' : 'header', + 'sentAs' : 'copy-source', + 'skipEncoding' : true, + 'withPrefix' : true + }, + 'CopySourceRange' : { + 'location' : 'header', + 'sentAs' : 'copy-source-range', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true + }, + 'CopySourceSseC' :{ + 'location' : 'header', + 'sentAs' : 'copy-source-server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'CopySourceSseCKey' :{ + 'location' : 'header', + 'sentAs' : 'copy-source-server-side-encryption-customer-key', + 'type' : 'password', + 'withPrefix' : true + } + }, + }, + 'CopyPartOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'CopyPartResult', + }, + 'parameters' : { + 'LastModified' : { + 'type' : 'date', + 'location' : 'xml', + 'sentAs' : 'LastModified', + }, + 'ETag' : { + 'location' : 'xml', + 'sentAs' : 'ETag', + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKeyMd5' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key-MD5', + 'withPrefix' : true + } + }, + }, + 'AbortMultipartUpload' : { + 'httpMethod' : 'DELETE', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'UploadId' : { + 'required' : true, + 'location' : 'urlPath', + 'sentAs' : 'uploadId', + }, + }, + }, + + 'CompleteMultipartUpload' : { + 'httpMethod' : 'POST', + 'data' : { + 'xmlRoot' : 'CompleteMultipartUpload', + }, + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'UploadId' : { + 'required' : true, + 'location' : 'urlPath', + 'sentAs' : 'uploadId', + }, + 'Parts' : { + 'required' : true, + 'type' : 'array', + 'location' : 'xml', + 'sentAs' : 'Part', + 'items' : { + 'type' : 'object', + 'parameters' : { + 'PartNumber' : { + 'sentAs' : 'PartNumber', + }, + 'ETag' : { + 'sentAs' : 'ETag', + }, + }, + }, + }, + }, + }, + 'CompleteMultipartUploadOutput' : { + 'data' : { + 'type' : 'xml', + 'xmlRoot' : 'CompleteMultipartUploadResult', + }, + 'parameters' : { + 'VersionId' : { + 'location' : 'header', + 'sentAs' : 'version-id', + 'withPrefix' : true + }, + 'Location' : { + 'location' : 'xml', + 'sentAs' : 'Location', + }, + 'Bucket' : { + 'location' : 'xml', + 'sentAs' : 'Bucket', + }, + 'Key' : { + 'location' : 'xml', + 'sentAs' : 'Key', + }, + 'ETag' : { + 'location' : 'xml', + 'sentAs' : 'ETag', + }, + 'SseKms' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption', + 'withPrefix' : true + }, + 'SseKmsKey' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-kms-key-id', + 'withPrefix' : true + }, + 'SseC' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-algorithm', + 'withPrefix' : true + }, + 'SseCKeyMd5' :{ + 'location' : 'header', + 'sentAs' : 'server-side-encryption-customer-key-MD5', + 'withPrefix' : true + } + }, + }, + + 'OptionsObject' : { + 'httpMethod' : 'OPTIONS', + 'parameters' : { + 'Bucket' : { + 'required' : true, + 'location' : 'uri', + }, + 'Key' : { + 'required' : true, + 'location' : 'uri', + }, + 'Origin' : { + 'required' : true, + 'location' : 'header', + 'sentAs' : 'Origin', + }, + 'AccessControlRequestMethods' : { + 'required' : true, + 'type' : 'array', + 'location' : 'header', + 'sentAs' : 'Access-Control-Request-Method', + 'items' : { + 'type' : 'string', + }, + }, + 'AccessControlRequestHeaders' : { + 'type' : 'array', + 'location' : 'header', + 'sentAs' : 'Access-Control-Request-Headers', + 'items' : { + 'type' : 'string', + }, + }, + }, + }, + 'OptionsObjectOutput' : { + 'parameters' : { + 'AllowOrigin' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-origin', + }, + 'AllowHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-headers', + }, + 'AllowMethod' : { + 'location' : 'header', + 'sentAs' : 'access-control-allow-methods', + }, + 'ExposeHeader' : { + 'location' : 'header', + 'sentAs' : 'access-control-expose-headers', + }, + 'MaxAgeSeconds' : { + 'location' : 'header', + 'sentAs' : 'access-control-max-age', + }, + }, + } +}; + + +module.exports = operations; \ No newline at end of file diff --git a/lib/obs-sdk-3.0.0/utils.js b/lib/obs-sdk-3.0.0/utils.js new file mode 100644 index 0000000..32ad198 --- /dev/null +++ b/lib/obs-sdk-3.0.0/utils.js @@ -0,0 +1,2026 @@ +'use strict'; + +const crypto = require('crypto'); +const fs = require('fs'); +const events = require('events'); +const httpLib = require('http'); +const httpsLib = require('https'); +const xml2js = require('xml2js'); +const urlLib = require('url'); +const pathLib = require('path'); +const streamLib = require('stream'); +const obsModel = require('./obsModel'); +const v2Model = require('./v2Model'); + +const CONTENT_SHA256 = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'; +const OBS_SDK_VERSION = '3.0.0'; + +const mimeTypes = { + '7z' : 'application/x-7z-compressed', + 'aac' : 'audio/x-aac', + 'ai' : 'application/postscript', + 'aif' : 'audio/x-aiff', + 'asc' : 'text/plain', + 'asf' : 'video/x-ms-asf', + 'atom' : 'application/atom+xml', + 'avi' : 'video/x-msvideo', + 'bmp' : 'image/bmp', + 'bz2' : 'application/x-bzip2', + 'cer' : 'application/pkix-cert', + 'crl' : 'application/pkix-crl', + 'crt' : 'application/x-x509-ca-cert', + 'css' : 'text/css', + 'csv' : 'text/csv', + 'cu' : 'application/cu-seeme', + 'deb' : 'application/x-debian-package', + 'doc' : 'application/msword', + 'docx' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dvi' : 'application/x-dvi', + 'eot' : 'application/vnd.ms-fontobject', + 'eps' : 'application/postscript', + 'epub' : 'application/epub+zip', + 'etx' : 'text/x-setext', + 'flac' : 'audio/flac', + 'flv' : 'video/x-flv', + 'gif' : 'image/gif', + 'gz' : 'application/gzip', + 'htm' : 'text/html', + 'html' : 'text/html', + 'ico' : 'image/x-icon', + 'ics' : 'text/calendar', + 'ini' : 'text/plain', + 'iso' : 'application/x-iso9660-image', + 'jar' : 'application/java-archive', + 'jpe' : 'image/jpeg', + 'jpeg' : 'image/jpeg', + 'jpg' : 'image/jpeg', + 'js' : 'text/javascript', + 'json' : 'application/json', + 'latex' : 'application/x-latex', + 'log' : 'text/plain', + 'm4a' : 'audio/mp4', + 'm4v' : 'video/mp4', + 'mid' : 'audio/midi', + 'midi' : 'audio/midi', + 'mov' : 'video/quicktime', + 'mp3' : 'audio/mpeg', + 'mp4' : 'video/mp4', + 'mp4a' : 'audio/mp4', + 'mp4v' : 'video/mp4', + 'mpe' : 'video/mpeg', + 'mpeg' : 'video/mpeg', + 'mpg' : 'video/mpeg', + 'mpg4' : 'video/mp4', + 'oga' : 'audio/ogg', + 'ogg' : 'audio/ogg', + 'ogv' : 'video/ogg', + 'ogx' : 'application/ogg', + 'pbm' : 'image/x-portable-bitmap', + 'pdf' : 'application/pdf', + 'pgm' : 'image/x-portable-graymap', + 'png' : 'image/png', + 'pnm' : 'image/x-portable-anymap', + 'ppm' : 'image/x-portable-pixmap', + 'ppt' : 'application/vnd.ms-powerpoint', + 'pptx' : 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'ps' : 'application/postscript', + 'qt' : 'video/quicktime', + 'rar' : 'application/x-rar-compressed', + 'ras' : 'image/x-cmu-raster', + 'rss' : 'application/rss+xml', + 'rtf' : 'application/rtf', + 'sgm' : 'text/sgml', + 'sgml' : 'text/sgml', + 'svg' : 'image/svg+xml', + 'swf' : 'application/x-shockwave-flash', + 'tar' : 'application/x-tar', + 'tif' : 'image/tiff', + 'tiff' : 'image/tiff', + 'torrent' : 'application/x-bittorrent', + 'ttf' : 'application/x-font-ttf', + 'txt' : 'text/plain', + 'wav' : 'audio/x-wav', + 'webm' : 'video/webm', + 'wma' : 'audio/x-ms-wma', + 'wmv' : 'video/x-ms-wmv', + 'woff' : 'application/x-font-woff', + 'wsdl' : 'application/wsdl+xml', + 'xbm' : 'image/x-xbitmap', + 'xls' : 'application/vnd.ms-excel', + 'xlsx' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xml' : 'application/xml', + 'xpm' : 'image/x-xpixmap', + 'xwd' : 'image/x-xwindowdump', + 'yaml' : 'text/yaml', + 'yml' : 'text/yaml', + 'zip' : 'application/zip', +}; + + +const allowedResourceParameterNames = [ + 'acl', + 'backtosource', + 'policy', + 'torrent', + 'logging', + 'location', + 'storageinfo', + 'quota', + 'storageclass', + 'storagepolicy', + 'requestpayment', + 'versions', + 'versioning', + 'versionid', + 'uploads', + 'uploadid', + 'partnumber', + 'website', + 'notification', + 'replication', + 'lifecycle', + 'deletebucket', + 'delete', + 'cors', + 'restore', + 'tagging', + 'append', + 'position', + 'response-content-type', + 'response-content-language', + 'response-expires', + 'response-cache-control', + 'response-content-disposition', + 'response-content-encoding', + 'x-image-process', + 'x-oss-process' +]; + + +const allowedResponseHttpHeaderMetadataNames = [ + 'content-type', + 'content-md5', + 'content-length', + 'content-language', + 'expires', + 'origin', + 'cache-control', + 'content-disposition', + 'content-encoding', + 'x-default-storage-class', + 'location', + 'date', + 'etag', + 'host', + 'last-modified', + 'content-range', + 'x-reserved', + 'access-control-allow-origin', + 'access-control-allow-headers', + 'access-control-max-age', + 'access-control-allow-methods', + 'access-control-expose-headers', + 'connection' +]; + +const commonHeaders = { + 'content-length' : 'ContentLength', + 'date' : 'Date', + 'x-reserved' : 'Reserved' +}; + +const obsAllowedStorageClass = ['STANDARD', 'WARM', 'COLD']; + +const v2AllowedStorageClass = ['STANDARD', 'STANDARD_IA', 'GLACIER']; + +const obsAllowedAcl = ['private', 'public-read', 'public-read-write', 'public-read-delivered', 'public-read-write-delivered']; + +const v2AllowedAcl = ['private', 'public-read', 'public-read-write', 'authenticated-read', 'bucket-owner-read', 'bucket-owner-full-control', 'log-delivery-write']; + +const obsAllowedUri = ['Everyone']; + +const v2AllowedUri = ['http://acs.amazonaws.com/groups/global/AllUsers', 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers', 'http://acs.amazonaws.com/groups/s3/LogDelivery']; + +const obsAllowedEvent = ['ObjectCreated:*', 'ObjectCreated:Put', 'ObjectCreated:Post', 'ObjectCreated:Copy', + 'ObjectCreated:CompleteMultipartUpload', 'ObjectRemoved:*', 'ObjectRemoved:Delete', 'ObjectRemoved:DeleteMarkerCreated']; +const v2AllowedEvent = ['s3:ObjectCreated:*', 's3:ObjectCreated:Put', 's3:ObjectCreated:Post', 's3:ObjectCreated:Copy', + 's3:ObjectCreated:CompleteMultipartUpload', 's3:ObjectRemoved:*', 's3:ObjectRemoved:Delete', 's3:ObjectRemoved:DeleteMarkerCreated']; + +function encodeURIWithSafe(str, safe, skipEncoding){ + str = String(str); + if(str.length === 0){ + return ''; + } + if(skipEncoding){ + return str; + } + let ret; + if(safe){ + ret = []; + for(let i=0;i=0 ? str[i] : encodeURIComponent(str[i])); + } + ret = ret.join(''); + }else{ + ret = encodeURIComponent(str); + } + return ret.replace(/!/g, '%21') + .replace(/~/g,'%7E') + .replace(/\*/g, '%2A') + .replace(/'/g, '%27') + .replace(/\(/g, '%28') + .replace(/\)/g, '%29'); +} + +function headerTostring(obj){ + return JSON ? JSON.stringify(obj) : ''; +} + +function parseObjectFromHeaders(sentAs, headers){ + var metadata = {}; + for(let key in headers){ + let k = String(key).toLowerCase(); + if(k.indexOf(sentAs) === 0){ + metadata[k.slice(sentAs.length)] = headers[key]; + } + } + return metadata; +} + +function mkdirsSync(dirname){ + return fs.existsSync(dirname) ? true : (mkdirsSync(pathLib.dirname(dirname)) ? fs.mkdirSync(dirname) : false); +} + +function isArray(obj){ + return Object.prototype.toString.call(obj) === '[object Array]'; +} + +function isObject(obj){ + return Object.prototype.toString.call(obj) === '[object Object]'; +} + +function utcToLocaleString(utcDate){ + return utcDate ? new Date(Date.parse(utcDate)).toLocaleString() : ''; +} + +function makeObjFromXml(xml, bc){ + xml2js.parseString(xml, {explicitArray:false, ignoreAttrs:true}, function(err, result){ + if(err){ + bc(err, null); + return; + } + bc(null, result); + }); +} + + +function getExpireDate(utcDateStr){ + var date = new Date(Date.parse(utcDateStr)); + var hour = date.getUTCHours(); + var min = date.getUTCMinutes(); + var sec = date.getUTCSeconds(); + var day = date.getUTCDate(); + var moth = date.getUTCMonth() + 1; + var year = date.getUTCFullYear(); + var shortDate = ''; + var longDate = ''; + var expireDate = ''; + expireDate += year + '-'; + + if(moth < 10){ + expireDate += '0'; + } + expireDate += moth + '-'; + + if(day < 10){ + expireDate += '0'; + } + expireDate += day + 'T'; + + if(hour < 10){ + expireDate += '0'; + } + expireDate += hour + ':'; + + if(min < 10){ + expireDate += '0'; + } + expireDate += min + ':'; + + if(sec < 10){ + expireDate += '0'; + } + expireDate += sec + 'Z'; + return expireDate; +} + +function getDates(utcDateStr){ + var date = new Date(Date.parse(utcDateStr)); + var hour = date.getUTCHours(); + var min = date.getUTCMinutes(); + var sec = date.getUTCSeconds(); + var day = date.getUTCDate(); + var moth = date.getUTCMonth() + 1; + var year = date.getUTCFullYear(); + var shortDate = ''; + var longDate = ''; + shortDate += year; + + if(moth < 10){ + shortDate += '0'; + } + shortDate += moth; + + if(day < 10){ + shortDate += '0'; + } + shortDate += day; + + longDate += shortDate + 'T'; + if(hour < 10){ + longDate += '0'; + } + longDate += hour; + + if(min < 10){ + longDate += '0'; + } + longDate += min; + + if(sec < 10){ + longDate += '0'; + } + longDate += sec + 'Z'; + return [shortDate, longDate]; +} + +function getSignedAndCanonicalHeaders(header){ + var arrheadKey = []; + var arrhead = {}; + for(let key in header){ + arrheadKey.push(key.toLowerCase()); + arrhead[key.toLowerCase()] = header[key]; + } + arrheadKey = arrheadKey.sort(); + var signedHeaders = ''; + var canonicalHeaders = ''; + for(let i = 0; i < arrheadKey.length; i++){ + if(i !== 0){ + signedHeaders += ';'; + } + signedHeaders += arrheadKey[i]; + canonicalHeaders += arrheadKey[i] + ':' + arrhead[arrheadKey[i]] + '\n'; + } + return [signedHeaders, canonicalHeaders]; +} + +function createV4Signature(shortDate, sk, region, stringToSign){ + var dateKey = crypto.createHmac('sha256', 'AWS4' + sk).update(shortDate).digest(); + var dateRegionKey = crypto.createHmac('sha256', dateKey).update(region).digest(); + var dateRegionServiceKey = crypto.createHmac('sha256', dateRegionKey).update('s3').digest(); + var signingKey = crypto.createHmac('sha256',dateRegionServiceKey).update('aws4_request').digest(); + return crypto.createHmac('sha256',signingKey).update(stringToSign).digest('hex'); +} + +function getV4Signature(shortDate, longDate, sk, region, canonicalRequest){ + var scop = shortDate + '/' + region + '/s3/aws4_request'; + var stringToSign = 'AWS4-HMAC-SHA256' + '\n'; + stringToSign += longDate + '\n'; + stringToSign += scop + '\n'; + stringToSign += crypto.createHash('sha256').update(canonicalRequest).digest('hex'); + return createV4Signature(shortDate, sk, region, stringToSign); +} + + +function Utils(logger) { + this.log = logger; + this.ak = null; + this.sk = null; + this.securityToken = null; + this.isSecure = true; + this.server = null; + this.pathStyle = false; + this.signature = 'v2'; + this.region = 'region'; + this.port = null; + this.maxRetryCount = 3; + this.timeout = 60; + this.sslVerify = false; + this.httpAgent = false; + this.httpsAgent = false; + this.obsSdkVersion = OBS_SDK_VERSION; +} + +Utils.prototype.encodeURIWithSafe = encodeURIWithSafe; + +Utils.prototype.mimeTypes = mimeTypes; + +Utils.prototype.close = function(){ + if(this.httpAgent){ + this.httpAgent.destroy(); + } + if(this.httpsAgent){ + this.httpsAgent.destroy(); + } +}; + +Utils.prototype.refresh = function(ak, sk, securityToken){ + this.ak = ak ? String(ak).trim() : null; + this.sk = sk ? String(sk).trim(): null; + this.securityToken = securityToken ? String(securityToken).trim() : null; +}; + +Utils.prototype.initFactory = function(ak, sk, isSecure, + server, pathStyle, signature, region, port, maxRetryCount, timeout, sslVerify, long_conn_param, securityToken){ + + this.refresh(ak, sk, securityToken); + + if (!server) { + throw new Error('Server is not set'); + } + server = String(server).trim(); + + if(server.indexOf('https://') === 0){ + server = server.slice('https://'.length); + isSecure = true; + }else if(server.indexOf('http://') === 0){ + server = server.slice('http://'.length); + isSecure = false; + } + + let index = server.lastIndexOf('/'); + while(index >= 0){ + server = server.slice(0, index); + index = server.lastIndexOf('/'); + } + + index = server.indexOf(':'); + if(index >= 0){ + port = server.slice(index + 1); + server = server.slice(0, index); + } + this.server = server; + + if(/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/.test(this.server)){ + pathStyle = true; + } + + if (isSecure !== undefined) { + this.isSecure = Boolean(isSecure); + } + if (pathStyle !== undefined) { + this.pathStyle = Boolean(pathStyle); + } + if (signature !== undefined) { + this.signature = String(signature).trim().toLowerCase(); + } + + if(this.signature === 'obs'){ + this.headerPrefix = 'x-obs-'; + this.headerMetaPrefix = 'x-obs-meta-'; + this.authPrefix = 'OBS'; + }else{ + this.headerPrefix = 'x-amz-'; + this.headerMetaPrefix = 'x-amz-meta-'; + this.authPrefix = 'AWS'; + } + + if(region !== undefined){ + this.region = String(region).trim(); + } + + this.port = port ? parseInt(port) : (this.isSecure ? 443 : 80); + + if(maxRetryCount !== undefined){ + this.maxRetryCount = parseInt(maxRetryCount); + } + + if(timeout !== undefined){ + this.timeout = parseInt(timeout); + } + + if(sslVerify !== undefined){ + this.sslVerify = sslVerify; + } + + if(long_conn_param !== undefined && Number(long_conn_param) >= 0){ + this.httpAgent = new httpLib.Agent({keepAlive : true, keepAliveMsecs : Number(long_conn_param) * 1000}); + this.httpsAgent = new httpsLib.Agent({keepAlive : true, keepAliveMsecs : Number(long_conn_param) * 1000}); + } +}; + +Utils.prototype.SseKmsAdapter = function(value){ + value = value || ''; + value = String(value); + let index = value.indexOf('aws:'); + if(this.signature === 'obs'){ + return index === 0 ? value.slice(4) : value; + }else{ + return index === 0 ? value : 'aws:' + value; + } +}; + +Utils.prototype.BucketAdapter = function(value){ + value = value || ''; + value = String(value); + let index = value.indexOf('arn:aws:s3:::'); + if(this.signature === 'obs'){ + return index === 0 ? value.slice('arn:aws:s3:::'.length) : value; + }else{ + return index === 0 ? value : 'arn:aws:s3:::' + value; + } +}; + + +Utils.prototype.EventAdapter = function(value){ + value = value || ''; + value = String(value); + if(this.signature === 'obs'){ + if(obsAllowedEvent.indexOf(value) >= 0){ + return value; + } + if(v2AllowedEvent.indexOf(value) >= 0){ + return value.substring(3); + } + }else{ + if(v2AllowedEvent.indexOf(value) >= 0){ + return value; + } + if(obsAllowedEvent.indexOf(value) >= 0){ + return 's3:' + value; + } + } + return ''; +}; + +Utils.prototype.URIAdapter = function(value){ + value = value || ''; + value = String(value); + if(this.signature === 'obs'){ + if(obsAllowedUri.indexOf(value) >= 0){ + return value; + } + if(value === 'AllUsers' || value === 'http://acs.amazonaws.com/groups/global/AllUsers'){ + return 'Everyone'; + } + }else{ + if(v2AllowedUri.indexOf(value) >= 0){ + return value; + } + if(value === 'Everyone' || value === 'AllUsers'){ + return 'http://acs.amazonaws.com/groups/global/AllUsers'; + }else if(value === 'AuthenticatedUsers'){ + return 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers'; + }else if(value === 'LogDelivery'){ + return 'http://acs.amazonaws.com/groups/s3/LogDelivery'; + } + } + return ''; +}; + + +Utils.prototype.StorageClassAdapter = function(value){ + value = value || ''; + value = String(value).toUpperCase(); + if(this.signature === 'obs'){ + if(obsAllowedStorageClass.indexOf(value) >= 0){ + return value; + } + if(value === 'STANDARD_IA'){ + return 'WARM'; + }else if(value === 'GLACIER'){ + return 'COLD'; + } + }else{ + if(v2AllowedStorageClass.indexOf(value) >= 0){ + return value; + } + if(value === 'WARM'){ + return 'STANDARD_IA'; + }else if(value === 'COLD'){ + return 'GLACIER'; + } + } + return ''; +}; + +Utils.prototype.ACLAdapter = function(value){ + value = value || ''; + value = String(value).toLowerCase(); + if(this.signature === 'obs'){ + if(obsAllowedAcl.indexOf(value) >= 0){ + return value; + } + }else{ + if(value === 'public-read-delivered'){ + value = 'public-read'; + }else if(value === 'public-read-write-delivered'){ + value = 'public-read-write'; + } + + if(v2AllowedAcl.indexOf(value) >= 0){ + return value; + } + } + return ''; +}; + + +Utils.prototype.toXml = function(mXml, xmlMeta, root, sentAs){ + var xml = ''; + if(root !== null){ + xml += this.buildXml(mXml, xmlMeta, root, sentAs); + }else{ + for (let key in xmlMeta){ + if(key in mXml){ + let meta = xmlMeta[key]; + xml += this.buildXml(mXml, meta, key, meta.sentAs || key); + } + } + } + return xml; +}; + +Utils.prototype.buildXml = function(mXml, xmlMeta, key, sentAs){ + var xml = ''; + let type = xmlMeta.type; + if(type === 'array'){ + for(let i = 0; i < mXml[key].length; i++){ + if(xmlMeta.items.type === 'object'){ + let result = this.toXml(mXml[key][i], xmlMeta.items.parameters, null); + if(result !== ''){ + xml += '<' + sentAs + '>'+ result + ''; + } + }else if(xmlMeta.items.type === 'adapter'){ + xml += '<' + sentAs + '>' + String(this[key + 'Adapter'](mXml[key][i])).replace(/&/g, '&').replace(/'/g, ''').replace(/"/g, '"') + ''; + }else if(xmlMeta.items.type !== 'array'){ + xml += '<' + sentAs + '>'+ String(mXml[key][i]).replace(/&/g, '&').replace(/'/g, ''').replace(/"/g, '"') + ''; + } + } + }else if(type === 'object'){ + let result = this.toXml(mXml[key], xmlMeta.parameters, null); + if(result !== ''){ + xml += '<' + sentAs; + if('data' in xmlMeta){ + if('xsiNamespace' in xmlMeta.data){ + xml += ' xmlns:xsi="' + xmlMeta.data.xsiNamespace + '"'; + } + if('xsiType' in xmlMeta.data){ + xml += ' xsi:type="' + mXml[key][xmlMeta.data.xsiType] + '"'; + } + } + xml += '>'; + xml += result + ''; + } + + }else if(type === 'adapter'){ + xml += '<' + sentAs + '>' + String(this[key + 'Adapter'](mXml[key])).replace(/&/g, '&').replace(/'/g, ''').replace(/"/g, '"') + ''; + }else if(type !== 'ignore'){ + xml += '<' + sentAs + '>' + String(mXml[key]).replace(/&/g, '&').replace(/'/g, ''').replace(/"/g, '"') + ''; + } + if(xml && xmlMeta.wrapper){ + let _wrapper = xmlMeta.wrapper; + xml = '<' + _wrapper + '>' + xml + ''; + } + return xml; +}; + + + +Utils.prototype.jsonToObject = function(model, obj, root){ + var opt = {}; + if(root !== null){ + this.buildObject(model, obj, root, opt); + }else{ + for(let key in model){ + this.buildObject(model, obj, key, opt); + } + } + return opt; +}; + +Utils.prototype.buildObject = function(model, obj, key, opt){ + if(isObject(obj)){ + let flag = true; + let wrapper = model[key].wrapper; + if(wrapper && wrapper in obj){ + obj = obj[wrapper]; + flag = isObject(obj); + } + if(flag){ + let sentAs = model[key].sentAs || key; + if(sentAs in obj){ + if(model[key].type === 'object'){ + opt[key] = this.jsonToObject(model[key].parameters, obj[sentAs], null); + }else if(model[key].type === 'array'){ + let arr = []; + if(!isArray(obj[sentAs])){ + arr[0] = model[key].items.type === 'object' ? this.jsonToObject(model[key].items.parameters, obj[sentAs], null) : obj[sentAs]; + }else{ + for (let i = 0; i < obj[sentAs].length; i++ ){ + arr[i] = model[key].items.type === 'object' ? this.jsonToObject(model[key].items.parameters, obj[sentAs][i], null) : obj[sentAs][i]; + } + } + opt[key] = arr; + }else if(model[key].type === 'date'){ + opt[key] = utcToLocaleString(obj[sentAs]); + }else{ + opt[key] = obj[sentAs]; + } + } + } + } + + if(opt[key] === undefined){ + if(model[key].type === 'object'){ + opt[key] = model[key].parameters ? this.jsonToObject(model[key].parameters, null, null) : {}; + }else if(model[key].type === 'array'){ + opt[key] = []; + }else{ + opt[key] = ''; + } + } +}; + +Utils.prototype.makeParam = function(methodName, param){ + var model = this.signature === 'obs' ? obsModel[methodName] : v2Model[methodName]; + var method = model.httpMethod; + var uri = '/'; + var urlPath = ''; + var xml = ''; + var exheaders = {}; + var opt = {}; + + if ('urlPath' in model){ + urlPath += '?'; + urlPath += model.urlPath; + } + for (let key in model.parameters){ + let meta = model.parameters[key]; + if (meta.require && !(key in param)){ + opt.err = key + ' is a required element!'; + if(this.log.isLevelEnabled('warn')){ + this.log.runLog('warn', methodName, opt.err); + } + return opt; + } + + if(param[key] !== null && param[key] !== undefined){ + + if(meta.type === 'srcFile' || meta.type === 'dstFile'){ + opt[meta.type] = param[key]; + continue; + } + + if(meta.type === 'plain'){ + opt[key] = param[key]; + } + + let sentAs = meta.sentAs || key; + + if(meta.withPrefix){ + sentAs = this.headerPrefix + sentAs; + } + + if(meta.location === 'uri'){ + if(uri !== '/'){ + uri += '/'; + } + uri += param[key]; + }else if(meta.location === 'header'){ + let safe = meta.encodingSafe || ' ;/?:@&=+$,'; + if(meta.type === 'object'){ + if(this.headerMetaPrefix === sentAs){ + for(let item in param[key]){ + let value = param[key][item]; + item = String(item).trim().toLowerCase(); + exheaders[item.indexOf(sentAs) === 0 ? item: sentAs + item] = encodeURIWithSafe(value, safe); + } + } + }else if(meta.type === 'array'){ + let arr = []; + for(let i=0;i= 0)){ + urlPath += sep + encodeURIWithSafe(sentAs, '/') + '=' + encodeURIWithSafe(String(value), '/'); + } + }else if(meta.location === 'xml'){ + let mxml = this.toXml(param, meta, key, sentAs); + if(mxml){ + xml += mxml; + } + }else if(meta.location === 'body'){ + xml = param[key]; + } + } + } + + if('data' in model && 'xmlRoot' in model.data){ + if(xml || model.data.xmlAllowEmpty){ + let xmlRoot = model.data.xmlRoot; + xml = '<' + xmlRoot + '>' + xml + ''; + } + } + + exheaders.Host = this.server; + + if(!this.pathStyle){ + let uriList = uri.split('/'); + if(uriList.length >= 2 && uriList[1]){ + exheaders.Host = uriList[1] + '.' + exheaders.Host; + let requestUri = uri.replace(uriList[1], ''); + if(requestUri.indexOf('//') === 0){ + requestUri = requestUri.slice(1); + } + if(this.signature === 'v4'){ + uri = requestUri; + }else if(requestUri === '/'){ + uri += '/'; + } + opt.requestUri = encodeURIWithSafe(requestUri, '/'); + } + } + opt.method = method; + opt.uri = encodeURIWithSafe(uri, '/'); + opt.urlPath = urlPath; + if(xml){ + if(!(xml instanceof streamLib.Readable)){ + let body = Buffer.from(String(xml), 'utf8'); + if(model.data && model.data.md5){ + exheaders['Content-MD5'] = this.bufMD5(body); + } + exheaders['Content-Length'] = body.length === 0 ? '0' : String(body.length); + } + opt.xml = xml; + if(this.log.isLevelEnabled('debug')){ + this.log.runLog('debug', methodName, 'request content:' + xml); + } + } + opt.headers = exheaders; + + if('srcFile' in opt){ + if (!fs.existsSync(opt.srcFile)) { + opt.err = 'the file [' + opt.srcFile + '] is not exist!'; + if(this.log.isLevelEnabled('error')){ + this.log.runLog('error', methodName, opt.err); + } + return opt; + } + + let fileSize = fs.statSync(opt.srcFile).size; + if ('Content-Length' in opt.headers || 'PartSize' in opt || 'Offset' in opt) { + let offset = opt.Offset; + offset = (offset && offset >= 0 && offset < fileSize) ? offset : 0; + let partSize; + if('PartSize' in opt){ + partSize = opt.PartSize; + }else if('Content-Length' in opt.headers){ + partSize = parseInt(opt.headers['Content-Length']); + }else{ + partSize = fileSize; + } + partSize = (partSize && partSize > 0 && partSize <= fileSize - offset) ? partSize : fileSize - offset; + opt.PartSize = partSize; + opt.Offset = offset; + opt.headers['Content-Length'] = String(opt.PartSize); + } + } + + return opt; +}; + +Utils.prototype.sendRequest = function(funcName, opt, backcall, count){ + if(count === undefined){ + count = 1; + } + let that = this; + let readable = opt.xml instanceof streamLib.Readable; + that.makeRequest(funcName, opt, function(err,msg){ + if(err && !readable && msg !== 'PREMATURE_END' + && msg !== 'SELF_SIGNED_CERT_IN_CHAIN' && msg !== 'DEPTH_ZERO_SELF_SIGNED_CERT' && count <= that.maxRetryCount){ + that.sendRequest(funcName, opt, backcall, count + 1); + }else if(err === 'redirect' && !readable && msg){ + let uri = urlLib.parse(msg); + opt.headers.Host = uri.hostname; + opt.protocol = uri.protocol; + opt.port = uri.port || (opt.protocol.toLowerCase().indexOf('https') === 0 ? 443 : 80); + that.sendRequest(funcName, opt, backcall); + }else{ + backcall(err,msg); + } + }); +}; + +Utils.prototype.doAuth = function(opt, methodName) { + var interestHeader = ['Content-MD5', 'Content-Type', 'Date']; + var log = this.log; + var stringToSign = opt.method + '\n'; + for(let i=0;i= 0){ + urlPath += urlPath === '' ? '?' : '&'; + urlPath += key; + if(listvar.length === 2 && listvar[1]){ + urlPath += '=' + decodeURIComponent(listvar[1]); + } + } + } + path += urlPath; + } + stringToSign += path; + if(log.isLevelEnabled('debug')){ + log.runLog('debug',methodName, 'stringToSign:' + stringToSign); + } + opt.headers.Authorization = this.authPrefix + ' ' + this.ak + ':' + crypto.createHmac('sha1', this.sk).update(stringToSign).digest('base64'); +}; + +Utils.prototype.v4Auth = function(opt, methodName){ + opt.headers[this.headerPrefix + 'content-sha256'] = CONTENT_SHA256; + var header = opt.headers; + var log = this.log; + var shortDate = null; + var longDate = null; + + if(this.headerPrefix + 'date' in header){ + longDate = header[this.headerPrefix + 'date']; + shortDate = longDate.slice(0, longDate.indexOf('T')); + }else{ + let dates = getDates(header.Date); + shortDate = dates[0]; + longDate = dates[1]; + } + + var credential = this.ak + '/' + shortDate + '/' + this.region + '/s3/aws4_request'; + + var signedAndCanonicalHeaders = getSignedAndCanonicalHeaders(header); + + var signedHeaders = signedAndCanonicalHeaders[0]; + var canonicalHeaders = signedAndCanonicalHeaders[1]; + + var canonicalQueryString = ''; + if(opt.urlPath){ + let path = opt.urlPath.slice(1); + let arrPath = path.split('&').sort(); + for(let i=0;i= 300 && serverback.statusCode < 400 && serverback.statusCode !== 304 && !readable){ + let location = headers.location || headers.Location; + if(location){ + if(log.isLevelEnabled('warn')){ + let err = 'http code is 3xx, need to redirect to ' + location; + log.runLog('warn', methodName, err); + } + bc('redirect', location); + }else{ + let err = 'get redirect code 3xx, but no location in headers'; + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, err); + } + bc(err, null); + } + }else if(serverback.statusCode < 300){ + if(dstFile){ + let fileDir = pathLib.dirname(dstFile); + if(mkdirsSync(fileDir)){ + let stream = fs.createWriteStream(dstFile); + serverback.on('error', function(err){ + stream.end(); + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'get response stream error [' + headerTostring(err) + ']'); + } + bc(err, null); + }).on('end', function(){ + stream.end(); + that.contrustCommonMsg(opt, obj, headers, methodName); + if(log.isLevelEnabled('debug')){ + log.runLog('debug', methodName, 'exec interface ' + methodName + ' finish, Status:' + opt['CommonMsg']['Status'] + ', Code: ,Message: '); + } + }).pipe(stream); + + stream.on('close', function(){ + if(opt.InterfaceResult && opt.InterfaceResult.ContentLength !== undefined){ + if(fs.existsSync(dstFile)){ + let fstat = fs.statSync(dstFile); + if(fstat.size !== parseInt(opt.InterfaceResult.ContentLength)){ + bc('premature end of Content-Length delimiter message body (expected:' + opt.InterfaceResult.ContentLength + '; received:' + fstat.size + ')', 'PREMATURE_END'); + return; + } + } + } + doLog(); + }); + }else{ + bc('failed to create file:' + dstFile, null); + } + }else if(('data' in model) && saveAsStream){ + that.contrustCommonMsg(opt, obj, headers, methodName); + if(log.isLevelEnabled('debug')){ + let respMsg = 'Status: ' + opt.CommonMsg.Status + ', headers: ' + headerTostring(headers); + log.runLog('debug', methodName, respMsg); + } + + for (let key in obj){ + if(obj[key].location === 'body'){ + if(opt.InterfaceResult && opt.InterfaceResult.ContentLength !== undefined){ + let contentLength = parseInt(opt.InterfaceResult.ContentLength); + serverback.$readedCount = 0; + serverback.$expectedCount = contentLength; + serverback.on('data', function(data){ + serverback.$readedCount += data.length; + }).on('end', function(){ + let expectedCount = serverback.$expectedCount; + let readedCount = serverback.$readedCount; + delete serverback.$readedCount; + delete serverback.$expectedCount; + if(expectedCount !== readedCount){ + throw new Error('premature end of Content-Length delimiter message body (expected:' + serverback.$expectedCount + '; received:' + serverback.$readedCount + ')'); + } + }); + } + opt.InterfaceResult[key] = serverback; + break; + } + } + doLog(); + }else{ + let body = []; + serverback.on('data', function(data) { + body.push(data); + }).on('error', function(err){ + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'get response stream error [' + headerTostring(err) + ']'); + } + bc(err, null); + }).on('end', function() { + that.contrustCommonMsg(opt, obj, headers, methodName); + body = Buffer.concat(body); + + if(log.isLevelEnabled('debug')){ + let respMsg = 'Status: ' + opt.CommonMsg.Status + ', headers: ' + headerTostring(headers); + if(body){ + respMsg += 'body length: ' + body.length; + log.runLog('debug', methodName, 'response body length:' + body.length); + } + log.runLog('debug', methodName, respMsg); + } + + if(body && ('data' in model)){ + if(model.data.type === 'xml'){ + makeObjFromXml(body, function(err,result){ + if(err){ + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'change xml to json err [' + headerTostring(err) + ']' ); + } + bc(err, null); + return; + } + let tempResult = result; + if(model.data.xmlRoot && (model.data.xmlRoot in tempResult)){ + tempResult = result[model.data.xmlRoot]; + } + if(isObject(tempResult)){ + for (let key in obj){ + if(obj[key].location === 'xml'){ + opt.InterfaceResult[key] = that.jsonToObject(obj, tempResult, key)[key]; + } + } + } + }); + }else if(model.data.type === 'body'){ + for (let key in obj){ + if(obj[key].location === 'body'){ + opt.InterfaceResult[key] = body; + break; + } + } + } + } + doLog(); + }); + } + }else{ + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'request error with http status code:' + serverback.statusCode); + } + let body = []; + serverback.on('data', function(data) { + body.push(data); + }).on('error', function(err){ + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'get response stream error [' + headerTostring(err) + ']'); + } + bc(err, null); + }).on('end', function() { + body = Buffer.concat(body); + if(log.isLevelEnabled('debug')){ + let respMsg = 'Status: ' + opt.CommonMsg.Status + ', headers: ' + headerTostring(headers); + if(body !== ''){ + respMsg += 'body: ' + body; + log.runLog('debug', methodName, 'response body :' + body); + } + log.runLog('debug', methodName, respMsg); + } + + if(body){ + makeObjFromXml(body, function(err, re){ + if(err){ + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'change xml to json err [' + headerTostring(err) + ']' ); + } + bc(err,null); + return; + } + if(re && 'Error' in re){ + let errMsg = re.Error; + opt.CommonMsg.Code = errMsg.Code; + opt.CommonMsg.Message = errMsg.Message; + opt.CommonMsg.HostId = errMsg.HostId; + opt.CommonMsg.RequestId = errMsg.RequestId; + + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'request error with error code:' + opt.CommonMsg.Code + ', error message:' + opt.CommonMsg.Message + ', request id:' + opt.CommonMsg.RequestId); + } + + } + doLog(); + }); + }else{ + doLog(); + } + }); + } + +}; + +Utils.prototype.makeRequest = function(methodName, opt, bc){ + var log = this.log; + var body = opt.xml; + var readable = body instanceof streamLib.Readable; + + var nowDate = new Date(); + opt.headers.Date = nowDate.toUTCString(); + + delete opt.headers.Authorization;//retry bug fix + + var ex = opt.headers; + var path = (opt.requestUri ? opt.requestUri : opt.uri) + opt.urlPath; + var method = opt.method; + + if(this.ak && this.sk){ + if(this.securityToken){ + opt.headers[this.headerPrefix + 'security-token'] = this.securityToken; + } + if(this.signature === 'v4'){ + this.v4Auth(opt, methodName); + }else{ + this.doAuth(opt, methodName); + } + } + + ex['User-Agent'] = 'obs-sdk-js/' + this.obsSdkVersion; + + if(log.isLevelEnabled('info')){ + log.runLog('info', methodName, 'prepare request parameters ok, then Send request to service start'); + } + + if(log.isLevelEnabled('debug')){ + let header_msg = {}; + for (let key in ex){ + header_msg[key] = ex[key]; + } + header_msg.Authorization = '****'; + + let msg = 'method:' + method + ', path:' + path + 'headers:' + headerTostring(header_msg); + if (body && !readable) { + msg += 'body:' + body; + } + log.runLog('debug', methodName, 'request msg:' + msg); + } + + var reopt = { + method : method, + host : ex.Host, + port : opt.port || this.port, + path : path, + ca : !this.sslVerify || !fs.existsSync(String(this.sslVerify)) ? null : fs.readFileSync(String(this.sslVerify)), + checkServerIdentity: function (host, cert) { + return undefined;//do not verify hostname + }, + rejectUnauthorized : Boolean(this.sslVerify), + headers : ex + }; + + var start = nowDate.getTime(); + + var _isSecure = opt.protocol ? opt.protocol.toLowerCase().indexOf('https') === 0 : this.isSecure; + + reopt.agent = _isSecure ? this.httpsAgent : this.httpAgent; + + var _http = _isSecure ? httpsLib : httpLib; + + var req = _http.request(reopt); + req.setNoDelay(true); + req.setTimeout(this.timeout * 1000); + + var that = this; + + req.on('response', function(serverback) { + if(log.isLevelEnabled('info')){ + log.runLog('info', methodName, 'http cost ' + (new Date().getTime() - start) + ' ms'); + } + that.getRequest(methodName, serverback, opt.dstFile, bc, opt.SaveAsStream, readable); + }).on('error', function(err){ + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'Send request to service error [' + headerTostring(err) + ']'); + } + if(log.isLevelEnabled('info')){ + log.runLog('info', methodName, 'http cost ' + (new Date().getTime() - start) + ' ms'); + } + bc(err, null); + }); + + if(method in ['GET', 'HEAD', 'OPTIONS']){ + req.end(); + return; + } + + if(body){ + if(readable){ + if('ContentLength' in opt){ + let contentLength = parseInt(opt.ContentLength); + let writeCount = 0; + body.on('data', function(data){ + if(writeCount >= contentLength){ + req.end(); + if(body.destroy){ + body.destroy(); + } + return; + } + if(contentLength - writeCount > data.length){ + req.write(data, function(err){ + if(err){ + req.abort(); + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'read stream to send error [' + err + ']'); + } + bc(err, null); + return; + } + writeCount += data.length; + }); + }else{ + req.write(Buffer.from(data, 0, contentLength - writeCount), function(err){ + if(err){ + req.abort(); + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'read stream to send error [' + err + ']'); + } + bc(err, null); + return; + } + writeCount = contentLength; + }); + } + }); + }else{ + body.pipe(req); + } + body.on('error',function(err){ + req.abort(); + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'read file to send error [' + headerTostring(err) + ']'); + } + bc(err,null); + }).on('end', function(){ + req.end(); + }); + }else{ + req.end(String(body)); + } + return; + } + if(!('srcFile' in opt)){ + req.end(); + return; + } + + let offset = opt.Offset >= 0 ? opt.Offset : 0; + if('PartSize' in opt){ + this.doSend(req, opt.srcFile, offset, parseInt(opt.PartSize), methodName, bc); + }else if('ContentLength' in opt){ + this.doSend(req, opt.srcFile, offset, parseInt(opt.ContentLength), methodName, bc); + }else{ + let stream = fs.createReadStream(opt.srcFile); + stream.on('error', function(err){ + req.abort(); + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'read file to send error [' + headerTostring(err) + ']'); + } + bc(err, null); + }).on('end', function(){ + req.end(); + }).pipe(req); + } + +}; + +Utils.prototype.doSend = function(req, srcFile, initPos, totalCount, methodName, bc){ + var log = this.log; + fs.open(srcFile, 'r', function(err, fd){ + if(err){ + req.abort(); + fs.close(fd,function(err){}); + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'read file to send error [' + err + ']'); + } + bc(err, null); + return; + } + + var buffer = Buffer.alloc(65536); + var _doSend = function(sendPosition, sendCount){ + if(sendCount >= totalCount){ + req.end(); + fs.close(fd,function(err){}); + return; + } + + var sendCountOnce = (totalCount - sendCount) > buffer.length ? buffer.length : totalCount - sendCount; + + fs.read(fd, buffer, 0, sendCountOnce, sendPosition, function(err, bytes){ + if (err){ + req.abort(); + fs.close(fd,function(err){}); + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'read file to send error [' + err + ']'); + } + bc(err, null); + return; + } + if(bytes <= 0){ + req.end(); + fs.close(fd, function(err){}); + return; + } + req.write(buffer.slice(0, bytes), function(err){ + if(err){ + req.abort(); + fs.close(fd,function(err){}); + if(log.isLevelEnabled('error')){ + log.runLog('error', methodName, 'read file to send error [' + err + ']'); + } + bc(err, null); + return; + } + _doSend(sendPosition + bytes, sendCount + bytes); + }); + }); + }; + _doSend(initPos, 0); + }); +}; + +Utils.prototype.bufMD5 = function(buf) { + return crypto.createHash('md5').update(buf).digest('base64'); +}; + +Utils.prototype.fileMD5 = function (filePath, bc){ + var stream = fs.createReadStream(filePath); + var sha = crypto.createHash('md5'); + stream.on('error',function(err){ + if(err){ + bc(err,null); + } + }).on('data', function(data){ + sha.update(data); + }).on('end', function(){ + var md5 = sha.digest('base64'); + bc(null, md5); + }); +}; + + +Utils.prototype.createSignedUrlSync = function(param){ + return this.signature === 'v4' ? this.createV4SignedUrlSync(param) : this.createV2SignedUrlSync(param); +}; + +Utils.prototype.createV2SignedUrlSync = function(param){ + param = param || {}; + + var method = param.Method ? String(param.Method) : 'GET'; + var bucketName = param.Bucket ? String(param.Bucket) : null; + var objectKey = param.Key ? String(param.Key) : null; + var specialParam = param.SpecialParam ? String(param.SpecialParam) : null; + + if(this.signature === 'obs' && specialParam === 'storagePolicy'){ + specialParam = 'storageClass'; + }else if(this.signature === 'v2' && specialParam === 'storageClass'){ + specialParam = 'storagePolicy'; + } + + var expires = param.Expires ? parseInt(param.Expires) : 300; + var headers = {}; + if(param.Headers && (param.Headers instanceof Object) && !(param.Headers instanceof Array)){ + for(let key in param.Headers){ + headers[key] = param.Headers[key]; + } + } + + var queryParams = {}; + if(param.QueryParams && (param.QueryParams instanceof Object) && !(param.QueryParams instanceof Array)){ + for(let key in param.QueryParams){ + queryParams[key] = param.QueryParams[key]; + } + } + + if(this.securityToken && !queryParams[this.headerPrefix + 'security-token']){ + queryParams[this.headerPrefix + 'security-token'] = this.securityToken; + } + + var result = ''; + var resource = ''; + var host = this.server; + if(bucketName){ + resource += '/' + bucketName; + if(this.pathStyle){ + result += '/' + bucketName; + }else{ + host = bucketName + '.' + host; + resource += '/'; + } + } + + headers.Host = host; + + if(objectKey){ + objectKey = encodeURIWithSafe(objectKey, '/'); + result += '/' + objectKey; + if(resource.lastIndexOf('/') !== resource.length - 1){ + resource += '/'; + } + resource += objectKey; + } + + if(resource === ''){ + resource = '/'; + } + + result += '?'; + + if(specialParam){ + queryParams[specialParam] = ''; + } + + if(this.signature === 'v2'){ + queryParams.AWSAccessKeyId = this.ak; + }else{ + queryParams.AccessKeyId = this.ak; + } + + if(expires < 0){ + expires = 300; + } + expires = parseInt(new Date().getTime() / 1000) + expires; + + queryParams.Expires = String(expires); + + var interestHeaders = {}; + for(let name in headers){ + let key = String(name).toLowerCase(); + if(key === 'content-type' || key === 'content-md5' || key.length > this.headerPrefix.length && key.slice(0,this.headerPrefix.length) === this.headerPrefix){ + interestHeaders[key] = headers[name]; + } + } + + var queryParamsKeys = []; + for(let key in queryParams){ + queryParamsKeys.push(key); + } + queryParamsKeys.sort(); + var index = 0; + var flag = false; + var _resource = []; + for(let i=0;i=0 || key.toLowerCase().indexOf(this.headerPrefix) === 0){ + flag = true; + let _val = val ? key + '=' + decodeURIComponent(val) : key; + _resource.push(_val); + } + result += '&'; + index++; + } + _resource = _resource.join('&'); + if(flag){ + _resource = '?' + _resource; + } + resource += _resource; + var stringToSign = [method]; + stringToSign.push('\n'); + + if('content-md5' in interestHeaders){ + stringToSign.push(interestHeaders['content-md5']); + } + stringToSign.push('\n'); + + if('content-type' in interestHeaders){ + stringToSign.push(interestHeaders['content-type']); + } + stringToSign.push('\n'); + + stringToSign.push(String(expires)); + stringToSign.push('\n'); + + var temp = []; + var i = 0; + for(let key in interestHeaders){ + if (key.length > this.headerPrefix.length && key.slice(0, this.headerPrefix.length) === this.headerPrefix){ + temp[i++] = key; + } + } + temp = temp.sort(); + for(let j=0;j { + options = options || {}; + if (!options.hasOwnProperty('server') || !options.hasOwnProperty('bucket') + || !options.hasOwnProperty('accessKeyId') || !options.hasOwnProperty('secretAccessKey') + || !options.hasOwnProperty('localDir')) { + throw new Error('server, bucket, accessKeyId, secretAccessKey, localDir must not be empty'); + } + + if (options.server.substring(0, 8) != "https://") { + throw new Error('server option must start with "https://", e.g. "https://obs.cn-north-1.myhwclouds.com"'); + } + + if (!options.hasOwnProperty('localFilesIgnorePattern')) options.localFilesIgnorePattern = "$\\..*"; + if (!options.hasOwnProperty('remoteDir')) options.remoteDir = "/"; + if (!options.hasOwnProperty('syncDeletedFiles')) options.syncDeletedFiles = "yes"; + if (!options.hasOwnProperty('syncDeletedFilesIgnorePattern')) options.syncDeletedFilesIgnorePattern = "$\\..*"; + + options.localDir = path.normalize(options.localDir).replace(/(^\s*)|(\s*$)/g, "") + options.remoteDir = options.remoteDir.replace(/(^\/*)|(\/*$)/g, "").replace(/(^\s*)|(\s*$)/g, "") + return options; + } + + let checkSyncFileToOptions = (options) => { + options = options || {}; + if (!options.hasOwnProperty('server') || !options.hasOwnProperty('bucket') + || !options.hasOwnProperty('accessKeyId') || !options.hasOwnProperty('secretAccessKey') + || !options.hasOwnProperty('localFileName') || !options.hasOwnProperty('remoteFileName')) { + throw new Error('server, bucket, accessKeyId, secretAccessKey, localFileName remoteFileName must not be empty'); + } + + if (options.server.substring(0, 8) != "https://") { + throw new Error('server option must start with "https://", e.g. "https://obs.cn-north-1.myhwclouds.com"'); + } + + options.localFileName = path.normalize(options.localFileName).replace(/(^\s*)|(\s*$)/g, "") + options.remoteFileName = options.remoteFileName.replace(/(^\/*)|(\/*$)/g, "").replace(/(^\s*)|(\s*$)/g, "") + return options; + } + + let getObsClient = (options) => { + return new ObsClient({ + access_key_id: options.accessKeyId, + secret_access_key: options.secretAccessKey, + server : options.server, + }); + }; + + let getOBSFileList = async (options) => { + let baseUrl = options.server.replace("https://", "https://" + options.bucket + ".") + "?max-keys=1000&prefix=" + urlencode(options.remoteDir); + let marker = ""; + let result = []; + console.log("get remote obs file list ..."); + while (true) { + let data = await new Promise((resolver, reject) => { + let url = marker == "" ? baseUrl : baseUrl + "&marker=" + urlencode(marker); + console.log(url); + request(url, (error, response, body) => { + if (error) reject(error); + xml2js.parseString(body, {explicitArray:false, ignoreAttrs:true}, (error, result) => { + resolver(result); + }); + }); + }); + if (data.ListBucketResult.Contents != undefined) { + result = result.concat(data.ListBucketResult.Contents); + } + if (data.ListBucketResult.NextMarker == "" || data.ListBucketResult.NextMarker == undefined) { + break; + } + marker = data.ListBucketResult.NextMarker; + } + console.log("get remote obs file list success, total file " + result.length); + return [options, result]; + } + + let getChangedFileList = (info) => { + let options = info[0]; + let remoteFileList = info[1]; + console.log("=================sync files start================================"); + console.log("get local file list ..."); + let localFileList = hexofs.listDirSync(options.localDir).map(item => { + let data = hexofs.readFileSync(path.join(options.localDir, item), {escape: false, encoding: null}); + let result = { + filename: path.join(options.localDir, item), + linuxFilename: item.replace(/\\/g, "/"), + obsKey: options.remoteDir == "" ? item.replace(/\\/g, "/") : options.remoteDir + "/" + item.replace(/\\/g, "/"), + md5: crypto.createHash('md5').update(data).digest('hex'), + base64MD5: crypto.createHash('md5').update(data).digest("base64") + }; + return result; + }) + console.log("get local file list success, total file " + localFileList.length); + + console.log("calculate changed local file list ..."); + var updatedFileList = []; + let localFilesIgnoreRegex = new RegExp(options.localFilesIgnorePattern); + for (var i = 0; i < localFileList.length; i++) { + let isUpdated = true; + for (var j = 0; j < remoteFileList.length; j++) { + if (remoteFileList[j].Key == localFileList[i].obsKey) { + if (remoteFileList[j].ETag.replace(/"/g, "") == localFileList[i].md5) { + isUpdated = false; + } + break; + } + } + if (isUpdated && !localFilesIgnoreRegex.test(localFileList[i].linuxFilename)) { + updatedFileList.push(localFileList[i]); + } + } + console.log("calculate changed local file list success, total changed file " + updatedFileList.length); + + console.log("calculate deleted local file list ..."); + var deletedFileList = []; + let syncDeletedFilesIgnoreRegex = new RegExp(options.syncDeletedFilesIgnorePattern); + for (var i = 0; i < remoteFileList.length; i++) { + let isExist = false; + for (var j = 0; j < localFileList.length; j++) { + if (remoteFileList[i].Key == localFileList[j].obsKey) { + isExist = true; + break; + } + } + if (!isExist && !syncDeletedFilesIgnoreRegex.test(remoteFileList[i].Key)) { + deletedFileList.push(remoteFileList[i]); + } + } + console.log("calculate deleted local file list success, total changed file " + deletedFileList.length); + return [options, updatedFileList, deletedFileList]; + } + + let uploadFiles = async (info) => { + let options = info[0]; + let updatedFileList = info[1]; + let deletedFileList = info[2]; + let obsClient = getObsClient(options); + + console.log("===========> uploading files ..."); + await Promise.all(updatedFileList.map(function (item) { + return new Promise((resolver, reject) => { + obsClient.putObject({ + Bucket : options.bucket, + Key : item.obsKey, + SourceFile : item.filename, + ContentMD5: item.base64MD5 + }, (err, result) => { + if(err){ + console.error('upload file--> ' + item.obsKey + ', error, ' + err); + reject(err); + }else{ + console.error('upload file--> ' + item.obsKey + ', ' + result.CommonMsg.Status); + resolver(result.CommonMsg.Status); + } + }); + }); + })); + console.log("===========> uploading files finished..."); + + if (options.syncDeletedFiles == "yes") { + console.log("===========> deleting files ..."); + await Promise.all(deletedFileList.map(function (item) { + return new Promise((resolver, reject) => { + obsClient.deleteObject({ + Bucket : options.bucket, + Key : item.Key + }, (err, result) => { + if(err){ + console.error('delete file--> ' + item.Ke + ', error, ' + err); + reject(err); + }else{ + console.error('delete file --> ' + item.Key + ', response code: ' + result.CommonMsg.Status); + resolver(result.CommonMsg.Status); + } + }); + }); + })); + console.log("===========> deleting files finished..."); + } + obsClient.close(); + console.log("=================sync files finished================================"); + } + + this.syncFolderToOBS = (options) => { + return getOBSFileList(checkSyncToOptions(options)).then(getChangedFileList).then(uploadFiles); + } + + this.syncFileToOBS = (options) => { + options = checkSyncFileToOptions(options); + return new Promise((resolver, reject) => { + let data = hexofs.readFileSync(options.localFileName, {escape: false, encoding: null}); + let obsClient = getObsClient(options); + obsClient.putObject({ + Bucket : options.bucket, + Key : options.remoteFileName, + SourceFile : options.localFileName, + ContentMD5: crypto.createHash('md5').update(data).digest("base64") + }, (err, result) => { + obsClient.close(); + if(err){ + console.error('upload file--> ' + item.obsKey + ', error, ' + err); + reject(err); + }else{ + console.error('upload file--> ' + item.obsKey + ', ' + result.CommonMsg.Status); + resolver(result.CommonMsg.Status); + } + }); + }); + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9329fa2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2362 @@ +{ + "name": "huaweicloud-obs-sync", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==" + }, + "bluebird": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", + "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==" + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.4", + "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.2.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-format": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-0.0.0.tgz", + "integrity": "sha1-CSBoY6sHDrRZrOpVQsvYVrEZZrM=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "2.2.4" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.1.0", + "repeat-element": "1.1.3", + "repeat-string": "1.6.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.20" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + } + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "0.2.2" + } + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "optional": true, + "requires": { + "nan": "2.11.1", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "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" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "optional": 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" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": 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" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "2.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hexo-fs": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/hexo-fs/-/hexo-fs-0.1.6.tgz", + "integrity": "sha1-+YDMw7x50PuS7dvYh7wgpWUA0D8=", + "requires": { + "bluebird": "3.5.2", + "chokidar": "1.7.0", + "escape-string-regexp": "1.0.5", + "graceful-fs": "4.1.11" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "1.12.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "log4js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-1.1.1.tgz", + "integrity": "sha1-wh0px2BAieTyVYM+f5SzRh3h/0M=", + "requires": { + "debug": "2.6.9", + "semver": "5.5.1", + "streamroller": "0.4.1" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "1.0.1" + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "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" + } + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "requires": { + "mime-db": "1.36.0" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "randomatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "4.1.11", + "micromatch": "3.1.10", + "readable-stream": "2.3.6" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.1.0", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.20", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "3.2.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "streamroller": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.4.1.tgz", + "integrity": "sha1-1DW9WXQ3Or2b2QaDWVEwhRBswF8=", + "requires": { + "date-format": "0.0.0", + "debug": "0.7.4", + "mkdirp": "0.5.1", + "readable-stream": "1.1.14" + }, + "dependencies": { + "debug": { + "version": "0.7.4", + "resolved": "http://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "1.1.29", + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "urlencode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/urlencode/-/urlencode-1.1.0.tgz", + "integrity": "sha1-HyuibwE8hfATP3o61v8nMK33y7c=", + "requires": { + "iconv-lite": "0.4.24" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": "1.2.4", + "xmlbuilder": "9.0.7" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7e55a2e --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "huaweicloud-obs-sync", + "version": "1.0.0", + "description": "sync files to huaweicloud obs.", + "repository": { + "type": "git", + "url": "git+https://github.com/ruanxinyu/huaweicloud-obs-sync.git" + }, + "homepage": "http://blog.ruanxinyu.cn", + "keywords": [ + "sync", + "huaweicloud-obs" + ], + "main": "lib/sync", + "author": "ruanxinyu", + "license": "MIT", + "dependencies": { + "bluebird": "^3.4.7", + "hexo-fs": "^0.1.6", + "log4js": "^1.1.1", + "xml2js": "^0.4.19", + "request": "^2.88.0", + "urlencode": "^1.1.0" + }, + "bugs": { + "url": "https://github.com/ruanxinyu/huaweicloud-obs-sync/issues" + }, + "directories": { + "lib": "lib" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + } +}