├── .cproject
├── .gitignore
├── .project
├── LICENSE
├── Makefile
├── README.md
├── components
├── .gitignore
└── cpp_utils
├── docs
├── design.md
├── images
│ ├── FileSystem.png
│ └── System.png
└── purpose.md
├── fatfs_data
├── ESP32Explorer.html
├── ESP32Explorer.js
├── images
│ ├── check.png
│ ├── cross.png
│ ├── in.png
│ ├── info.png
│ └── out.png
├── jQuery-File-Upload-9.18.0
│ ├── .gitignore
│ ├── .jshintrc
│ ├── .npmignore
│ ├── CONTRIBUTING.md
│ ├── LICENSE
│ ├── README.md
│ ├── angularjs.html
│ ├── basic-plus.html
│ ├── basic.html
│ ├── bower-version-update.js
│ ├── bower.json
│ ├── cors
│ │ ├── postmessage.html
│ │ └── result.html
│ ├── css
│ │ ├── demo-ie8.css
│ │ ├── demo.css
│ │ ├── jquery.fileupload-noscript.css
│ │ ├── jquery.fileupload-ui-noscript.css
│ │ ├── jquery.fileupload-ui.css
│ │ ├── jquery.fileupload.css
│ │ └── style.css
│ ├── img
│ │ ├── loading.gif
│ │ └── progressbar.gif
│ ├── index.html
│ ├── jquery-ui.html
│ ├── js
│ │ ├── app.js
│ │ ├── cors
│ │ │ ├── jquery.postmessage-transport.js
│ │ │ └── jquery.xdr-transport.js
│ │ ├── jquery.fileupload-angular.js
│ │ ├── jquery.fileupload-audio.js
│ │ ├── jquery.fileupload-image.js
│ │ ├── jquery.fileupload-jquery-ui.js
│ │ ├── jquery.fileupload-process.js
│ │ ├── jquery.fileupload-ui.js
│ │ ├── jquery.fileupload-validate.js
│ │ ├── jquery.fileupload-video.js
│ │ ├── jquery.fileupload.js
│ │ ├── jquery.iframe-transport.js
│ │ ├── main.js
│ │ └── vendor
│ │ │ └── jquery.ui.widget.js
│ ├── package.json
│ ├── server
│ │ ├── gae-go
│ │ │ ├── app.yaml
│ │ │ ├── app
│ │ │ │ └── main.go
│ │ │ └── static
│ │ │ │ ├── favicon.ico
│ │ │ │ └── robots.txt
│ │ ├── gae-python
│ │ │ ├── app.yaml
│ │ │ ├── main.py
│ │ │ └── static
│ │ │ │ ├── favicon.ico
│ │ │ │ └── robots.txt
│ │ └── php
│ │ │ ├── Dockerfile
│ │ │ ├── UploadHandler.php
│ │ │ ├── docker-compose.yml
│ │ │ ├── files
│ │ │ ├── .gitignore
│ │ │ └── .htaccess
│ │ │ └── index.php
│ └── test
│ │ ├── index.html
│ │ └── test.js
├── jquery
│ └── jquery-3.2.1.min.js
├── jqueryui
│ ├── AUTHORS.txt
│ ├── LICENSE.txt
│ ├── external
│ │ └── jquery
│ │ │ └── jquery.js
│ ├── images
│ │ ├── ui-icons_444444_256x240.png
│ │ ├── ui-icons_555555_256x240.png
│ │ ├── ui-icons_777620_256x240.png
│ │ ├── ui-icons_777777_256x240.png
│ │ ├── ui-icons_cc0000_256x240.png
│ │ └── ui-icons_ffffff_256x240.png
│ ├── index.html
│ ├── jquery-ui.css
│ ├── jquery-ui.js
│ ├── jquery-ui.min.css
│ ├── jquery-ui.min.js
│ ├── jquery-ui.structure.css
│ ├── jquery-ui.structure.min.css
│ ├── jquery-ui.theme.css
│ ├── jquery-ui.theme.min.css
│ └── package.json
└── jstree
│ ├── jstree.min.js
│ └── themes
│ ├── default-dark
│ ├── 32px.png
│ ├── 40px.png
│ ├── style.css
│ ├── style.min.css
│ └── throbber.gif
│ └── default
│ ├── 32px.png
│ ├── 40px.png
│ ├── style.css
│ ├── style.min.css
│ └── throbber.gif
├── main
├── BLEExplorer.cpp
├── BLEExplorer.h
├── BootWiFi.cpp
├── BootWiFi.h
├── ESP32Explorer.cpp
├── ESP32Explorer.h
├── FILESYSTEM_JSON.cpp
├── GPIO_JSON.cpp
├── I2C_COMMANDS.cpp
├── I2C_SCAN.cpp
├── I2S_JSON.cpp
├── SYSTEM_JSON.cpp
├── WIFI_JSON.cpp
├── common.h
├── component.mk
├── main.cpp
└── selectAP.h
├── partitions.csv
└── sdkconfig
/.cproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | sdkconfig.old
3 | .cproject
4 | .project
5 | .settings/
6 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | ESP32_Explorer
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 |
14 |
15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
16 | full,incremental,
17 |
18 |
19 |
20 |
21 |
22 | org.eclipse.cdt.core.cnature
23 | org.eclipse.cdt.core.ccnature
24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
26 |
27 |
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a
3 | # project subdirectory.
4 | #
5 |
6 | PROJECT_NAME := app-template
7 |
8 | include $(IDF_PATH)/make/project.mk
9 |
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## ESP32 Explorer
2 |
3 | ** WARNING!! - VERY EARLY CODE **
4 |
5 | A utility library / application for investigating the ESP32.
6 |
7 | Locked within an ESP32 at runtime is a wealth of information. This includes:
8 |
9 | * Your availabile memory
10 | * Your WiFi connections
11 | * Your GPIO status
12 | * The files on your flash file system
13 | * The status of your logging enablement
14 | * The partitions in use
15 | * The state of FreeRTOS tasks
16 | * and *much* more ...
17 |
18 | As I wrote applications to run on the ESP32, I found that from time to time I would need this information or wish to tweak some settings at runtime. I would inject code into my application, perform those tests and then remove it. As I wrote more applications, I found that I was repeating these steps over and over again. This notion became the kernel of this project.
19 |
20 | The purpose of the project is to produce a library which, when linked with your own application can reveal the content of your ESP32 at runtime **and** allow you to tweak settings.
21 |
22 | When linked with your application, it will start listening as a network endpoint (an HTTP server) to accept external calls for information and receive external calls to change state and data. In addition to the library you link with your ESP32 app, there is a web page that can be opened which presents the information in a series of tabbed pages.
23 |
24 | 
25 |
26 | Some pages have additional tabs on them.
27 |
28 | ## File System
29 | The File System page shows the file system found on the ESP32. From here you can see if the files you expect to be available are present. You also have the opportunity to upload new and updated files.
30 |
31 | 
--------------------------------------------------------------------------------
/components/.gitignore:
--------------------------------------------------------------------------------
1 | /cpp_utils/
2 |
--------------------------------------------------------------------------------
/components/cpp_utils:
--------------------------------------------------------------------------------
1 | /home/esp32/synchro/esp32-snippets/cpp_utils/
--------------------------------------------------------------------------------
/docs/design.md:
--------------------------------------------------------------------------------
1 | ## Design
2 | The library will run a Web Server. The files served by the Web Server will come from a file system contained
3 | in a partition. The files are supplied as part of the solution and are a mixture of HTML and JavaScript. When
4 | a browser connects to the ESP32 hosted Web Server, it is these files that are brought back to the browser and
5 | executed. The files will then present an attractive user interface for the user to navigate across the distinct
6 | parts of the ESP32 environment.
7 |
8 |
9 | ### File system
10 | The file system used is the FATFS supplied as part of ESP-IDF.
11 |
12 | ### Browser UI
13 | The browser UI is built from a mixture of HTML5, JavaScript, jQuery and jQuery UI. Additional open source components
14 | are used for specialized visualization including:
15 |
16 | * jstree
17 |
18 |
19 | ## Components
20 |
21 | ### File system
22 | The file system examination story uses standard IO functions to examine the file system directory structures. A
23 | JSON representation of the file system is built and sent back to the browser. The browser then examines the JSON
24 | data received and visualizes it through the "jstree" library,
25 |
26 |
--------------------------------------------------------------------------------
/docs/images/FileSystem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/docs/images/FileSystem.png
--------------------------------------------------------------------------------
/docs/images/System.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/docs/images/System.png
--------------------------------------------------------------------------------
/docs/purpose.md:
--------------------------------------------------------------------------------
1 | ## Purpose
2 | The core notion is that the library will expose a Web Server that will serve up information about the operation
3 | of the ESP32.
4 |
5 | The ESP32 can be thought of as having multiple separate internal functional areas. These include:
6 |
7 | * WiFi
8 | * GPIO
9 | * File systems
10 | * I2S
11 |
12 | In addition there is the ESP32 "System" itself which includes memory management, flash partitions and more.
13 |
14 | As an application that you may have written runs on the ESP32, we don't necessarily have good visibility into the state.
15 | We can, of course, attach debuggers and other useful tools but they pretty much give us insight into the operation
16 | and logic of your own application, and not the environment in which your application runs. This library can be linked
17 | with your own application to present the information you might otherwise not see.
--------------------------------------------------------------------------------
/fatfs_data/images/check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/images/check.png
--------------------------------------------------------------------------------
/fatfs_data/images/cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/images/cross.png
--------------------------------------------------------------------------------
/fatfs_data/images/in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/images/in.png
--------------------------------------------------------------------------------
/fatfs_data/images/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/images/info.png
--------------------------------------------------------------------------------
/fatfs_data/images/out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/images/out.png
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.pyc
3 | node_modules
4 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
3 | "camelcase" : true, // true: Identifiers must be in camelCase
4 | "curly" : true, // true: Require {} for every new block or scope
5 | "eqeqeq" : true, // true: Require triple equals (===) for comparison
6 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
7 | "immed" : true, // true: Require immediate invocations to be wrapped in parens
8 | // e.g. `(function () { } ());`
9 | "indent" : 4, // {int} Number of spaces to use for indentation
10 | "latedef" : true, // true: Require variables/functions to be defined before being used
11 | "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()`
12 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
13 | "noempty" : true, // true: Prohibit use of empty blocks
14 | "nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment)
15 | "plusplus" : false, // true: Prohibit use of `++` & `--`
16 | "quotmark" : "single", // Quotation mark consistency:
17 | // false : do nothing (default)
18 | // true : ensure whatever is used is consistent
19 | // "single" : require single quotes
20 | // "double" : require double quotes
21 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
22 | "unused" : true, // true: Require all defined variables be used
23 | "strict" : true, // true: Requires all functions run in ES5 Strict Mode
24 | "trailing" : true, // true: Prohibit trailing whitespaces
25 | "maxparams" : false, // {int} Max number of formal params allowed per function
26 | "maxdepth" : false, // {int} Max depth of nested blocks (within functions)
27 | "maxstatements" : false, // {int} Max number statements per function
28 | "maxcomplexity" : false, // {int} Max cyclomatic complexity per function
29 | "maxlen" : false, // {int} Max number of characters per line
30 |
31 | // Relaxing
32 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
33 | "boss" : false, // true: Tolerate assignments where comparisons would be expected
34 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
35 | "eqnull" : false, // true: Tolerate use of `== null`
36 | "es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
37 | "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
38 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
39 | // (ex: `for each`, multiple try/catch, function expression…)
40 | "evil" : false, // true: Tolerate use of `eval` and `new Function()`
41 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs
42 | "funcscope" : false, // true: Tolerate defining variables inside control statements"
43 | "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
44 | "iterator" : false, // true: Tolerate using the `__iterator__` property
45 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
46 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings
47 | "laxcomma" : false, // true: Tolerate comma-first style coding
48 | "loopfunc" : false, // true: Tolerate functions being defined in loops
49 | "multistr" : false, // true: Tolerate multi-line strings
50 | "proto" : false, // true: Tolerate using the `__proto__` property
51 | "scripturl" : false, // true: Tolerate script-targeted URLs
52 | "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
53 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
54 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
55 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
56 | "validthis" : false, // true: Tolerate using this in a non-constructor function
57 |
58 | // Environments
59 | "browser" : false, // Web Browser (window, document, etc)
60 | "couch" : false, // CouchDB
61 | "devel" : false, // Development/debugging (alert, confirm, etc)
62 | "dojo" : false, // Dojo Toolkit
63 | "jquery" : false, // jQuery
64 | "mootools" : false, // MooTools
65 | "node" : false, // Node.js
66 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
67 | "prototypejs" : false, // Prototype and Scriptaculous
68 | "rhino" : false, // Rhino
69 | "worker" : false, // Web Workers
70 | "wsh" : false, // Windows Scripting Host
71 | "yui" : false, // Yahoo User Interface
72 |
73 | // Legacy
74 | "nomen" : true, // true: Prohibit dangling `_` in variables
75 | "onevar" : true, // true: Allow only one `var` statement per function
76 | "passfail" : false, // true: Stop on first error
77 | "white" : true, // true: Check against strict whitespace and indentation rules
78 |
79 | // Custom Globals
80 | "globals" : {} // additional predefined global variables
81 | }
82 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/.npmignore:
--------------------------------------------------------------------------------
1 | *
2 | !css/jquery.fileupload-noscript.css
3 | !css/jquery.fileupload-ui-noscript.css
4 | !css/jquery.fileupload-ui.css
5 | !css/jquery.fileupload.css
6 | !img/loading.gif
7 | !img/progressbar.gif
8 | !js/cors/jquery.postmessage-transport.js
9 | !js/cors/jquery.xdr-transport.js
10 | !js/vendor/jquery.ui.widget.js
11 | !js/jquery.fileupload-angular.js
12 | !js/jquery.fileupload-audio.js
13 | !js/jquery.fileupload-image.js
14 | !js/jquery.fileupload-jquery-ui.js
15 | !js/jquery.fileupload-process.js
16 | !js/jquery.fileupload-ui.js
17 | !js/jquery.fileupload-validate.js
18 | !js/jquery.fileupload-video.js
19 | !js/jquery.fileupload.js
20 | !js/jquery.iframe-transport.js
21 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Please follow these pull request guidelines:
2 |
3 | 1. Update your fork to the latest upstream version.
4 |
5 | 2. Follow the coding conventions of the original source files (indentation, spaces, brackets layout).
6 |
7 | 3. Code changes must pass JSHint validation with the `.jshintrc` settings of this project.
8 |
9 | 4. Code changes must pass the QUnit tests defined in the `test` folder.
10 |
11 | 5. New features should be covered by accompanying QUnit tests.
12 |
13 | 6. Keep your commits as atomic as possible, i.e. create a new commit for every single bug fix or feature added.
14 |
15 | 7. Always add meaningful commit messages.
16 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 jQuery-File-Upload Authors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/README.md:
--------------------------------------------------------------------------------
1 | # jQuery File Upload Plugin
2 |
3 | ## Demo
4 | [Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
5 |
6 | ## Description
7 | File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery.
8 | Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
9 |
10 | ## Setup
11 | * [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
12 | * [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
13 |
14 | ## Features
15 | * **Multiple file upload:**
16 | Allows to select multiple files at once and upload them simultaneously.
17 | * **Drag & Drop support:**
18 | Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window.
19 | * **Upload progress bar:**
20 | Shows a progress bar indicating the upload progress for individual files and for all uploads combined.
21 | * **Cancelable uploads:**
22 | Individual file uploads can be canceled to stop the upload progress.
23 | * **Resumable uploads:**
24 | Aborted uploads can be resumed with browsers supporting the Blob API.
25 | * **Chunked uploads:**
26 | Large files can be uploaded in smaller chunks with browsers supporting the Blob API.
27 | * **Client-side image resizing:**
28 | Images can be automatically resized on client-side with browsers supporting the required JS APIs.
29 | * **Preview images, audio and video:**
30 | A preview of image, audio and video files can be displayed before uploading with browsers supporting the required APIs.
31 | * **No browser plugins (e.g. Adobe Flash) required:**
32 | The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins.
33 | * **Graceful fallback for legacy browsers:**
34 | Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers.
35 | * **HTML file upload form fallback:**
36 | Allows progressive enhancement by using a standard HTML file upload form as widget element.
37 | * **Cross-site file uploads:**
38 | Supports uploading files to a different domain with cross-site XMLHttpRequests or iframe redirects.
39 | * **Multiple plugin instances:**
40 | Allows to use multiple plugin instances on the same webpage.
41 | * **Customizable and extensible:**
42 | Provides an API to set individual options and define callBack methods for various upload events.
43 | * **Multipart and file contents stream uploads:**
44 | Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload).
45 | * **Compatible with any server-side application platform:**
46 | Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
47 |
48 | ## Requirements
49 |
50 | ### Mandatory requirements
51 | * [jQuery](https://jquery.com/) v. 1.6+
52 | * [jQuery UI widget factory](https://api.jqueryui.com/jQuery.widget/) v. 1.9+ (included): Required for the basic File Upload plugin, but very lightweight without any other dependencies from the jQuery UI suite.
53 | * [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) (included): Required for [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
54 |
55 | ### Optional requirements
56 | * [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates) v. 2.5.4+: Used to render the selected and uploaded files for the Basic Plus UI and jQuery UI versions.
57 | * [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image) v. 1.13.0+: Required for the image previews and resizing functionality.
58 | * [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob) v. 2.1.1+:Required for the image previews and resizing functionality.
59 | * [blueimp Gallery](https://github.com/blueimp/Gallery) v. 2.15.1+: Used to display the uploaded images in a lightbox.
60 | * [Bootstrap](http://getbootstrap.com/) v. 3.2.0+
61 | * [Glyphicons](http://glyphicons.com/)
62 |
63 | The user interface of all versions except the jQuery UI version is built with [Bootstrap](http://getbootstrap.com/) and icons from [Glyphicons](http://glyphicons.com/).
64 |
65 | ### Cross-domain requirements
66 | [Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads) using the [Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) require a redirect back to the origin server to retrieve the upload results. The [example implementation](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/main.js) makes use of [result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html) as a static redirect page for the origin server.
67 |
68 | The repository also includes the [jQuery XDomainRequest Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/cors/jquery.xdr-transport.js), which enables limited cross-domain AJAX requests in Microsoft Internet Explorer 8 and 9 (IE 10 supports cross-domain XHR requests).
69 | The XDomainRequest object allows GET and POST requests only and doesn't support file uploads. It is used on the [Demo](https://blueimp.github.io/jQuery-File-Upload/) to delete uploaded files from the cross-domain demo file upload service.
70 |
71 | ### Custom Backends
72 |
73 | You can add support for various backends by adhering to the specification [outlined here](https://github.com/blueimp/jQuery-File-Upload/wiki/JSON-Response).
74 |
75 | ## Browsers
76 |
77 | ### Desktop browsers
78 | The File Upload plugin is regularly tested with the latest browser versions and supports the following minimal versions:
79 |
80 | * Google Chrome
81 | * Apple Safari 4.0+
82 | * Mozilla Firefox 3.0+
83 | * Opera 11.0+
84 | * Microsoft Internet Explorer 6.0+
85 |
86 | ### Mobile browsers
87 | The File Upload plugin has been tested with and supports the following mobile browsers:
88 |
89 | * Apple Safari on iOS 6.0+
90 | * Google Chrome on iOS 6.0+
91 | * Google Chrome on Android 4.0+
92 | * Default Browser on Android 2.3+
93 | * Opera Mobile 12.0+
94 |
95 | ### Supported features
96 | For a detailed overview of the features supported by each browser version, please have a look at the [Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
97 |
98 | ## Contributing
99 | **Bug fixes** and **new features** can be proposed using [pull requests](https://github.com/blueimp/jQuery-File-Upload/pulls).
100 | Please read the [contribution guidelines](https://github.com/blueimp/jQuery-File-Upload/blob/master/CONTRIBUTING.md) before submitting a pull request.
101 |
102 | ## Support
103 | This project is actively maintained, but there is no official support channel.
104 | If you have a question that another developer might help you with, please post to [Stack Overflow](http://stackoverflow.com/questions/tagged/blueimp+jquery+file-upload) and tag your question with `blueimp jquery file upload`.
105 |
106 | ## License
107 | Released under the [MIT license](https://opensource.org/licenses/MIT).
108 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/basic-plus.html:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
17 |
18 |
19 | jQuery File Upload Demo - Basic Plus version
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
50 |
51 |
jQuery File Upload Demo
52 |
Basic Plus version
53 |
60 |
61 |
62 | File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery.
63 | Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
64 | Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
65 |
66 |
67 |
68 |
69 |
70 | Add files...
71 |
72 |
73 |
74 |
75 |
76 |
77 |
80 |
81 |
82 |
83 |
84 |
85 |
Demo Notes
86 |
87 |
88 |
89 | The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
90 | Only image files (JPG, GIF, PNG ) are allowed in this demo (by default there is no file type restriction).
91 | Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
92 | You can drag & drop files from your desktop on this webpage (see Browser support ).
93 | Please refer to the project website and documentation for more information.
94 | Built with the Bootstrap CSS framework and Icons from Glyphicons .
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
225 |
226 |
227 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/basic.html:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
17 |
18 |
19 | jQuery File Upload Demo - Basic version
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
50 |
51 |
jQuery File Upload Demo
52 |
Basic version
53 |
60 |
61 |
62 | File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery.
63 | Supports cross-domain, chunked and resumable file uploads.
64 | Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
65 |
66 |
67 |
68 |
69 |
70 | Select files...
71 |
72 |
73 |
74 |
75 |
76 |
77 |
80 |
81 |
82 |
83 |
84 |
85 |
Demo Notes
86 |
87 |
88 |
89 | The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
90 | Only image files (JPG, GIF, PNG ) are allowed in this demo (by default there is no file type restriction).
91 | Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
92 | You can drag & drop files from your desktop on this webpage (see Browser support ).
93 | Please refer to the project website and documentation for more information.
94 | Built with the Bootstrap CSS framework and Icons from Glyphicons .
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/bower-version-update.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | 'use strict';
4 |
5 | var path = require('path');
6 | var packageJSON = require(path.join(__dirname, 'package.json'));
7 | var bowerFile = path.join(__dirname, 'bower.json');
8 | var bowerJSON = require('bower-json').parse(
9 | require(bowerFile),
10 | {normalize: true}
11 | );
12 | bowerJSON.version = packageJSON.version;
13 | require('fs').writeFileSync(
14 | bowerFile,
15 | JSON.stringify(bowerJSON, null, 2) + '\n'
16 | );
17 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blueimp-file-upload",
3 | "version": "9.18.0",
4 | "title": "jQuery File Upload",
5 | "description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images.",
6 | "keywords": [
7 | "jquery",
8 | "file",
9 | "upload",
10 | "widget",
11 | "multiple",
12 | "selection",
13 | "drag",
14 | "drop",
15 | "progress",
16 | "preview",
17 | "cross-domain",
18 | "cross-site",
19 | "chunk",
20 | "resume",
21 | "gae",
22 | "go",
23 | "python",
24 | "php",
25 | "bootstrap"
26 | ],
27 | "homepage": "https://github.com/blueimp/jQuery-File-Upload",
28 | "author": {
29 | "name": "Sebastian Tschan",
30 | "url": "https://blueimp.net"
31 | },
32 | "maintainers": [
33 | {
34 | "name": "Sebastian Tschan",
35 | "url": "https://blueimp.net"
36 | }
37 | ],
38 | "repository": {
39 | "type": "git",
40 | "url": "git://github.com/blueimp/jQuery-File-Upload.git"
41 | },
42 | "bugs": "https://github.com/blueimp/jQuery-File-Upload/issues",
43 | "license": "MIT",
44 | "dependencies": {
45 | "jquery": ">=1.6",
46 | "blueimp-tmpl": ">=2.5.4",
47 | "blueimp-load-image": ">=1.13.0",
48 | "blueimp-canvas-to-blob": ">=2.1.1"
49 | },
50 | "main": [
51 | "js/jquery.fileupload.js"
52 | ],
53 | "ignore": [
54 | "/*.*",
55 | "/cors",
56 | "css/demo-ie8.css",
57 | "css/demo.css",
58 | "css/style.css",
59 | "js/app.js",
60 | "js/main.js",
61 | "server",
62 | "test"
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/cors/postmessage.html:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
17 | jQuery File Upload Plugin postMessage API
18 |
19 |
20 |
21 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/cors/result.html:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
17 | jQuery Iframe Transport Plugin Redirect Page
18 |
19 |
20 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/css/demo-ie8.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /*
3 | * jQuery File Upload Demo CSS Fixes for IE<9
4 | * https://github.com/blueimp/jQuery-File-Upload
5 | *
6 | * Copyright 2013, Sebastian Tschan
7 | * https://blueimp.net
8 | *
9 | * Licensed under the MIT license:
10 | * https://opensource.org/licenses/MIT
11 | */
12 |
13 | .navigation {
14 | list-style: none;
15 | padding: 0;
16 | margin: 1em 0;
17 | }
18 | .navigation li {
19 | display: inline;
20 | margin-right: 10px;
21 | }
22 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/css/demo.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /*
3 | * jQuery File Upload Demo CSS
4 | * https://github.com/blueimp/jQuery-File-Upload
5 | *
6 | * Copyright 2013, Sebastian Tschan
7 | * https://blueimp.net
8 | *
9 | * Licensed under the MIT license:
10 | * https://opensource.org/licenses/MIT
11 | */
12 |
13 | body {
14 | max-width: 750px;
15 | margin: 0 auto;
16 | padding: 1em;
17 | font-family: "Lucida Grande", "Lucida Sans Unicode", Arial, sans-serif;
18 | font-size: 1em;
19 | line-height: 1.4em;
20 | background: #222;
21 | color: #fff;
22 | -webkit-text-size-adjust: 100%;
23 | -ms-text-size-adjust: 100%;
24 | }
25 | a {
26 | color: orange;
27 | text-decoration: none;
28 | }
29 | img {
30 | border: 0;
31 | vertical-align: middle;
32 | }
33 | h1 {
34 | line-height: 1em;
35 | }
36 | blockquote {
37 | padding: 0 0 0 15px;
38 | margin: 0 0 20px;
39 | border-left: 5px solid #eee;
40 | }
41 | table {
42 | width: 100%;
43 | margin: 10px 0;
44 | }
45 |
46 | .fileupload-progress {
47 | margin: 10px 0;
48 | }
49 | .fileupload-progress .progress-extended {
50 | margin-top: 5px;
51 | }
52 | .error {
53 | color: red;
54 | }
55 |
56 | @media (min-width: 481px) {
57 | .navigation {
58 | list-style: none;
59 | padding: 0;
60 | }
61 | .navigation li {
62 | display: inline-block;
63 | }
64 | .navigation li:not(:first-child):before {
65 | content: "| ";
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/css/jquery.fileupload-noscript.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /*
3 | * jQuery File Upload Plugin NoScript CSS
4 | * https://github.com/blueimp/jQuery-File-Upload
5 | *
6 | * Copyright 2013, Sebastian Tschan
7 | * https://blueimp.net
8 | *
9 | * Licensed under the MIT license:
10 | * https://opensource.org/licenses/MIT
11 | */
12 |
13 | .fileinput-button input {
14 | position: static;
15 | opacity: 1;
16 | filter: none;
17 | font-size: inherit !important;
18 | direction: inherit;
19 | }
20 | .fileinput-button span {
21 | display: none;
22 | }
23 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/css/jquery.fileupload-ui-noscript.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /*
3 | * jQuery File Upload UI Plugin NoScript CSS
4 | * https://github.com/blueimp/jQuery-File-Upload
5 | *
6 | * Copyright 2012, Sebastian Tschan
7 | * https://blueimp.net
8 | *
9 | * Licensed under the MIT license:
10 | * https://opensource.org/licenses/MIT
11 | */
12 |
13 | .fileinput-button i,
14 | .fileupload-buttonbar .delete,
15 | .fileupload-buttonbar .toggle {
16 | display: none;
17 | }
18 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/css/jquery.fileupload-ui.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /*
3 | * jQuery File Upload UI Plugin CSS
4 | * https://github.com/blueimp/jQuery-File-Upload
5 | *
6 | * Copyright 2010, Sebastian Tschan
7 | * https://blueimp.net
8 | *
9 | * Licensed under the MIT license:
10 | * https://opensource.org/licenses/MIT
11 | */
12 |
13 | .fileupload-buttonbar .btn,
14 | .fileupload-buttonbar .toggle {
15 | margin-bottom: 5px;
16 | }
17 | .progress-animated .progress-bar,
18 | .progress-animated .bar {
19 | background: url("../img/progressbar.gif") !important;
20 | filter: none;
21 | }
22 | .fileupload-process {
23 | float: right;
24 | display: none;
25 | }
26 | .fileupload-processing .fileupload-process,
27 | .files .processing .preview {
28 | display: block;
29 | width: 32px;
30 | height: 32px;
31 | background: url("../img/loading.gif") center no-repeat;
32 | background-size: contain;
33 | }
34 | .files audio,
35 | .files video {
36 | max-width: 300px;
37 | }
38 |
39 | @media (max-width: 767px) {
40 | .fileupload-buttonbar .toggle,
41 | .files .toggle,
42 | .files .btn span {
43 | display: none;
44 | }
45 | .files .name {
46 | width: 80px;
47 | word-wrap: break-word;
48 | }
49 | .files audio,
50 | .files video {
51 | max-width: 80px;
52 | }
53 | .files img,
54 | .files canvas {
55 | max-width: 100%;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/css/jquery.fileupload.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /*
3 | * jQuery File Upload Plugin CSS
4 | * https://github.com/blueimp/jQuery-File-Upload
5 | *
6 | * Copyright 2013, Sebastian Tschan
7 | * https://blueimp.net
8 | *
9 | * Licensed under the MIT license:
10 | * https://opensource.org/licenses/MIT
11 | */
12 |
13 | .fileinput-button {
14 | position: relative;
15 | overflow: hidden;
16 | display: inline-block;
17 | }
18 | .fileinput-button input {
19 | position: absolute;
20 | top: 0;
21 | right: 0;
22 | margin: 0;
23 | opacity: 0;
24 | -ms-filter: 'alpha(opacity=0)';
25 | font-size: 200px !important;
26 | direction: ltr;
27 | cursor: pointer;
28 | }
29 |
30 | /* Fixes for IE < 8 */
31 | @media screen\9 {
32 | .fileinput-button input {
33 | filter: alpha(opacity=0);
34 | font-size: 100%;
35 | height: 100%;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/css/style.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /*
3 | * jQuery File Upload Plugin CSS Example
4 | * https://github.com/blueimp/jQuery-File-Upload
5 | *
6 | * Copyright 2013, Sebastian Tschan
7 | * https://blueimp.net
8 | *
9 | * Licensed under the MIT license:
10 | * https://opensource.org/licenses/MIT
11 | */
12 |
13 | body {
14 | padding-top: 60px;
15 | }
16 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jQuery-File-Upload-9.18.0/img/loading.gif
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/img/progressbar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jQuery-File-Upload-9.18.0/img/progressbar.gif
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/app.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery File Upload Plugin Angular JS Example
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* jshint nomen:false */
13 | /* global window, angular */
14 |
15 | ;(function () {
16 | 'use strict';
17 |
18 | var isOnGitHub = window.location.hostname === 'blueimp.github.io',
19 | url = isOnGitHub ? '//jquery-file-upload.appspot.com/' : 'server/php/';
20 |
21 | angular.module('demo', [
22 | 'blueimp.fileupload'
23 | ])
24 | .config([
25 | '$httpProvider', 'fileUploadProvider',
26 | function ($httpProvider, fileUploadProvider) {
27 | delete $httpProvider.defaults.headers.common['X-Requested-With'];
28 | fileUploadProvider.defaults.redirect = window.location.href.replace(
29 | /\/[^\/]*$/,
30 | '/cors/result.html?%s'
31 | );
32 | if (isOnGitHub) {
33 | // Demo settings:
34 | angular.extend(fileUploadProvider.defaults, {
35 | // Enable image resizing, except for Android and Opera,
36 | // which actually support image resizing, but fail to
37 | // send Blob objects via XHR requests:
38 | disableImageResize: /Android(?!.*Chrome)|Opera/
39 | .test(window.navigator.userAgent),
40 | maxFileSize: 999000,
41 | acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
42 | });
43 | }
44 | }
45 | ])
46 |
47 | .controller('DemoFileUploadController', [
48 | '$scope', '$http', '$filter', '$window',
49 | function ($scope, $http) {
50 | $scope.options = {
51 | url: url
52 | };
53 | if (!isOnGitHub) {
54 | $scope.loadingFiles = true;
55 | $http.get(url)
56 | .then(
57 | function (response) {
58 | $scope.loadingFiles = false;
59 | $scope.queue = response.data.files || [];
60 | },
61 | function () {
62 | $scope.loadingFiles = false;
63 | }
64 | );
65 | }
66 | }
67 | ])
68 |
69 | .controller('FileDestroyController', [
70 | '$scope', '$http',
71 | function ($scope, $http) {
72 | var file = $scope.file,
73 | state;
74 | if (file.url) {
75 | file.$state = function () {
76 | return state;
77 | };
78 | file.$destroy = function () {
79 | state = 'pending';
80 | return $http({
81 | url: file.deleteUrl,
82 | method: file.deleteType
83 | }).then(
84 | function () {
85 | state = 'resolved';
86 | $scope.clear(file);
87 | },
88 | function () {
89 | state = 'rejected';
90 | }
91 | );
92 | };
93 | } else if (!file.$cancel && !file._index) {
94 | file.$cancel = function () {
95 | $scope.clear(file);
96 | };
97 | }
98 | }
99 | ]);
100 |
101 | }());
102 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/cors/jquery.postmessage-transport.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery postMessage Transport Plugin
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2011, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* global define, require, window, document */
13 |
14 | ;(function (factory) {
15 | 'use strict';
16 | if (typeof define === 'function' && define.amd) {
17 | // Register as an anonymous AMD module:
18 | define(['jquery'], factory);
19 | } else if (typeof exports === 'object') {
20 | // Node/CommonJS:
21 | factory(require('jquery'));
22 | } else {
23 | // Browser globals:
24 | factory(window.jQuery);
25 | }
26 | }(function ($) {
27 | 'use strict';
28 |
29 | var counter = 0,
30 | names = [
31 | 'accepts',
32 | 'cache',
33 | 'contents',
34 | 'contentType',
35 | 'crossDomain',
36 | 'data',
37 | 'dataType',
38 | 'headers',
39 | 'ifModified',
40 | 'mimeType',
41 | 'password',
42 | 'processData',
43 | 'timeout',
44 | 'traditional',
45 | 'type',
46 | 'url',
47 | 'username'
48 | ],
49 | convert = function (p) {
50 | return p;
51 | };
52 |
53 | $.ajaxSetup({
54 | converters: {
55 | 'postmessage text': convert,
56 | 'postmessage json': convert,
57 | 'postmessage html': convert
58 | }
59 | });
60 |
61 | $.ajaxTransport('postmessage', function (options) {
62 | if (options.postMessage && window.postMessage) {
63 | var iframe,
64 | loc = $('').prop('href', options.postMessage)[0],
65 | target = loc.protocol + '//' + loc.host,
66 | xhrUpload = options.xhr().upload;
67 | // IE always includes the port for the host property of a link
68 | // element, but not in the location.host or origin property for the
69 | // default http port 80 and https port 443, so we strip it:
70 | if (/^(http:\/\/.+:80)|(https:\/\/.+:443)$/.test(target)) {
71 | target = target.replace(/:(80|443)$/, '');
72 | }
73 | return {
74 | send: function (_, completeCallback) {
75 | counter += 1;
76 | var message = {
77 | id: 'postmessage-transport-' + counter
78 | },
79 | eventName = 'message.' + message.id;
80 | iframe = $(
81 | ''
84 | ).bind('load', function () {
85 | $.each(names, function (i, name) {
86 | message[name] = options[name];
87 | });
88 | message.dataType = message.dataType.replace('postmessage ', '');
89 | $(window).bind(eventName, function (e) {
90 | e = e.originalEvent;
91 | var data = e.data,
92 | ev;
93 | if (e.origin === target && data.id === message.id) {
94 | if (data.type === 'progress') {
95 | ev = document.createEvent('Event');
96 | ev.initEvent(data.type, false, true);
97 | $.extend(ev, data);
98 | xhrUpload.dispatchEvent(ev);
99 | } else {
100 | completeCallback(
101 | data.status,
102 | data.statusText,
103 | {postmessage: data.result},
104 | data.headers
105 | );
106 | iframe.remove();
107 | $(window).unbind(eventName);
108 | }
109 | }
110 | });
111 | iframe[0].contentWindow.postMessage(
112 | message,
113 | target
114 | );
115 | }).appendTo(document.body);
116 | },
117 | abort: function () {
118 | if (iframe) {
119 | iframe.remove();
120 | }
121 | }
122 | };
123 | }
124 | });
125 |
126 | }));
127 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/cors/jquery.xdr-transport.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery XDomainRequest Transport Plugin
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2011, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | *
11 | * Based on Julian Aubourg's ajaxHooks xdr.js:
12 | * https://github.com/jaubourg/ajaxHooks/
13 | */
14 |
15 | /* global define, require, window, XDomainRequest */
16 |
17 | ;(function (factory) {
18 | 'use strict';
19 | if (typeof define === 'function' && define.amd) {
20 | // Register as an anonymous AMD module:
21 | define(['jquery'], factory);
22 | } else if (typeof exports === 'object') {
23 | // Node/CommonJS:
24 | factory(require('jquery'));
25 | } else {
26 | // Browser globals:
27 | factory(window.jQuery);
28 | }
29 | }(function ($) {
30 | 'use strict';
31 | if (window.XDomainRequest && !$.support.cors) {
32 | $.ajaxTransport(function (s) {
33 | if (s.crossDomain && s.async) {
34 | if (s.timeout) {
35 | s.xdrTimeout = s.timeout;
36 | delete s.timeout;
37 | }
38 | var xdr;
39 | return {
40 | send: function (headers, completeCallback) {
41 | var addParamChar = /\?/.test(s.url) ? '&' : '?';
42 | function callback(status, statusText, responses, responseHeaders) {
43 | xdr.onload = xdr.onerror = xdr.ontimeout = $.noop;
44 | xdr = null;
45 | completeCallback(status, statusText, responses, responseHeaders);
46 | }
47 | xdr = new XDomainRequest();
48 | // XDomainRequest only supports GET and POST:
49 | if (s.type === 'DELETE') {
50 | s.url = s.url + addParamChar + '_method=DELETE';
51 | s.type = 'POST';
52 | } else if (s.type === 'PUT') {
53 | s.url = s.url + addParamChar + '_method=PUT';
54 | s.type = 'POST';
55 | } else if (s.type === 'PATCH') {
56 | s.url = s.url + addParamChar + '_method=PATCH';
57 | s.type = 'POST';
58 | }
59 | xdr.open(s.type, s.url);
60 | xdr.onload = function () {
61 | callback(
62 | 200,
63 | 'OK',
64 | {text: xdr.responseText},
65 | 'Content-Type: ' + xdr.contentType
66 | );
67 | };
68 | xdr.onerror = function () {
69 | callback(404, 'Not Found');
70 | };
71 | if (s.xdrTimeout) {
72 | xdr.ontimeout = function () {
73 | callback(0, 'timeout');
74 | };
75 | xdr.timeout = s.xdrTimeout;
76 | }
77 | xdr.send((s.hasContent && s.data) || null);
78 | },
79 | abort: function () {
80 | if (xdr) {
81 | xdr.onerror = $.noop();
82 | xdr.abort();
83 | }
84 | }
85 | };
86 | }
87 | });
88 | }
89 | }));
90 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/jquery.fileupload-audio.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery File Upload Audio Preview Plugin
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* jshint nomen:false */
13 | /* global define, require, window, document */
14 |
15 | ;(function (factory) {
16 | 'use strict';
17 | if (typeof define === 'function' && define.amd) {
18 | // Register as an anonymous AMD module:
19 | define([
20 | 'jquery',
21 | 'load-image',
22 | './jquery.fileupload-process'
23 | ], factory);
24 | } else if (typeof exports === 'object') {
25 | // Node/CommonJS:
26 | factory(
27 | require('jquery'),
28 | require('blueimp-load-image/js/load-image'),
29 | require('./jquery.fileupload-process')
30 | );
31 | } else {
32 | // Browser globals:
33 | factory(
34 | window.jQuery,
35 | window.loadImage
36 | );
37 | }
38 | }(function ($, loadImage) {
39 | 'use strict';
40 |
41 | // Prepend to the default processQueue:
42 | $.blueimp.fileupload.prototype.options.processQueue.unshift(
43 | {
44 | action: 'loadAudio',
45 | // Use the action as prefix for the "@" options:
46 | prefix: true,
47 | fileTypes: '@',
48 | maxFileSize: '@',
49 | disabled: '@disableAudioPreview'
50 | },
51 | {
52 | action: 'setAudio',
53 | name: '@audioPreviewName',
54 | disabled: '@disableAudioPreview'
55 | }
56 | );
57 |
58 | // The File Upload Audio Preview plugin extends the fileupload widget
59 | // with audio preview functionality:
60 | $.widget('blueimp.fileupload', $.blueimp.fileupload, {
61 |
62 | options: {
63 | // The regular expression for the types of audio files to load,
64 | // matched against the file type:
65 | loadAudioFileTypes: /^audio\/.*$/
66 | },
67 |
68 | _audioElement: document.createElement('audio'),
69 |
70 | processActions: {
71 |
72 | // Loads the audio file given via data.files and data.index
73 | // as audio element if the browser supports playing it.
74 | // Accepts the options fileTypes (regular expression)
75 | // and maxFileSize (integer) to limit the files to load:
76 | loadAudio: function (data, options) {
77 | if (options.disabled) {
78 | return data;
79 | }
80 | var file = data.files[data.index],
81 | url,
82 | audio;
83 | if (this._audioElement.canPlayType &&
84 | this._audioElement.canPlayType(file.type) &&
85 | ($.type(options.maxFileSize) !== 'number' ||
86 | file.size <= options.maxFileSize) &&
87 | (!options.fileTypes ||
88 | options.fileTypes.test(file.type))) {
89 | url = loadImage.createObjectURL(file);
90 | if (url) {
91 | audio = this._audioElement.cloneNode(false);
92 | audio.src = url;
93 | audio.controls = true;
94 | data.audio = audio;
95 | return data;
96 | }
97 | }
98 | return data;
99 | },
100 |
101 | // Sets the audio element as a property of the file object:
102 | setAudio: function (data, options) {
103 | if (data.audio && !options.disabled) {
104 | data.files[data.index][options.name || 'preview'] = data.audio;
105 | }
106 | return data;
107 | }
108 |
109 | }
110 |
111 | });
112 |
113 | }));
114 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/jquery.fileupload-jquery-ui.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery File Upload jQuery UI Plugin
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* jshint nomen:false */
13 | /* global define, require, window */
14 |
15 | ;(function (factory) {
16 | 'use strict';
17 | if (typeof define === 'function' && define.amd) {
18 | // Register as an anonymous AMD module:
19 | define([
20 | 'jquery',
21 | './jquery.fileupload-ui'
22 | ], factory);
23 | } else if (typeof exports === 'object') {
24 | // Node/CommonJS:
25 | factory(
26 | require('jquery'),
27 | require('./jquery.fileupload-ui')
28 | );
29 | } else {
30 | // Browser globals:
31 | factory(window.jQuery);
32 | }
33 | }(function ($) {
34 | 'use strict';
35 |
36 | $.widget('blueimp.fileupload', $.blueimp.fileupload, {
37 |
38 | options: {
39 | processdone: function (e, data) {
40 | data.context.find('.start').button('enable');
41 | },
42 | progress: function (e, data) {
43 | if (data.context) {
44 | data.context.find('.progress').progressbar(
45 | 'option',
46 | 'value',
47 | parseInt(data.loaded / data.total * 100, 10)
48 | );
49 | }
50 | },
51 | progressall: function (e, data) {
52 | var $this = $(this);
53 | $this.find('.fileupload-progress')
54 | .find('.progress').progressbar(
55 | 'option',
56 | 'value',
57 | parseInt(data.loaded / data.total * 100, 10)
58 | ).end()
59 | .find('.progress-extended').each(function () {
60 | $(this).html(
61 | ($this.data('blueimp-fileupload') ||
62 | $this.data('fileupload'))
63 | ._renderExtendedProgress(data)
64 | );
65 | });
66 | }
67 | },
68 |
69 | _renderUpload: function (func, files) {
70 | var node = this._super(func, files),
71 | showIconText = $(window).width() > 480;
72 | node.find('.progress').empty().progressbar();
73 | node.find('.start').button({
74 | icons: {primary: 'ui-icon-circle-arrow-e'},
75 | text: showIconText
76 | });
77 | node.find('.cancel').button({
78 | icons: {primary: 'ui-icon-cancel'},
79 | text: showIconText
80 | });
81 | if (node.hasClass('fade')) {
82 | node.hide();
83 | }
84 | return node;
85 | },
86 |
87 | _renderDownload: function (func, files) {
88 | var node = this._super(func, files),
89 | showIconText = $(window).width() > 480;
90 | node.find('.delete').button({
91 | icons: {primary: 'ui-icon-trash'},
92 | text: showIconText
93 | });
94 | if (node.hasClass('fade')) {
95 | node.hide();
96 | }
97 | return node;
98 | },
99 |
100 | _startHandler: function (e) {
101 | $(e.currentTarget).button('disable');
102 | this._super(e);
103 | },
104 |
105 | _transition: function (node) {
106 | var deferred = $.Deferred();
107 | if (node.hasClass('fade')) {
108 | node.fadeToggle(
109 | this.options.transitionDuration,
110 | this.options.transitionEasing,
111 | function () {
112 | deferred.resolveWith(node);
113 | }
114 | );
115 | } else {
116 | deferred.resolveWith(node);
117 | }
118 | return deferred;
119 | },
120 |
121 | _create: function () {
122 | this._super();
123 | this.element
124 | .find('.fileupload-buttonbar')
125 | .find('.fileinput-button').each(function () {
126 | var input = $(this).find('input:file').detach();
127 | $(this)
128 | .button({icons: {primary: 'ui-icon-plusthick'}})
129 | .append(input);
130 | })
131 | .end().find('.start')
132 | .button({icons: {primary: 'ui-icon-circle-arrow-e'}})
133 | .end().find('.cancel')
134 | .button({icons: {primary: 'ui-icon-cancel'}})
135 | .end().find('.delete')
136 | .button({icons: {primary: 'ui-icon-trash'}})
137 | .end().find('.progress').progressbar();
138 | },
139 |
140 | _destroy: function () {
141 | this.element
142 | .find('.fileupload-buttonbar')
143 | .find('.fileinput-button').each(function () {
144 | var input = $(this).find('input:file').detach();
145 | $(this)
146 | .button('destroy')
147 | .append(input);
148 | })
149 | .end().find('.start')
150 | .button('destroy')
151 | .end().find('.cancel')
152 | .button('destroy')
153 | .end().find('.delete')
154 | .button('destroy')
155 | .end().find('.progress').progressbar('destroy');
156 | this._super();
157 | }
158 |
159 | });
160 |
161 | }));
162 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/jquery.fileupload-process.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery File Upload Processing Plugin
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2012, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* jshint nomen:false */
13 | /* global define, require, window */
14 |
15 | ;(function (factory) {
16 | 'use strict';
17 | if (typeof define === 'function' && define.amd) {
18 | // Register as an anonymous AMD module:
19 | define([
20 | 'jquery',
21 | './jquery.fileupload'
22 | ], factory);
23 | } else if (typeof exports === 'object') {
24 | // Node/CommonJS:
25 | factory(
26 | require('jquery'),
27 | require('./jquery.fileupload')
28 | );
29 | } else {
30 | // Browser globals:
31 | factory(
32 | window.jQuery
33 | );
34 | }
35 | }(function ($) {
36 | 'use strict';
37 |
38 | var originalAdd = $.blueimp.fileupload.prototype.options.add;
39 |
40 | // The File Upload Processing plugin extends the fileupload widget
41 | // with file processing functionality:
42 | $.widget('blueimp.fileupload', $.blueimp.fileupload, {
43 |
44 | options: {
45 | // The list of processing actions:
46 | processQueue: [
47 | /*
48 | {
49 | action: 'log',
50 | type: 'debug'
51 | }
52 | */
53 | ],
54 | add: function (e, data) {
55 | var $this = $(this);
56 | data.process(function () {
57 | return $this.fileupload('process', data);
58 | });
59 | originalAdd.call(this, e, data);
60 | }
61 | },
62 |
63 | processActions: {
64 | /*
65 | log: function (data, options) {
66 | console[options.type](
67 | 'Processing "' + data.files[data.index].name + '"'
68 | );
69 | }
70 | */
71 | },
72 |
73 | _processFile: function (data, originalData) {
74 | var that = this,
75 | dfd = $.Deferred().resolveWith(that, [data]),
76 | chain = dfd.promise();
77 | this._trigger('process', null, data);
78 | $.each(data.processQueue, function (i, settings) {
79 | var func = function (data) {
80 | if (originalData.errorThrown) {
81 | return $.Deferred()
82 | .rejectWith(that, [originalData]).promise();
83 | }
84 | return that.processActions[settings.action].call(
85 | that,
86 | data,
87 | settings
88 | );
89 | };
90 | chain = chain.then(func, settings.always && func);
91 | });
92 | chain
93 | .done(function () {
94 | that._trigger('processdone', null, data);
95 | that._trigger('processalways', null, data);
96 | })
97 | .fail(function () {
98 | that._trigger('processfail', null, data);
99 | that._trigger('processalways', null, data);
100 | });
101 | return chain;
102 | },
103 |
104 | // Replaces the settings of each processQueue item that
105 | // are strings starting with an "@", using the remaining
106 | // substring as key for the option map,
107 | // e.g. "@autoUpload" is replaced with options.autoUpload:
108 | _transformProcessQueue: function (options) {
109 | var processQueue = [];
110 | $.each(options.processQueue, function () {
111 | var settings = {},
112 | action = this.action,
113 | prefix = this.prefix === true ? action : this.prefix;
114 | $.each(this, function (key, value) {
115 | if ($.type(value) === 'string' &&
116 | value.charAt(0) === '@') {
117 | settings[key] = options[
118 | value.slice(1) || (prefix ? prefix +
119 | key.charAt(0).toUpperCase() + key.slice(1) : key)
120 | ];
121 | } else {
122 | settings[key] = value;
123 | }
124 |
125 | });
126 | processQueue.push(settings);
127 | });
128 | options.processQueue = processQueue;
129 | },
130 |
131 | // Returns the number of files currently in the processsing queue:
132 | processing: function () {
133 | return this._processing;
134 | },
135 |
136 | // Processes the files given as files property of the data parameter,
137 | // returns a Promise object that allows to bind callbacks:
138 | process: function (data) {
139 | var that = this,
140 | options = $.extend({}, this.options, data);
141 | if (options.processQueue && options.processQueue.length) {
142 | this._transformProcessQueue(options);
143 | if (this._processing === 0) {
144 | this._trigger('processstart');
145 | }
146 | $.each(data.files, function (index) {
147 | var opts = index ? $.extend({}, options) : options,
148 | func = function () {
149 | if (data.errorThrown) {
150 | return $.Deferred()
151 | .rejectWith(that, [data]).promise();
152 | }
153 | return that._processFile(opts, data);
154 | };
155 | opts.index = index;
156 | that._processing += 1;
157 | that._processingQueue = that._processingQueue.then(func, func)
158 | .always(function () {
159 | that._processing -= 1;
160 | if (that._processing === 0) {
161 | that._trigger('processstop');
162 | }
163 | });
164 | });
165 | }
166 | return this._processingQueue;
167 | },
168 |
169 | _create: function () {
170 | this._super();
171 | this._processing = 0;
172 | this._processingQueue = $.Deferred().resolveWith(this)
173 | .promise();
174 | }
175 |
176 | });
177 |
178 | }));
179 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/jquery.fileupload-validate.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery File Upload Validation Plugin
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* global define, require, window */
13 |
14 | ;(function (factory) {
15 | 'use strict';
16 | if (typeof define === 'function' && define.amd) {
17 | // Register as an anonymous AMD module:
18 | define([
19 | 'jquery',
20 | './jquery.fileupload-process'
21 | ], factory);
22 | } else if (typeof exports === 'object') {
23 | // Node/CommonJS:
24 | factory(
25 | require('jquery'),
26 | require('./jquery.fileupload-process')
27 | );
28 | } else {
29 | // Browser globals:
30 | factory(
31 | window.jQuery
32 | );
33 | }
34 | }(function ($) {
35 | 'use strict';
36 |
37 | // Append to the default processQueue:
38 | $.blueimp.fileupload.prototype.options.processQueue.push(
39 | {
40 | action: 'validate',
41 | // Always trigger this action,
42 | // even if the previous action was rejected:
43 | always: true,
44 | // Options taken from the global options map:
45 | acceptFileTypes: '@',
46 | maxFileSize: '@',
47 | minFileSize: '@',
48 | maxNumberOfFiles: '@',
49 | disabled: '@disableValidation'
50 | }
51 | );
52 |
53 | // The File Upload Validation plugin extends the fileupload widget
54 | // with file validation functionality:
55 | $.widget('blueimp.fileupload', $.blueimp.fileupload, {
56 |
57 | options: {
58 | /*
59 | // The regular expression for allowed file types, matches
60 | // against either file type or file name:
61 | acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
62 | // The maximum allowed file size in bytes:
63 | maxFileSize: 10000000, // 10 MB
64 | // The minimum allowed file size in bytes:
65 | minFileSize: undefined, // No minimal file size
66 | // The limit of files to be uploaded:
67 | maxNumberOfFiles: 10,
68 | */
69 |
70 | // Function returning the current number of files,
71 | // has to be overriden for maxNumberOfFiles validation:
72 | getNumberOfFiles: $.noop,
73 |
74 | // Error and info messages:
75 | messages: {
76 | maxNumberOfFiles: 'Maximum number of files exceeded',
77 | acceptFileTypes: 'File type not allowed',
78 | maxFileSize: 'File is too large',
79 | minFileSize: 'File is too small'
80 | }
81 | },
82 |
83 | processActions: {
84 |
85 | validate: function (data, options) {
86 | if (options.disabled) {
87 | return data;
88 | }
89 | var dfd = $.Deferred(),
90 | settings = this.options,
91 | file = data.files[data.index],
92 | fileSize;
93 | if (options.minFileSize || options.maxFileSize) {
94 | fileSize = file.size;
95 | }
96 | if ($.type(options.maxNumberOfFiles) === 'number' &&
97 | (settings.getNumberOfFiles() || 0) + data.files.length >
98 | options.maxNumberOfFiles) {
99 | file.error = settings.i18n('maxNumberOfFiles');
100 | } else if (options.acceptFileTypes &&
101 | !(options.acceptFileTypes.test(file.type) ||
102 | options.acceptFileTypes.test(file.name))) {
103 | file.error = settings.i18n('acceptFileTypes');
104 | } else if (fileSize > options.maxFileSize) {
105 | file.error = settings.i18n('maxFileSize');
106 | } else if ($.type(fileSize) === 'number' &&
107 | fileSize < options.minFileSize) {
108 | file.error = settings.i18n('minFileSize');
109 | } else {
110 | delete file.error;
111 | }
112 | if (file.error || data.files.error) {
113 | data.files.error = true;
114 | dfd.rejectWith(this, [data]);
115 | } else {
116 | dfd.resolveWith(this, [data]);
117 | }
118 | return dfd.promise();
119 | }
120 |
121 | }
122 |
123 | });
124 |
125 | }));
126 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/jquery.fileupload-video.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery File Upload Video Preview Plugin
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2013, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* jshint nomen:false */
13 | /* global define, require, window, document */
14 |
15 | ;(function (factory) {
16 | 'use strict';
17 | if (typeof define === 'function' && define.amd) {
18 | // Register as an anonymous AMD module:
19 | define([
20 | 'jquery',
21 | 'load-image',
22 | './jquery.fileupload-process'
23 | ], factory);
24 | } else if (typeof exports === 'object') {
25 | // Node/CommonJS:
26 | factory(
27 | require('jquery'),
28 | require('blueimp-load-image/js/load-image'),
29 | require('./jquery.fileupload-process')
30 | );
31 | } else {
32 | // Browser globals:
33 | factory(
34 | window.jQuery,
35 | window.loadImage
36 | );
37 | }
38 | }(function ($, loadImage) {
39 | 'use strict';
40 |
41 | // Prepend to the default processQueue:
42 | $.blueimp.fileupload.prototype.options.processQueue.unshift(
43 | {
44 | action: 'loadVideo',
45 | // Use the action as prefix for the "@" options:
46 | prefix: true,
47 | fileTypes: '@',
48 | maxFileSize: '@',
49 | disabled: '@disableVideoPreview'
50 | },
51 | {
52 | action: 'setVideo',
53 | name: '@videoPreviewName',
54 | disabled: '@disableVideoPreview'
55 | }
56 | );
57 |
58 | // The File Upload Video Preview plugin extends the fileupload widget
59 | // with video preview functionality:
60 | $.widget('blueimp.fileupload', $.blueimp.fileupload, {
61 |
62 | options: {
63 | // The regular expression for the types of video files to load,
64 | // matched against the file type:
65 | loadVideoFileTypes: /^video\/.*$/
66 | },
67 |
68 | _videoElement: document.createElement('video'),
69 |
70 | processActions: {
71 |
72 | // Loads the video file given via data.files and data.index
73 | // as video element if the browser supports playing it.
74 | // Accepts the options fileTypes (regular expression)
75 | // and maxFileSize (integer) to limit the files to load:
76 | loadVideo: function (data, options) {
77 | if (options.disabled) {
78 | return data;
79 | }
80 | var file = data.files[data.index],
81 | url,
82 | video;
83 | if (this._videoElement.canPlayType &&
84 | this._videoElement.canPlayType(file.type) &&
85 | ($.type(options.maxFileSize) !== 'number' ||
86 | file.size <= options.maxFileSize) &&
87 | (!options.fileTypes ||
88 | options.fileTypes.test(file.type))) {
89 | url = loadImage.createObjectURL(file);
90 | if (url) {
91 | video = this._videoElement.cloneNode(false);
92 | video.src = url;
93 | video.controls = true;
94 | data.video = video;
95 | return data;
96 | }
97 | }
98 | return data;
99 | },
100 |
101 | // Sets the video element as a property of the file object:
102 | setVideo: function (data, options) {
103 | if (data.video && !options.disabled) {
104 | data.files[data.index][options.name || 'preview'] = data.video;
105 | }
106 | return data;
107 | }
108 |
109 | }
110 |
111 | });
112 |
113 | }));
114 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/jquery.iframe-transport.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Iframe Transport Plugin
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2011, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* global define, require, window, document, JSON */
13 |
14 | ;(function (factory) {
15 | 'use strict';
16 | if (typeof define === 'function' && define.amd) {
17 | // Register as an anonymous AMD module:
18 | define(['jquery'], factory);
19 | } else if (typeof exports === 'object') {
20 | // Node/CommonJS:
21 | factory(require('jquery'));
22 | } else {
23 | // Browser globals:
24 | factory(window.jQuery);
25 | }
26 | }(function ($) {
27 | 'use strict';
28 |
29 | // Helper variable to create unique names for the transport iframes:
30 | var counter = 0,
31 | jsonAPI = $,
32 | jsonParse = 'parseJSON';
33 |
34 | if ('JSON' in window && 'parse' in JSON) {
35 | jsonAPI = JSON;
36 | jsonParse = 'parse';
37 | }
38 |
39 | // The iframe transport accepts four additional options:
40 | // options.fileInput: a jQuery collection of file input fields
41 | // options.paramName: the parameter name for the file form data,
42 | // overrides the name property of the file input field(s),
43 | // can be a string or an array of strings.
44 | // options.formData: an array of objects with name and value properties,
45 | // equivalent to the return data of .serializeArray(), e.g.:
46 | // [{name: 'a', value: 1}, {name: 'b', value: 2}]
47 | // options.initialIframeSrc: the URL of the initial iframe src,
48 | // by default set to "javascript:false;"
49 | $.ajaxTransport('iframe', function (options) {
50 | if (options.async) {
51 | // javascript:false as initial iframe src
52 | // prevents warning popups on HTTPS in IE6:
53 | /*jshint scripturl: true */
54 | var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
55 | /*jshint scripturl: false */
56 | form,
57 | iframe,
58 | addParamChar;
59 | return {
60 | send: function (_, completeCallback) {
61 | form = $('');
62 | form.attr('accept-charset', options.formAcceptCharset);
63 | addParamChar = /\?/.test(options.url) ? '&' : '?';
64 | // XDomainRequest only supports GET and POST:
65 | if (options.type === 'DELETE') {
66 | options.url = options.url + addParamChar + '_method=DELETE';
67 | options.type = 'POST';
68 | } else if (options.type === 'PUT') {
69 | options.url = options.url + addParamChar + '_method=PUT';
70 | options.type = 'POST';
71 | } else if (options.type === 'PATCH') {
72 | options.url = options.url + addParamChar + '_method=PATCH';
73 | options.type = 'POST';
74 | }
75 | // IE versions below IE8 cannot set the name property of
76 | // elements that have already been added to the DOM,
77 | // so we set the name along with the iframe HTML markup:
78 | counter += 1;
79 | iframe = $(
80 | ''
82 | ).bind('load', function () {
83 | var fileInputClones,
84 | paramNames = $.isArray(options.paramName) ?
85 | options.paramName : [options.paramName];
86 | iframe
87 | .unbind('load')
88 | .bind('load', function () {
89 | var response;
90 | // Wrap in a try/catch block to catch exceptions thrown
91 | // when trying to access cross-domain iframe contents:
92 | try {
93 | response = iframe.contents();
94 | // Google Chrome and Firefox do not throw an
95 | // exception when calling iframe.contents() on
96 | // cross-domain requests, so we unify the response:
97 | if (!response.length || !response[0].firstChild) {
98 | throw new Error();
99 | }
100 | } catch (e) {
101 | response = undefined;
102 | }
103 | // The complete callback returns the
104 | // iframe content document as response object:
105 | completeCallback(
106 | 200,
107 | 'success',
108 | {'iframe': response}
109 | );
110 | // Fix for IE endless progress bar activity bug
111 | // (happens on form submits to iframe targets):
112 | $('')
113 | .appendTo(form);
114 | window.setTimeout(function () {
115 | // Removing the form in a setTimeout call
116 | // allows Chrome's developer tools to display
117 | // the response result
118 | form.remove();
119 | }, 0);
120 | });
121 | form
122 | .prop('target', iframe.prop('name'))
123 | .prop('action', options.url)
124 | .prop('method', options.type);
125 | if (options.formData) {
126 | $.each(options.formData, function (index, field) {
127 | $(' ')
128 | .prop('name', field.name)
129 | .val(field.value)
130 | .appendTo(form);
131 | });
132 | }
133 | if (options.fileInput && options.fileInput.length &&
134 | options.type === 'POST') {
135 | fileInputClones = options.fileInput.clone();
136 | // Insert a clone for each file input field:
137 | options.fileInput.after(function (index) {
138 | return fileInputClones[index];
139 | });
140 | if (options.paramName) {
141 | options.fileInput.each(function (index) {
142 | $(this).prop(
143 | 'name',
144 | paramNames[index] || options.paramName
145 | );
146 | });
147 | }
148 | // Appending the file input fields to the hidden form
149 | // removes them from their original location:
150 | form
151 | .append(options.fileInput)
152 | .prop('enctype', 'multipart/form-data')
153 | // enctype must be set as encoding for IE:
154 | .prop('encoding', 'multipart/form-data');
155 | // Remove the HTML5 form attribute from the input(s):
156 | options.fileInput.removeAttr('form');
157 | }
158 | form.submit();
159 | // Insert the file input fields at their original location
160 | // by replacing the clones with the originals:
161 | if (fileInputClones && fileInputClones.length) {
162 | options.fileInput.each(function (index, input) {
163 | var clone = $(fileInputClones[index]);
164 | // Restore the original name and form properties:
165 | $(input)
166 | .prop('name', clone.prop('name'))
167 | .attr('form', clone.attr('form'));
168 | clone.replaceWith(input);
169 | });
170 | }
171 | });
172 | form.append(iframe).appendTo(document.body);
173 | },
174 | abort: function () {
175 | if (iframe) {
176 | // javascript:false as iframe src aborts the request
177 | // and prevents warning popups on HTTPS in IE6.
178 | // concat is used to avoid the "Script URL" JSLint error:
179 | iframe
180 | .unbind('load')
181 | .prop('src', initialIframeSrc);
182 | }
183 | if (form) {
184 | form.remove();
185 | }
186 | }
187 | };
188 | }
189 | });
190 |
191 | // The iframe transport returns the iframe content document as response.
192 | // The following adds converters from iframe to text, json, html, xml
193 | // and script.
194 | // Please note that the Content-Type for JSON responses has to be text/plain
195 | // or text/html, if the browser doesn't include application/json in the
196 | // Accept header, else IE will show a download dialog.
197 | // The Content-Type for XML responses on the other hand has to be always
198 | // application/xml or text/xml, so IE properly parses the XML response.
199 | // See also
200 | // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation
201 | $.ajaxSetup({
202 | converters: {
203 | 'iframe text': function (iframe) {
204 | return iframe && $(iframe[0].body).text();
205 | },
206 | 'iframe json': function (iframe) {
207 | return iframe && jsonAPI[jsonParse]($(iframe[0].body).text());
208 | },
209 | 'iframe html': function (iframe) {
210 | return iframe && $(iframe[0].body).html();
211 | },
212 | 'iframe xml': function (iframe) {
213 | var xmlDoc = iframe && iframe[0];
214 | return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc :
215 | $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||
216 | $(xmlDoc.body).html());
217 | },
218 | 'iframe script': function (iframe) {
219 | return iframe && $.globalEval($(iframe[0].body).text());
220 | }
221 | }
222 | });
223 |
224 | }));
225 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/js/main.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery File Upload Plugin JS Example
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2010, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | /* global $, window */
13 |
14 | $(function () {
15 | 'use strict';
16 |
17 | // Initialize the jQuery File Upload widget:
18 | $('#fileupload').fileupload({
19 | // Uncomment the following to send cross-domain cookies:
20 | //xhrFields: {withCredentials: true},
21 | url: 'server/php/'
22 | });
23 |
24 | // Enable iframe cross-domain access via redirect option:
25 | $('#fileupload').fileupload(
26 | 'option',
27 | 'redirect',
28 | window.location.href.replace(
29 | /\/[^\/]*$/,
30 | '/cors/result.html?%s'
31 | )
32 | );
33 |
34 | if (window.location.hostname === 'blueimp.github.io') {
35 | // Demo settings:
36 | $('#fileupload').fileupload('option', {
37 | url: '//jquery-file-upload.appspot.com/',
38 | // Enable image resizing, except for Android and Opera,
39 | // which actually support image resizing, but fail to
40 | // send Blob objects via XHR requests:
41 | disableImageResize: /Android(?!.*Chrome)|Opera/
42 | .test(window.navigator.userAgent),
43 | maxFileSize: 999000,
44 | acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
45 | });
46 | // Upload server status check for browsers with CORS support:
47 | if ($.support.cors) {
48 | $.ajax({
49 | url: '//jquery-file-upload.appspot.com/',
50 | type: 'HEAD'
51 | }).fail(function () {
52 | $('
')
53 | .text('Upload server currently unavailable - ' +
54 | new Date())
55 | .appendTo('#fileupload');
56 | });
57 | }
58 | } else {
59 | // Load existing files:
60 | $('#fileupload').addClass('fileupload-processing');
61 | $.ajax({
62 | // Uncomment the following to send cross-domain cookies:
63 | //xhrFields: {withCredentials: true},
64 | url: $('#fileupload').fileupload('option', 'url'),
65 | dataType: 'json',
66 | context: $('#fileupload')[0]
67 | }).always(function () {
68 | $(this).removeClass('fileupload-processing');
69 | }).done(function (result) {
70 | $(this).fileupload('option', 'done')
71 | .call(this, $.Event('done'), {result: result});
72 | });
73 | }
74 |
75 | });
76 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blueimp-file-upload",
3 | "version": "9.18.0",
4 | "title": "jQuery File Upload",
5 | "description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
6 | "keywords": [
7 | "jquery",
8 | "file",
9 | "upload",
10 | "widget",
11 | "multiple",
12 | "selection",
13 | "drag",
14 | "drop",
15 | "progress",
16 | "preview",
17 | "cross-domain",
18 | "cross-site",
19 | "chunk",
20 | "resume",
21 | "gae",
22 | "go",
23 | "python",
24 | "php",
25 | "bootstrap"
26 | ],
27 | "homepage": "https://github.com/blueimp/jQuery-File-Upload",
28 | "author": {
29 | "name": "Sebastian Tschan",
30 | "url": "https://blueimp.net"
31 | },
32 | "repository": {
33 | "type": "git",
34 | "url": "git://github.com/blueimp/jQuery-File-Upload.git"
35 | },
36 | "license": "MIT",
37 | "optionalDependencies": {
38 | "blueimp-canvas-to-blob": "3.5.0",
39 | "blueimp-load-image": "2.12.2",
40 | "blueimp-tmpl": "3.6.0"
41 | },
42 | "devDependencies": {
43 | "bower-json": "0.8.1",
44 | "jshint": "2.9.3"
45 | },
46 | "scripts": {
47 | "bower-version-update": "./bower-version-update.js",
48 | "lint": "jshint *.js js/*.js js/cors/*.js",
49 | "test": "npm run lint",
50 | "preversion": "npm test",
51 | "version": "npm run bower-version-update && git add bower.json",
52 | "postversion": "git push --tags origin master && npm publish"
53 | },
54 | "main": "js/jquery.fileupload.js"
55 | }
56 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-go/app.yaml:
--------------------------------------------------------------------------------
1 | application: jquery-file-upload
2 | version: 2
3 | runtime: go
4 | api_version: go1
5 |
6 | handlers:
7 | - url: /(favicon\.ico|robots\.txt)
8 | static_files: static/\1
9 | upload: static/(.*)
10 | expiration: '1d'
11 | - url: /.*
12 | script: _go_app
13 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-go/app/main.go:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery File Upload Plugin GAE Go Example
3 | * https://github.com/blueimp/jQuery-File-Upload
4 | *
5 | * Copyright 2011, Sebastian Tschan
6 | * https://blueimp.net
7 | *
8 | * Licensed under the MIT license:
9 | * https://opensource.org/licenses/MIT
10 | */
11 |
12 | package app
13 |
14 | import (
15 | "bufio"
16 | "bytes"
17 | "encoding/json"
18 | "fmt"
19 | "github.com/disintegration/gift"
20 | "golang.org/x/net/context"
21 | "google.golang.org/appengine"
22 | "google.golang.org/appengine/memcache"
23 | "hash/crc32"
24 | "image"
25 | "image/gif"
26 | "image/jpeg"
27 | "image/png"
28 | "io"
29 | "log"
30 | "mime/multipart"
31 | "net/http"
32 | "net/url"
33 | "path/filepath"
34 | "regexp"
35 | "strings"
36 | )
37 |
38 | const (
39 | WEBSITE = "https://blueimp.github.io/jQuery-File-Upload/"
40 | MIN_FILE_SIZE = 1 // bytes
41 | // Max file size is memcache limit (1MB) minus key size minus overhead:
42 | MAX_FILE_SIZE = 999000 // bytes
43 | IMAGE_TYPES = "image/(gif|p?jpeg|(x-)?png)"
44 | ACCEPT_FILE_TYPES = IMAGE_TYPES
45 | THUMB_MAX_WIDTH = 80
46 | THUMB_MAX_HEIGHT = 80
47 | EXPIRATION_TIME = 300 // seconds
48 | // If empty, only allow redirects to the referer protocol+host.
49 | // Set to a regexp string for custom pattern matching:
50 | REDIRECT_ALLOW_TARGET = ""
51 | )
52 |
53 | var (
54 | imageTypes = regexp.MustCompile(IMAGE_TYPES)
55 | acceptFileTypes = regexp.MustCompile(ACCEPT_FILE_TYPES)
56 | thumbSuffix = "." + fmt.Sprint(THUMB_MAX_WIDTH) + "x" +
57 | fmt.Sprint(THUMB_MAX_HEIGHT)
58 | )
59 |
60 | func escape(s string) string {
61 | return strings.Replace(url.QueryEscape(s), "+", "%20", -1)
62 | }
63 |
64 | func extractKey(r *http.Request) string {
65 | // Use RequestURI instead of r.URL.Path, as we need the encoded form:
66 | path := strings.Split(r.RequestURI, "?")[0]
67 | // Also adjust double encoded slashes:
68 | return strings.Replace(path[1:], "%252F", "%2F", -1)
69 | }
70 |
71 | func check(err error) {
72 | if err != nil {
73 | panic(err)
74 | }
75 | }
76 |
77 | type FileInfo struct {
78 | Key string `json:"-"`
79 | ThumbnailKey string `json:"-"`
80 | Url string `json:"url,omitempty"`
81 | ThumbnailUrl string `json:"thumbnailUrl,omitempty"`
82 | Name string `json:"name"`
83 | Type string `json:"type"`
84 | Size int64 `json:"size"`
85 | Error string `json:"error,omitempty"`
86 | DeleteUrl string `json:"deleteUrl,omitempty"`
87 | DeleteType string `json:"deleteType,omitempty"`
88 | }
89 |
90 | func (fi *FileInfo) ValidateType() (valid bool) {
91 | if acceptFileTypes.MatchString(fi.Type) {
92 | return true
93 | }
94 | fi.Error = "Filetype not allowed"
95 | return false
96 | }
97 |
98 | func (fi *FileInfo) ValidateSize() (valid bool) {
99 | if fi.Size < MIN_FILE_SIZE {
100 | fi.Error = "File is too small"
101 | } else if fi.Size > MAX_FILE_SIZE {
102 | fi.Error = "File is too big"
103 | } else {
104 | return true
105 | }
106 | return false
107 | }
108 |
109 | func (fi *FileInfo) CreateUrls(r *http.Request, c context.Context) {
110 | u := &url.URL{
111 | Scheme: r.URL.Scheme,
112 | Host: appengine.DefaultVersionHostname(c),
113 | Path: "/",
114 | }
115 | uString := u.String()
116 | fi.Url = uString + fi.Key
117 | fi.DeleteUrl = fi.Url
118 | fi.DeleteType = "DELETE"
119 | if fi.ThumbnailKey != "" {
120 | fi.ThumbnailUrl = uString + fi.ThumbnailKey
121 | }
122 | }
123 |
124 | func (fi *FileInfo) SetKey(checksum uint32) {
125 | fi.Key = escape(string(fi.Type)) + "/" +
126 | escape(fmt.Sprint(checksum)) + "/" +
127 | escape(string(fi.Name))
128 | }
129 |
130 | func (fi *FileInfo) createThumb(buffer *bytes.Buffer, c context.Context) {
131 | if imageTypes.MatchString(fi.Type) {
132 | src, _, err := image.Decode(bytes.NewReader(buffer.Bytes()))
133 | check(err)
134 | filter := gift.New(gift.ResizeToFit(
135 | THUMB_MAX_WIDTH,
136 | THUMB_MAX_HEIGHT,
137 | gift.LanczosResampling,
138 | ))
139 | dst := image.NewNRGBA(filter.Bounds(src.Bounds()))
140 | filter.Draw(dst, src)
141 | buffer.Reset()
142 | bWriter := bufio.NewWriter(buffer)
143 | switch fi.Type {
144 | case "image/jpeg", "image/pjpeg":
145 | err = jpeg.Encode(bWriter, dst, nil)
146 | case "image/gif":
147 | err = gif.Encode(bWriter, dst, nil)
148 | default:
149 | err = png.Encode(bWriter, dst)
150 | }
151 | check(err)
152 | bWriter.Flush()
153 | thumbnailKey := fi.Key + thumbSuffix + filepath.Ext(fi.Name)
154 | item := &memcache.Item{
155 | Key: thumbnailKey,
156 | Value: buffer.Bytes(),
157 | }
158 | err = memcache.Set(c, item)
159 | check(err)
160 | fi.ThumbnailKey = thumbnailKey
161 | }
162 | }
163 |
164 | func handleUpload(r *http.Request, p *multipart.Part) (fi *FileInfo) {
165 | fi = &FileInfo{
166 | Name: p.FileName(),
167 | Type: p.Header.Get("Content-Type"),
168 | }
169 | if !fi.ValidateType() {
170 | return
171 | }
172 | defer func() {
173 | if rec := recover(); rec != nil {
174 | log.Println(rec)
175 | fi.Error = rec.(error).Error()
176 | }
177 | }()
178 | var buffer bytes.Buffer
179 | hash := crc32.NewIEEE()
180 | mw := io.MultiWriter(&buffer, hash)
181 | lr := &io.LimitedReader{R: p, N: MAX_FILE_SIZE + 1}
182 | _, err := io.Copy(mw, lr)
183 | check(err)
184 | fi.Size = MAX_FILE_SIZE + 1 - lr.N
185 | if !fi.ValidateSize() {
186 | return
187 | }
188 | fi.SetKey(hash.Sum32())
189 | item := &memcache.Item{
190 | Key: fi.Key,
191 | Value: buffer.Bytes(),
192 | }
193 | context := appengine.NewContext(r)
194 | err = memcache.Set(context, item)
195 | check(err)
196 | fi.createThumb(&buffer, context)
197 | fi.CreateUrls(r, context)
198 | return
199 | }
200 |
201 | func getFormValue(p *multipart.Part) string {
202 | var b bytes.Buffer
203 | io.CopyN(&b, p, int64(1<<20)) // Copy max: 1 MiB
204 | return b.String()
205 | }
206 |
207 | func handleUploads(r *http.Request) (fileInfos []*FileInfo) {
208 | fileInfos = make([]*FileInfo, 0)
209 | mr, err := r.MultipartReader()
210 | check(err)
211 | r.Form, err = url.ParseQuery(r.URL.RawQuery)
212 | check(err)
213 | part, err := mr.NextPart()
214 | for err == nil {
215 | if name := part.FormName(); name != "" {
216 | if part.FileName() != "" {
217 | fileInfos = append(fileInfos, handleUpload(r, part))
218 | } else {
219 | r.Form[name] = append(r.Form[name], getFormValue(part))
220 | }
221 | }
222 | part, err = mr.NextPart()
223 | }
224 | return
225 | }
226 |
227 | func validateRedirect(r *http.Request, redirect string) bool {
228 | if redirect != "" {
229 | var redirectAllowTarget *regexp.Regexp
230 | if REDIRECT_ALLOW_TARGET != "" {
231 | redirectAllowTarget = regexp.MustCompile(REDIRECT_ALLOW_TARGET)
232 | } else {
233 | referer := r.Referer()
234 | if referer == "" {
235 | return false
236 | }
237 | refererUrl, err := url.Parse(referer)
238 | if err != nil {
239 | return false
240 | }
241 | redirectAllowTarget = regexp.MustCompile("^" + regexp.QuoteMeta(
242 | refererUrl.Scheme+"://"+refererUrl.Host+"/",
243 | ))
244 | }
245 | return redirectAllowTarget.MatchString(redirect)
246 | }
247 | return false
248 | }
249 |
250 | func get(w http.ResponseWriter, r *http.Request) {
251 | if r.URL.Path == "/" {
252 | http.Redirect(w, r, WEBSITE, http.StatusFound)
253 | return
254 | }
255 | // Use RequestURI instead of r.URL.Path, as we need the encoded form:
256 | key := extractKey(r)
257 | parts := strings.Split(key, "/")
258 | if len(parts) == 3 {
259 | context := appengine.NewContext(r)
260 | item, err := memcache.Get(context, key)
261 | if err == nil {
262 | w.Header().Add("X-Content-Type-Options", "nosniff")
263 | contentType, _ := url.QueryUnescape(parts[0])
264 | if !imageTypes.MatchString(contentType) {
265 | contentType = "application/octet-stream"
266 | }
267 | w.Header().Add("Content-Type", contentType)
268 | w.Header().Add(
269 | "Cache-Control",
270 | fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME),
271 | )
272 | w.Write(item.Value)
273 | return
274 | }
275 | }
276 | http.Error(w, "404 Not Found", http.StatusNotFound)
277 | }
278 |
279 | func post(w http.ResponseWriter, r *http.Request) {
280 | result := make(map[string][]*FileInfo, 1)
281 | result["files"] = handleUploads(r)
282 | b, err := json.Marshal(result)
283 | check(err)
284 | if redirect := r.FormValue("redirect"); validateRedirect(r, redirect) {
285 | if strings.Contains(redirect, "%s") {
286 | redirect = fmt.Sprintf(
287 | redirect,
288 | escape(string(b)),
289 | )
290 | }
291 | http.Redirect(w, r, redirect, http.StatusFound)
292 | return
293 | }
294 | w.Header().Set("Cache-Control", "no-cache")
295 | jsonType := "application/json"
296 | if strings.Index(r.Header.Get("Accept"), jsonType) != -1 {
297 | w.Header().Set("Content-Type", jsonType)
298 | }
299 | fmt.Fprintln(w, string(b))
300 | }
301 |
302 | func delete(w http.ResponseWriter, r *http.Request) {
303 | key := extractKey(r)
304 | parts := strings.Split(key, "/")
305 | if len(parts) == 3 {
306 | result := make(map[string]bool, 1)
307 | context := appengine.NewContext(r)
308 | err := memcache.Delete(context, key)
309 | if err == nil {
310 | result[key] = true
311 | contentType, _ := url.QueryUnescape(parts[0])
312 | if imageTypes.MatchString(contentType) {
313 | thumbnailKey := key + thumbSuffix + filepath.Ext(parts[2])
314 | err := memcache.Delete(context, thumbnailKey)
315 | if err == nil {
316 | result[thumbnailKey] = true
317 | }
318 | }
319 | }
320 | w.Header().Set("Content-Type", "application/json")
321 | b, err := json.Marshal(result)
322 | check(err)
323 | fmt.Fprintln(w, string(b))
324 | } else {
325 | http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed)
326 | }
327 | }
328 |
329 | func handle(w http.ResponseWriter, r *http.Request) {
330 | params, err := url.ParseQuery(r.URL.RawQuery)
331 | check(err)
332 | w.Header().Add("Access-Control-Allow-Origin", "*")
333 | w.Header().Add(
334 | "Access-Control-Allow-Methods",
335 | "OPTIONS, HEAD, GET, POST, DELETE",
336 | )
337 | w.Header().Add(
338 | "Access-Control-Allow-Headers",
339 | "Content-Type, Content-Range, Content-Disposition",
340 | )
341 | switch r.Method {
342 | case "OPTIONS", "HEAD":
343 | return
344 | case "GET":
345 | get(w, r)
346 | case "POST":
347 | if len(params["_method"]) > 0 && params["_method"][0] == "DELETE" {
348 | delete(w, r)
349 | } else {
350 | post(w, r)
351 | }
352 | case "DELETE":
353 | delete(w, r)
354 | default:
355 | http.Error(w, "501 Not Implemented", http.StatusNotImplemented)
356 | }
357 | }
358 |
359 | func init() {
360 | http.HandleFunc("/", handle)
361 | }
362 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-go/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-go/static/favicon.ico
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-go/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-python/app.yaml:
--------------------------------------------------------------------------------
1 | application: jquery-file-upload
2 | version: 1
3 | runtime: python27
4 | api_version: 1
5 | threadsafe: true
6 |
7 | libraries:
8 | - name: PIL
9 | version: latest
10 |
11 | handlers:
12 | - url: /(favicon\.ico|robots\.txt)
13 | static_files: static/\1
14 | upload: static/(.*)
15 | expiration: '1d'
16 | - url: /.*
17 | script: main.app
18 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-python/main.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # jQuery File Upload Plugin GAE Python Example
4 | # https://github.com/blueimp/jQuery-File-Upload
5 | #
6 | # Copyright 2011, Sebastian Tschan
7 | # https://blueimp.net
8 | #
9 | # Licensed under the MIT license:
10 | # https://opensource.org/licenses/MIT
11 | #
12 |
13 | from google.appengine.api import memcache, images
14 | import json
15 | import os
16 | import re
17 | import urllib
18 | import webapp2
19 |
20 | DEBUG=os.environ.get('SERVER_SOFTWARE', '').startswith('Dev')
21 | WEBSITE = 'https://blueimp.github.io/jQuery-File-Upload/'
22 | MIN_FILE_SIZE = 1 # bytes
23 | # Max file size is memcache limit (1MB) minus key size minus overhead:
24 | MAX_FILE_SIZE = 999000 # bytes
25 | IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)')
26 | ACCEPT_FILE_TYPES = IMAGE_TYPES
27 | THUMB_MAX_WIDTH = 80
28 | THUMB_MAX_HEIGHT = 80
29 | THUMB_SUFFIX = '.'+str(THUMB_MAX_WIDTH)+'x'+str(THUMB_MAX_HEIGHT)+'.png'
30 | EXPIRATION_TIME = 300 # seconds
31 | # If set to None, only allow redirects to the referer protocol+host.
32 | # Set to a regexp for custom pattern matching against the redirect value:
33 | REDIRECT_ALLOW_TARGET = None
34 |
35 | class CORSHandler(webapp2.RequestHandler):
36 | def cors(self):
37 | headers = self.response.headers
38 | headers['Access-Control-Allow-Origin'] = '*'
39 | headers['Access-Control-Allow-Methods'] =\
40 | 'OPTIONS, HEAD, GET, POST, DELETE'
41 | headers['Access-Control-Allow-Headers'] =\
42 | 'Content-Type, Content-Range, Content-Disposition'
43 |
44 | def initialize(self, request, response):
45 | super(CORSHandler, self).initialize(request, response)
46 | self.cors()
47 |
48 | def json_stringify(self, obj):
49 | return json.dumps(obj, separators=(',', ':'))
50 |
51 | def options(self, *args, **kwargs):
52 | pass
53 |
54 | class UploadHandler(CORSHandler):
55 | def validate(self, file):
56 | if file['size'] < MIN_FILE_SIZE:
57 | file['error'] = 'File is too small'
58 | elif file['size'] > MAX_FILE_SIZE:
59 | file['error'] = 'File is too big'
60 | elif not ACCEPT_FILE_TYPES.match(file['type']):
61 | file['error'] = 'Filetype not allowed'
62 | else:
63 | return True
64 | return False
65 |
66 | def validate_redirect(self, redirect):
67 | if redirect:
68 | if REDIRECT_ALLOW_TARGET:
69 | return REDIRECT_ALLOW_TARGET.match(redirect)
70 | referer = self.request.headers['referer']
71 | if referer:
72 | from urlparse import urlparse
73 | parts = urlparse(referer)
74 | redirect_allow_target = '^' + re.escape(
75 | parts.scheme + '://' + parts.netloc + '/'
76 | )
77 | return re.match(redirect_allow_target, redirect)
78 | return False
79 |
80 | def get_file_size(self, file):
81 | file.seek(0, 2) # Seek to the end of the file
82 | size = file.tell() # Get the position of EOF
83 | file.seek(0) # Reset the file position to the beginning
84 | return size
85 |
86 | def write_blob(self, data, info):
87 | key = urllib.quote(info['type'].encode('utf-8'), '') +\
88 | '/' + str(hash(data)) +\
89 | '/' + urllib.quote(info['name'].encode('utf-8'), '')
90 | try:
91 | memcache.set(key, data, time=EXPIRATION_TIME)
92 | except: #Failed to add to memcache
93 | return (None, None)
94 | thumbnail_key = None
95 | if IMAGE_TYPES.match(info['type']):
96 | try:
97 | img = images.Image(image_data=data)
98 | img.resize(
99 | width=THUMB_MAX_WIDTH,
100 | height=THUMB_MAX_HEIGHT
101 | )
102 | thumbnail_data = img.execute_transforms()
103 | thumbnail_key = key + THUMB_SUFFIX
104 | memcache.set(
105 | thumbnail_key,
106 | thumbnail_data,
107 | time=EXPIRATION_TIME
108 | )
109 | except: #Failed to resize Image or add to memcache
110 | thumbnail_key = None
111 | return (key, thumbnail_key)
112 |
113 | def handle_upload(self):
114 | results = []
115 | for name, fieldStorage in self.request.POST.items():
116 | if type(fieldStorage) is unicode:
117 | continue
118 | result = {}
119 | result['name'] = urllib.unquote(fieldStorage.filename)
120 | result['type'] = fieldStorage.type
121 | result['size'] = self.get_file_size(fieldStorage.file)
122 | if self.validate(result):
123 | key, thumbnail_key = self.write_blob(
124 | fieldStorage.value,
125 | result
126 | )
127 | if key is not None:
128 | result['url'] = self.request.host_url + '/' + key
129 | result['deleteUrl'] = result['url']
130 | result['deleteType'] = 'DELETE'
131 | if thumbnail_key is not None:
132 | result['thumbnailUrl'] = self.request.host_url +\
133 | '/' + thumbnail_key
134 | else:
135 | result['error'] = 'Failed to store uploaded file.'
136 | results.append(result)
137 | return results
138 |
139 | def head(self):
140 | pass
141 |
142 | def get(self):
143 | self.redirect(WEBSITE)
144 |
145 | def post(self):
146 | if (self.request.get('_method') == 'DELETE'):
147 | return self.delete()
148 | result = {'files': self.handle_upload()}
149 | s = self.json_stringify(result)
150 | redirect = self.request.get('redirect')
151 | if self.validate_redirect(redirect):
152 | return self.redirect(str(
153 | redirect.replace('%s', urllib.quote(s, ''), 1)
154 | ))
155 | if 'application/json' in self.request.headers.get('Accept'):
156 | self.response.headers['Content-Type'] = 'application/json'
157 | self.response.write(s)
158 |
159 | class FileHandler(CORSHandler):
160 | def normalize(self, str):
161 | return urllib.quote(urllib.unquote(str), '')
162 |
163 | def get(self, content_type, data_hash, file_name):
164 | content_type = self.normalize(content_type)
165 | file_name = self.normalize(file_name)
166 | key = content_type + '/' + data_hash + '/' + file_name
167 | data = memcache.get(key)
168 | if data is None:
169 | return self.error(404)
170 | # Prevent browsers from MIME-sniffing the content-type:
171 | self.response.headers['X-Content-Type-Options'] = 'nosniff'
172 | content_type = urllib.unquote(content_type)
173 | if not IMAGE_TYPES.match(content_type):
174 | # Force a download dialog for non-image types:
175 | content_type = 'application/octet-stream'
176 | elif file_name.endswith(THUMB_SUFFIX):
177 | content_type = 'image/png'
178 | self.response.headers['Content-Type'] = content_type
179 | # Cache for the expiration time:
180 | self.response.headers['Cache-Control'] = 'public,max-age=%d' \
181 | % EXPIRATION_TIME
182 | self.response.write(data)
183 |
184 | def delete(self, content_type, data_hash, file_name):
185 | content_type = self.normalize(content_type)
186 | file_name = self.normalize(file_name)
187 | key = content_type + '/' + data_hash + '/' + file_name
188 | result = {key: memcache.delete(key)}
189 | content_type = urllib.unquote(content_type)
190 | if IMAGE_TYPES.match(content_type):
191 | thumbnail_key = key + THUMB_SUFFIX
192 | result[thumbnail_key] = memcache.delete(thumbnail_key)
193 | if 'application/json' in self.request.headers.get('Accept'):
194 | self.response.headers['Content-Type'] = 'application/json'
195 | s = self.json_stringify(result)
196 | self.response.write(s)
197 |
198 | app = webapp2.WSGIApplication(
199 | [
200 | ('/', UploadHandler),
201 | ('/(.+)/([^/]+)/([^/]+)', FileHandler)
202 | ],
203 | debug=DEBUG
204 | )
205 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-python/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-python/static/favicon.ico
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/gae-python/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/php/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:7.0-apache
2 |
3 | # Enable the Apache Headers module:
4 | RUN ln -s /etc/apache2/mods-available/headers.load \
5 | /etc/apache2/mods-enabled/headers.load
6 |
7 | # Enable the Apache Rewrite module:
8 | RUN ln -s /etc/apache2/mods-available/rewrite.load \
9 | /etc/apache2/mods-enabled/rewrite.load
10 |
11 | # Install GD, Imagick and ImageMagick as image conversion options:
12 | RUN DEBIAN_FRONTEND=noninteractive \
13 | apt-get update && apt-get install -y --no-install-recommends \
14 | libpng-dev \
15 | libjpeg-dev \
16 | libmagickwand-dev \
17 | imagemagick \
18 | && pecl install \
19 | imagick \
20 | && docker-php-ext-enable \
21 | imagick \
22 | && docker-php-ext-configure \
23 | gd --with-jpeg-dir=/usr/include/ \
24 | && docker-php-ext-install \
25 | gd \
26 | # Uninstall obsolete packages:
27 | && apt-get autoremove -y \
28 | libpng-dev \
29 | libjpeg-dev \
30 | libmagickwand-dev \
31 | # Remove obsolete files:
32 | && apt-get clean \
33 | && rm -rf \
34 | /tmp/* \
35 | /usr/share/doc/* \
36 | /var/cache/* \
37 | /var/lib/apt/lists/* \
38 | /var/tmp/*
39 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/php/docker-compose.yml:
--------------------------------------------------------------------------------
1 | apache:
2 | build: ./
3 | ports:
4 | - "80:80"
5 | volumes:
6 | - "../../:/var/www/html"
7 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/php/files/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 | !.htaccess
4 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/php/files/.htaccess:
--------------------------------------------------------------------------------
1 | # To enable the Headers module, execute the following command and reload Apache:
2 | # sudo a2enmod headers
3 |
4 | # The following directives prevent the execution of script files
5 | # in the context of the website.
6 | # They also force the content-type application/octet-stream and
7 | # force browsers to display a download dialog for non-image files.
8 | SetHandler default-handler
9 | ForceType application/octet-stream
10 | Header set Content-Disposition attachment
11 |
12 | # The following unsets the forced type and Content-Disposition headers
13 | # for known image files:
14 |
15 | ForceType none
16 | Header unset Content-Disposition
17 |
18 |
19 | # The following directive prevents browsers from MIME-sniffing the content-type.
20 | # This is an important complement to the ForceType directive above:
21 | Header set X-Content-Type-Options nosniff
22 |
23 | # Uncomment the following lines to prevent unauthorized download of files:
24 | #AuthName "Authorization required"
25 | #AuthType Basic
26 | #require valid-user
27 |
--------------------------------------------------------------------------------
/fatfs_data/jQuery-File-Upload-9.18.0/server/php/index.php:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
17 |
20 |
21 | jQuery File Upload Plugin Test
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
73 |
74 |
105 |
106 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/fatfs_data/jqueryui/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright jQuery Foundation and other contributors, https://jquery.org/
2 |
3 | This software consists of voluntary contributions made by many
4 | individuals. For exact contribution history, see the revision history
5 | available at https://github.com/jquery/jquery-ui
6 |
7 | The following license applies to all parts of this software except as
8 | documented below:
9 |
10 | ====
11 |
12 | Permission is hereby granted, free of charge, to any person obtaining
13 | a copy of this software and associated documentation files (the
14 | "Software"), to deal in the Software without restriction, including
15 | without limitation the rights to use, copy, modify, merge, publish,
16 | distribute, sublicense, and/or sell copies of the Software, and to
17 | permit persons to whom the Software is furnished to do so, subject to
18 | the following conditions:
19 |
20 | The above copyright notice and this permission notice shall be
21 | included in all copies or substantial portions of the Software.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 |
31 | ====
32 |
33 | Copyright and related rights for sample code are waived via CC0. Sample
34 | code is defined as all source code contained within the demos directory.
35 |
36 | CC0: http://creativecommons.org/publicdomain/zero/1.0/
37 |
38 | ====
39 |
40 | All files located in the node_modules and external directories are
41 | externally maintained libraries used by this software which have their
42 | own licenses; we recommend you read them, as their terms may differ from
43 | the terms above.
44 |
--------------------------------------------------------------------------------
/fatfs_data/jqueryui/images/ui-icons_444444_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jqueryui/images/ui-icons_444444_256x240.png
--------------------------------------------------------------------------------
/fatfs_data/jqueryui/images/ui-icons_555555_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jqueryui/images/ui-icons_555555_256x240.png
--------------------------------------------------------------------------------
/fatfs_data/jqueryui/images/ui-icons_777620_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jqueryui/images/ui-icons_777620_256x240.png
--------------------------------------------------------------------------------
/fatfs_data/jqueryui/images/ui-icons_777777_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jqueryui/images/ui-icons_777777_256x240.png
--------------------------------------------------------------------------------
/fatfs_data/jqueryui/images/ui-icons_cc0000_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jqueryui/images/ui-icons_cc0000_256x240.png
--------------------------------------------------------------------------------
/fatfs_data/jqueryui/images/ui-icons_ffffff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jqueryui/images/ui-icons_ffffff_256x240.png
--------------------------------------------------------------------------------
/fatfs_data/jqueryui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery-ui",
3 | "title": "jQuery UI",
4 | "description": "A curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library.",
5 | "version": "1.12.1",
6 | "homepage": "http://jqueryui.com",
7 | "author": {
8 | "name": "jQuery Foundation and other contributors",
9 | "url": "https://github.com/jquery/jquery-ui/blob/1.12.1/AUTHORS.txt"
10 | },
11 | "main": "ui/widget.js",
12 | "maintainers": [
13 | {
14 | "name": "Scott González",
15 | "email": "scott.gonzalez@gmail.com",
16 | "url": "http://scottgonzalez.com"
17 | },
18 | {
19 | "name": "Jörn Zaefferer",
20 | "email": "joern.zaefferer@gmail.com",
21 | "url": "http://bassistance.de"
22 | },
23 | {
24 | "name": "Mike Sherov",
25 | "email": "mike.sherov@gmail.com",
26 | "url": "http://mike.sherov.com"
27 | },
28 | {
29 | "name": "TJ VanToll",
30 | "email": "tj.vantoll@gmail.com",
31 | "url": "http://tjvantoll.com"
32 | },
33 | {
34 | "name": "Felix Nagel",
35 | "email": "info@felixnagel.com",
36 | "url": "http://www.felixnagel.com"
37 | },
38 | {
39 | "name": "Alex Schmitz",
40 | "email": "arschmitz@gmail.com",
41 | "url": "https://github.com/arschmitz"
42 | }
43 | ],
44 | "repository": {
45 | "type": "git",
46 | "url": "git://github.com/jquery/jquery-ui.git"
47 | },
48 | "bugs": "https://bugs.jqueryui.com/",
49 | "license": "MIT",
50 | "scripts": {
51 | "test": "grunt"
52 | },
53 | "dependencies": {},
54 | "devDependencies": {
55 | "commitplease": "2.3.0",
56 | "grunt": "0.4.5",
57 | "grunt-bowercopy": "1.2.4",
58 | "grunt-cli": "0.1.13",
59 | "grunt-compare-size": "0.4.0",
60 | "grunt-contrib-concat": "0.5.1",
61 | "grunt-contrib-csslint": "0.5.0",
62 | "grunt-contrib-jshint": "0.12.0",
63 | "grunt-contrib-qunit": "1.0.1",
64 | "grunt-contrib-requirejs": "0.4.4",
65 | "grunt-contrib-uglify": "0.11.1",
66 | "grunt-git-authors": "3.1.0",
67 | "grunt-html": "6.0.0",
68 | "grunt-jscs": "2.1.0",
69 | "load-grunt-tasks": "3.4.0",
70 | "rimraf": "2.5.1",
71 | "testswarm": "1.1.0"
72 | },
73 | "keywords": []
74 | }
75 |
--------------------------------------------------------------------------------
/fatfs_data/jstree/themes/default-dark/32px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jstree/themes/default-dark/32px.png
--------------------------------------------------------------------------------
/fatfs_data/jstree/themes/default-dark/40px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jstree/themes/default-dark/40px.png
--------------------------------------------------------------------------------
/fatfs_data/jstree/themes/default-dark/throbber.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jstree/themes/default-dark/throbber.gif
--------------------------------------------------------------------------------
/fatfs_data/jstree/themes/default/32px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jstree/themes/default/32px.png
--------------------------------------------------------------------------------
/fatfs_data/jstree/themes/default/40px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jstree/themes/default/40px.png
--------------------------------------------------------------------------------
/fatfs_data/jstree/themes/default/throbber.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nkolban/ESP32_Explorer/611fcd1e418cdbb0744abaa7f3340849f84f1e60/fatfs_data/jstree/themes/default/throbber.gif
--------------------------------------------------------------------------------
/main/BLEExplorer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * BLEExplorer.cpp
3 | *
4 | * Created on: Sep 27, 2017
5 | * Author: kolban
6 | */
7 |
8 | #include "BLEExplorer.h"
9 | #include "sdkconfig.h"
10 | #include
11 | #include
12 | #include "Task.h"
13 | #include "Memory.h"
14 | #include
15 | #include "BLE2902.h"
16 | #include "BLEClient.h"
17 | static const char* LOG_TAG = "BLEExplorer";
18 | static bool isRunning = false;
19 | static BLEServer *pServer;
20 | static BLEServiceMap *mServices;
21 | static BLECharacteristicMap *mCharacteristics;
22 |
23 | BLEExplorer::BLEExplorer() {
24 | // TODO Auto-generated constructor stub
25 | }
26 |
27 | BLEExplorer::~BLEExplorer() {
28 | // TODO Auto-generated destructor stub
29 | }
30 | /**
31 | * @brief Perform a BLE Scan and return the results.
32 | */
33 | JsonArray BLEExplorer::scan() {
34 | ESP_LOGD(LOG_TAG, ">> scan");
35 | if(!isRunning){
36 | BLEDevice::init("");
37 | isRunning = true;
38 | }
39 | BLEScan* pBLEScan = BLEDevice::getScan();
40 | pBLEScan->setActiveScan(true);
41 | BLEScanResults scanResults = pBLEScan->start(1);
42 | JsonObject obj = JSON::createObject();
43 | JsonArray arr = JSON::createArray();
44 | arr.addString("BLE devices");
45 | for (int c = 0; c < scanResults.getCount(); ++c) {
46 | BLEAdvertisedDevice dev = scanResults.getDevice(c);
47 | arr.addObject(enumerateDevices(dev));
48 | }
49 | obj.setInt("deviceCount", scanResults.getCount());
50 | ESP_LOGD(LOG_TAG, "<< scan");
51 | return arr;
52 | } // scan
53 | /*
54 | * @brief Connect to BLE server to get and enumerate services and characteristics
55 | */
56 | JsonArray BLEExplorer::connect(std::string _addr){
57 | BLEAddress *pAddress = new BLEAddress(_addr);
58 | BLEClient* pClient = BLEDevice::createClient();
59 |
60 | // Connect to the remove BLE Server.
61 | pClient->connect(*pAddress);
62 | std::map *pRemoteServices = pClient->getServices();
63 | if (pRemoteServices == nullptr) {
64 | ESP_LOGD(LOG_TAG, "Failed to find services");
65 | return JSON::createArray();
66 | }
67 | // Memory::startTraceAll();
68 | JsonArray arr = JSON::createArray();
69 | for (auto it=pRemoteServices->begin(); it!=pRemoteServices->end(); ++it) {
70 | JsonObject obj = JSON::createObject();
71 | char tmp[33];
72 | itoa(it->second->getHandle(), tmp, 16);
73 |
74 | obj.setString("id", tmp); // todo service's handle
75 | obj.setString("text", BLEUtils::gattServiceToString(it->second->getUUID().getNative()->uuid.uuid32) + " Service: " + it->second->getUUID().toString());
76 | obj.setString("icon", "service");
77 | JsonObject state = JSON::createObject();
78 | state.setBoolean("opened", true);
79 | obj.setObject("state", state);
80 | obj.setString("parent", _addr);
81 | std::map *pChars = it->second->getCharacteristics();
82 | obj.setArray("children", enumerateCharacteristics(pChars));
83 | arr.addObject(obj);
84 | }
85 |
86 | pClient->disconnect();
87 | /*
88 | free(pClient);
89 | free(pAddress); //FIXME using it here causing multi heap crash
90 | free(pRemoteServices);*/
91 | return arr;
92 | }
93 | /*
94 | * @brief Enumerate devices
95 | */
96 | JsonObject BLEExplorer::enumerateDevices(BLEAdvertisedDevice device){
97 | JsonArray arr = JSON::createArray();
98 | JsonObject obj = JSON::createObject();
99 | obj.setString("id", device.getAddress().toString());
100 | obj.setString("parent", "#");
101 | obj.setString("text", device.getName() == ""? "N/A":device.getName());
102 | JsonObject state = JSON::createObject();
103 | state.setBoolean("opened", true);
104 | obj.setObject("state", state);
105 | JsonObject obj2 = JSON::createObject();
106 | //obj2.setString("id", device.getAddress().toString());
107 | //obj2.setString("parent", device.getAddress().toString());
108 | obj2.setString("text", "Address - " + device.getAddress().toString());
109 | //obj2.setBoolean("children", false);
110 | arr.addObject(obj2);
111 | if(device.haveManufacturerData()){
112 | obj2 = JSON::createObject();
113 | obj2.setString("text", "Manufacturer - " + atoi(device.getManufacturerData().c_str()));
114 | arr.addObject(obj2);
115 | }
116 | std::stringstream ss;
117 | if(device.haveAppearance()){
118 | ss << "Appearance - " << device.getAppearance();
119 | obj2 = JSON::createObject();
120 | obj2.setString("text", ss.str());
121 | arr.addObject(obj2);
122 | }
123 | if(device.haveRSSI()){
124 | ss.str("");
125 | ss << "RSSI - " << (int)device.getRSSI();
126 | obj2 = JSON::createObject();
127 | obj2.setString("text", ss.str());
128 | arr.addObject(obj2);
129 | }
130 | if(device.haveTXPower()){
131 | ss.str("");
132 | ss << "TX power - " << (int)device.getTXPower();
133 | obj2 = JSON::createObject();
134 | obj2.setString("text", ss.str());
135 | arr.addObject(obj2);
136 | }
137 | if(device.haveServiceUUID()){
138 | ss.str("");
139 | ss << "Advertised services - " << device.getServiceUUID().toString();
140 | obj2 = JSON::createObject();
141 | obj2.setString("text", ss.str());
142 | arr.addObject(obj2);
143 | }
144 |
145 |
146 | obj.setArray("children", arr);
147 |
148 | return obj;
149 | }
150 | /*
151 | * @brief Enumerate characteristics from given service
152 | */
153 | JsonArray BLEExplorer::enumerateCharacteristics(std::map *characteristicMap){
154 |
155 | //std::map *characteristicMap = pService;
156 | //pService->getCharacteristics(characteristicMap);
157 | JsonArray arr = JSON::createArray();
158 | char tmp[33];
159 |
160 | for (auto it=characteristicMap->begin(); it!=characteristicMap->end(); it++) { // TODO add descriptors enumerator, add short uuid if characteristic !UNKNOWN
161 | JsonObject ch = JSON::createObject();
162 | JsonObject val = JSON::createObject();
163 | JsonArray ar = JSON::createArray();
164 | itoa(it->second->getHandle(), tmp, 16);
165 | ch.setString("id", tmp); // characteristic's handle
166 |
167 | std::string str = it->second->canRead()?"R":"";
168 | str += it->second->canWrite()?"\\W":"";
169 | str += it->second->canBroadcast()?"\\B":"";
170 | str += it->second->canIndicate()?"\\I":"";
171 | str += it->second->canNotify()?"\\N]":"]";
172 | std::stringstream ss1;
173 | ss1 << BLEUtils::gattCharacteristicUUIDToString(it->second->getUUID().getNative()->uuid.uuid16) << \
174 | " Characteristic: " << it->second->getUUID().toString() << "[" << \
175 | str;
176 |
177 | ch.setString("text", ss1.str());
178 |
179 | ch.setString("icon", "characteristic");
180 | JsonObject state = JSON::createObject();
181 | state.setBoolean("opened", true);
182 | ch.setObject("state", state);
183 | std::map pChars;
184 | std::map *desc = it->second->getDescriptors();
185 | ar = enumerateDescriptors(desc);
186 | std::string f = it->second->readValue();
187 | ESP_LOGI(LOG_TAG, "Value: %s, %d, %#4x", f.c_str(), it->second->readUInt32(), it->second->readUInt32());
188 | std::stringstream ss;
189 | ss << "Value: " << f;
190 | val.setString("text", ss.str());
191 | ar.addObject(val);
192 | ch.setArray("children", ar);
193 | arr.addObject(ch);
194 | }
195 |
196 | return arr;
197 | }
198 |
199 | JsonArray BLEExplorer::enumerateDescriptors(std::map* descriptors){
200 | JsonArray arr = JSON::createArray();
201 | for(auto it=descriptors->begin();it!=descriptors->end();it++){
202 | JsonObject obj = JSON::createObject();
203 | obj.setString("icon", "descriptor");
204 | /*JsonObject val = JSON::createObject();
205 | std::stringstream ss;
206 | ss << "Value: " << it->second->readValue();
207 | val.setString("text", ss.str());
208 | obj.setObject("children", val);*/
209 | obj.setString("text", BLEUtils::gattDescriptorUUIDToString(it->second->getUUID().getNative()->uuid.uuid16) + " Descriptor: " + it->second->getUUID().toString());
210 | arr.addObject(obj);
211 | }
212 |
213 | return arr;
214 | }
215 |
216 | void BLEExplorer::createServer(std::string name){
217 | BLEDevice::init(name);
218 | pServer = BLEDevice::createServer();
219 | mCharacteristics = new BLECharacteristicMap();
220 | mServices = new BLEServiceMap();
221 | }
222 |
223 | void BLEExplorer::startService(uint16_t handle){
224 | BLEService *pservice = mServices->getByHandle(handle);
225 | pservice->start();
226 | }
227 |
228 | JsonObject BLEExplorer::addService(BLEUUID _uuid){
229 | JsonObject obj = JSON::createObject();
230 |
231 | char ptr[33];
232 | BLEService *pservice = pServer->createService(_uuid);
233 | if(pservice != nullptr){
234 | mServices->setByHandle(pservice->getHandle(), pservice);
235 | // pservice->start();
236 | obj.setString("icon", "service");
237 | itoa(pservice->getHandle(), ptr, 16);
238 | obj.setString("handle", ptr);
239 | obj.setString("parent", "#");
240 | obj.setString("text", BLEUtils::gattServiceToString(pservice->getUUID().getNative()->uuid.uuid16) + " Service: " + pservice->getUUID().toString());
241 | }
242 | return obj;
243 | }
244 |
245 | JsonObject BLEExplorer::addCharacteristic(BLEUUID uuid, uint16_t service){
246 | char ptr[33];
247 | BLEService *pservice = mServices->getByHandle(service);
248 | ESP_LOGE(LOG_TAG, "ADD: %d", pservice->getHandle());
249 | BLECharacteristic *charact = pservice->createCharacteristic(BLEUUID(uuid), {BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE});
250 | charact->setValue("Private name");
251 | //mCharacteristics->setByHandle(charact->getHandle(), charact);
252 | JsonObject obj = JSON::createObject();
253 | obj.setString("icon", "characteristic");
254 | itoa(charact->getHandle(), ptr, 16);
255 | obj.setString("handle", ptr);
256 | itoa(service, ptr, 16);
257 | obj.setString("parent", ptr);
258 | obj.setString("text", BLEUtils::gattCharacteristicUUIDToString(charact->getUUID().getNative()->uuid.uuid16) + " Characteristic: " + charact->getUUID().toString());
259 | return obj;
260 | }
261 |
262 | JsonObject BLEExplorer::addDescriptor(BLEUUID uuid, uint16_t charact){
263 | char ptr[33];
264 | BLECharacteristic *pcharact = mCharacteristics->getByHandle(charact);
265 | assert(charact == pcharact->getHandle());
266 | BLEDescriptor *descr = new BLE2902();
267 | pcharact->addDescriptor(descr);
268 | JsonObject obj = JSON::createObject();
269 | obj.setString("icon", "descriptor");
270 | itoa(descr->getHandle(), ptr, 16);
271 | obj.setString("handle", ptr);
272 | itoa(pcharact->getHandle(), ptr, 16);
273 | obj.setString("parent", ptr);
274 | obj.setString("text", BLEUtils::gattDescriptorUUIDToString(uuid.getNative()->uuid.uuid32) + " Descriptor: " + uuid.toString());
275 | return obj;
276 | }
277 |
278 | void BLEExplorer::startAdvertising(){
279 | pServer->getAdvertising()->start();
280 | }
281 |
282 | void BLEExplorer::stopAdvertising(){
283 | pServer->getAdvertising()->stop();
284 | }
285 |
286 |
--------------------------------------------------------------------------------
/main/BLEExplorer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * BLEExplorer.h
3 | *
4 | * Created on: Sep 27, 2017
5 | * Author: kolban
6 | */
7 |
8 | #ifndef MAIN_BLEEXPLORER_H_
9 | #define MAIN_BLEEXPLORER_H_
10 | #include
11 | #include "JSON.h"
12 | #include "BLEAdvertisedDevice.h"
13 |
14 | class BLEExplorer {
15 | public:
16 | BLEExplorer();
17 | virtual ~BLEExplorer();
18 | JsonArray scan();
19 | JsonArray connect(std::string addr);
20 | JsonObject enumerateDevices(BLEAdvertisedDevice device);
21 | JsonArray enumerateCharacteristics(std::map *characteristicMap);
22 | JsonArray enumerateDescriptors(std::map *descriptorsMap);
23 |
24 | // --- SERVER --- //
25 | void createServer(std::string name);
26 | void deleteServer();
27 | JsonObject addService(BLEUUID uuid);
28 | void startService(uint16_t handle);
29 | //void stopServer();
30 | void startAdvertising();
31 | void stopAdvertising();
32 | JsonObject addCharacteristic(BLEUUID uuid, uint16_t service);
33 | JsonObject addDescriptor(BLEUUID uuid, uint16_t characteristic);
34 | void setCharacteristicValue(BLEUUID uuid, std::string value);
35 |
36 | private:
37 | };
38 |
39 | #endif /* MAIN_BLEEXPLORER_H_ */
40 |
41 |
--------------------------------------------------------------------------------
/main/BootWiFi.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Bootwifi - Boot the WiFi environment.
3 | *
4 | * Compile with -DBOOTWIFI_OVERRIDE_GPIO= where is a GPIO pin number
5 | * to use a GPIO override.
6 | * See the README.md for full information.
7 | *
8 | */
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | //#include
17 | //#include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include "BootWiFi.h"
24 | #include "sdkconfig.h"
25 | #include "selectAP.h"
26 |
27 | // If the structure of a record saved for a subsequent reboot changes
28 | // then consider using semver to change the version number or else
29 | // we may try and boot with the wrong data.
30 | #define KEY_VERSION "version"
31 | uint32_t g_version=0x0100;
32 |
33 | #define KEY_CONNECTION_INFO "connectionInfo" // Key used in NVS for connection info
34 | #define BOOTWIFI_NAMESPACE "bootwifi" // Namespace in NVS for bootwifi
35 | #define SSID_SIZE (32) // Maximum SSID size
36 | #define PASSWORD_SIZE (64) // Maximum password size
37 |
38 |
39 | /**
40 | * The information about a WiFi access point connection.
41 | */
42 | typedef struct {
43 | char ssid[SSID_SIZE];
44 | char password[PASSWORD_SIZE];
45 | tcpip_adapter_ip_info_t ipInfo; // Optional static IP information
46 | } connection_info_t;
47 |
48 | //static bootwifi_callback_t g_callback = NULL; // Callback function to be invoked when we have finished.
49 |
50 |
51 | // Forward declarations
52 | static void saveConnectionInfo(connection_info_t *pConnectionInfo);
53 |
54 | static const char LOG_TAG[] = "bootwifi";
55 |
56 |
57 | static void dumpConnectionInfo(connection_info_t *pConnectionInfo) {
58 | ESP_LOGD(LOG_TAG, "connection_info.ssid = %.*s", SSID_SIZE, pConnectionInfo->ssid);
59 | ESP_LOGD(LOG_TAG, "connection_info.password = %.*s", PASSWORD_SIZE, pConnectionInfo->password);
60 | ESP_LOGD(LOG_TAG, "ip: %s, gw: %s, netmask: %s",
61 | GeneralUtils::ipToString((uint8_t*)&pConnectionInfo->ipInfo.ip).c_str(),
62 | GeneralUtils::ipToString((uint8_t*)&pConnectionInfo->ipInfo.gw).c_str(),
63 | GeneralUtils::ipToString((uint8_t*)&pConnectionInfo->ipInfo.netmask).c_str());
64 | }
65 |
66 |
67 | /**
68 | * Retrieve the connection info. A rc==0 means ok.
69 | */
70 | static int getConnectionInfo(connection_info_t *pConnectionInfo) {
71 | ESP_LOGD(LOG_TAG, ">> getConnectionInfo");
72 | size_t size;
73 | uint32_t version;
74 |
75 | NVS myNamespace(BOOTWIFI_NAMESPACE);
76 | myNamespace.get(KEY_VERSION, version);
77 |
78 | // Check the versions match
79 | if ((version & 0xff00) != (g_version & 0xff00)) {
80 | ESP_LOGD(LOG_TAG, "Incompatible versions ... current is %x, found is %x", version, g_version);
81 | return -1;
82 | }
83 |
84 | size = sizeof(connection_info_t);
85 | myNamespace.get(KEY_CONNECTION_INFO, (uint8_t*)pConnectionInfo, size);
86 |
87 | // Do a sanity check on the SSID
88 | if (strlen(pConnectionInfo->ssid) == 0) {
89 | ESP_LOGD(LOG_TAG, "NULL ssid detected");
90 | return -1;
91 | }
92 | dumpConnectionInfo(pConnectionInfo);
93 | ESP_LOGD(LOG_TAG, "<< getConnectionInfo");
94 | return 0;
95 |
96 | } // getConnectionInfo
97 |
98 |
99 | /**
100 | * Save our connection info for retrieval on a subsequent restart.
101 | */
102 | static void saveConnectionInfo(connection_info_t *pConnectionInfo) {
103 | dumpConnectionInfo(pConnectionInfo);
104 | NVS myNamespace(BOOTWIFI_NAMESPACE);
105 | myNamespace.set(KEY_CONNECTION_INFO, (uint8_t*)pConnectionInfo, sizeof(connection_info_t));
106 | myNamespace.set(KEY_VERSION, g_version);
107 | myNamespace.commit();
108 | } // setConnectionInfo
109 |
110 |
111 | /**
112 | * Retrieve the signal level on the OVERRIDE_GPIO pin. This is used to
113 | * indicate that we should not attempt to connect to any previously saved
114 | * access point we may know about.
115 | */
116 |
117 | static int checkOverrideGpio() {
118 | #ifdef BOOTWIFI_OVERRIDE_GPIO
119 | gpio_pad_select_gpio(BOOTWIFI_OVERRIDE_GPIO);
120 | gpio_set_direction(BOOTWIFI_OVERRIDE_GPIO, GPIO_MODE_INPUT);
121 | gpio_set_pull_mode(BOOTWIFI_OVERRIDE_GPIO, GPIO_PULLDOWN_ONLY);
122 | return gpio_get_level(BOOTWIFI_OVERRIDE_GPIO);
123 | #else
124 | return 0; // If no boot override, return false
125 | #endif
126 | } // checkOverrideGpio
127 |
128 | static void sendForm(HttpRequest* pRequest, HttpResponse* pResponse) {
129 | pResponse->setStatus(HttpResponse::HTTP_STATUS_OK, "OK");
130 | pResponse->addHeader(HttpRequest::HTTP_HEADER_CONTENT_TYPE, "text/html");
131 | pResponse->sendData(std::string((char*)selectAP_html, selectAP_html_len));
132 | pResponse->close();
133 | } // sendForm
134 |
135 |
136 | static void copyData(uint8_t* pTarget, size_t targetLength, std::string source) {
137 | memset(pTarget, 0, targetLength);
138 | size_t copySize = (source.length() > targetLength)? targetLength:source.length();
139 | memcpy(pTarget, source.data(), copySize);
140 | if (copySize < targetLength) {
141 | pTarget[copySize] = '\0';
142 | }
143 | } // copyData
144 |
145 |
146 | /**
147 | * @brief Process the form response.
148 | */
149 | static void processForm(HttpRequest* pRequest, HttpResponse* pResponse) {
150 | ESP_LOGD(LOG_TAG, ">> processForm");
151 | std::map formMap = pRequest->parseForm();
152 | connection_info_t connectionInfo;
153 | copyData((uint8_t*)connectionInfo.ssid, SSID_SIZE, formMap["ssid"]);
154 | copyData((uint8_t*)connectionInfo.password, PASSWORD_SIZE, formMap["password"]);
155 |
156 | try {
157 | std::string ipStr = formMap.at("ip");
158 | if (ipStr.empty()) {
159 | ESP_LOGD(LOG_TAG, "No IP address using default 0.0.0.0");
160 | connectionInfo.ipInfo.ip.addr = 0;
161 | } else {
162 | inet_pton(AF_INET, ipStr.c_str(), &connectionInfo.ipInfo.ip);
163 | }
164 | } catch(std::out_of_range& e) {
165 | ESP_LOGD(LOG_TAG, "No IP address using default 0.0.0.0");
166 | connectionInfo.ipInfo.ip.addr = 0;
167 | }
168 |
169 | try {
170 | std::string gwStr = formMap.at("gw");
171 | if (gwStr.empty()) {
172 | ESP_LOGD(LOG_TAG, "No GW address using default 0.0.0.0");
173 | connectionInfo.ipInfo.gw.addr = 0;
174 | } else {
175 | inet_pton(AF_INET, gwStr.c_str(), &connectionInfo.ipInfo.gw);
176 | }
177 | } catch(std::out_of_range& e) {
178 | ESP_LOGD(LOG_TAG, "No GW address using default 0.0.0.0");
179 | connectionInfo.ipInfo.gw.addr = 0;
180 | }
181 |
182 | try {
183 | std::string netmaskStr = formMap.at("netmask");
184 | if (netmaskStr.empty()) {
185 | ESP_LOGD(LOG_TAG, "No Netmask address using default 0.0.0.0");
186 | connectionInfo.ipInfo.netmask.addr = 0;
187 | } else {
188 | inet_pton(AF_INET, netmaskStr.c_str(), &connectionInfo.ipInfo.netmask);
189 | }
190 | } catch(std::out_of_range& e) {
191 | ESP_LOGD(LOG_TAG, "No Netmask address using default 0.0.0.0");
192 | connectionInfo.ipInfo.netmask.addr = 0;
193 | }
194 |
195 | ESP_LOGD(LOG_TAG, "ssid: %s, password: %s", connectionInfo.ssid, connectionInfo.password);
196 |
197 | saveConnectionInfo(&connectionInfo);
198 |
199 | pResponse->setStatus(HttpResponse::HTTP_STATUS_OK, "OK");
200 | pResponse->addHeader(HttpRequest::HTTP_HEADER_CONTENT_TYPE, "text/html");
201 | //pResponse->sendData(std::string((char*)selectAP_html, selectAP_html_len));
202 | pResponse->close();
203 | FreeRTOS::sleep(500);
204 | //GeneralUtils::restart();
205 | esp_restart();
206 | ESP_LOGD(LOG_TAG, "<< processForm");
207 | } // processForm
208 |
209 |
210 | class BootWifiEventHandler: public WiFiEventHandler {
211 | public:
212 | BootWifiEventHandler(BootWiFi *pBootWiFi) {
213 | m_pBootWiFi = pBootWiFi;
214 | }
215 |
216 | /**
217 | * When the access point logic has started and we are able to receive incoming browser
218 | * requests, start the internal HTTP Server.
219 | */
220 | esp_err_t apStart() {
221 | ESP_LOGD("BootWifiEventHandler", ">> apStart");
222 | if (m_pBootWiFi->m_httpServerStarted == false) {
223 | m_pBootWiFi->m_httpServerStarted = true;
224 | m_pBootWiFi->m_httpServer.addPathHandler("GET", "/", sendForm);
225 | m_pBootWiFi->m_httpServer.addPathHandler("POST", "/ssidSelected", processForm);
226 | m_pBootWiFi->m_httpServer.start(80);
227 | }
228 | ESP_LOGD("BootWifiEventHandler", "<< apStart");
229 | return ESP_OK;
230 | } // apStaConnected
231 |
232 | /**
233 | * If we fail to connect as a station, then become an access point and then
234 | * become a web server.
235 | */
236 | esp_err_t staDisconnected() {
237 | ESP_LOGD("BootWifiEventHandler", ">> staDisconnected");
238 | m_pBootWiFi->m_wifi.startAP("Duktape", "Duktape");
239 | ESP_LOGD("BootWifiEventHandler", "<< staDisconnected");
240 | return ESP_OK;
241 | }
242 |
243 | private:
244 | BootWiFi *m_pBootWiFi;
245 | };
246 |
247 |
248 | void BootWiFi::bootWiFi2() {
249 | ESP_LOGD(LOG_TAG, ">> bootWiFi2");
250 | // Check for a GPIO override which occurs when a physical Pin is high
251 | // during the test. This can force the ability to check for new configuration
252 | // even if the existing configured access point is available.
253 | m_wifi.setWifiEventHandler(new BootWifiEventHandler(this));
254 | if (checkOverrideGpio()) {
255 | ESP_LOGD(LOG_TAG, "- GPIO override detected");
256 | m_wifi.startAP(m_ssid, m_password);
257 | } else {
258 | // There was NO GPIO override, proceed as normal. This means we retrieve
259 | // our stored access point information of the access point we should connect
260 | // against. If that information doesn't exist, then again we become an
261 | // access point ourselves in order to allow a client to connect and bring
262 | // up a browser.
263 | connection_info_t connectionInfo;
264 | int rc = getConnectionInfo(&connectionInfo);
265 | if (rc == 0) {
266 | // We have received connection information, let us now become a station
267 | // and attempt to connect to the access point.
268 | ESP_LOGD(LOG_TAG, "- Connecting to access point \"%s\" ...", connectionInfo.ssid);
269 | assert(strlen(connectionInfo.ssid) > 0);
270 |
271 | m_wifi.setIPInfo(
272 | connectionInfo.ipInfo.ip.addr,
273 | connectionInfo.ipInfo.gw.addr,
274 | connectionInfo.ipInfo.netmask.addr
275 | );
276 | m_wifi.connectAP(connectionInfo.ssid, connectionInfo.password); // Connect to the access point.
277 |
278 | } else {
279 | // We do NOT have connection information. Let us now become an access
280 | // point that serves up a web server and allow a browser user to specify
281 | // the details that will be eventually used to allow us to connect
282 | // as a station.
283 | m_wifi.startAP(m_ssid, m_password);
284 | } // We do NOT have connection info
285 | }
286 | ESP_LOGD(LOG_TAG, "<< bootWiFi2");
287 | } // bootWiFi2
288 |
289 |
290 | /**
291 | * @brief Set the userid/password pair that will be used for the ESP32 access point.
292 | * @param [in] ssid The network id of the ESP32 when it becomes an access point.
293 | * @param [in] password The password for the ESP32 when it becomes an access point.
294 | */
295 | void BootWiFi::setAccessPointCredentials(std::string ssid, std::string password) {
296 | m_ssid = ssid;
297 | m_password = password;
298 | } // setAccessPointCredentials
299 |
300 |
301 | void BootWiFi::boot() {
302 | ESP_LOGD(LOG_TAG, ">> boot");
303 | ESP_LOGD(LOG_TAG, " +----------+");
304 | ESP_LOGD(LOG_TAG, " | BootWiFi |");
305 | ESP_LOGD(LOG_TAG, " +----------+");
306 | ESP_LOGD(LOG_TAG, " Access point credentials: %s/%s", m_ssid.c_str(), m_password.c_str());
307 | //m_completeSemaphore.take("boot"); // Take the semaphore which will be unlocked when we complete booting.
308 | bootWiFi2();
309 | //m_completeSemaphore.wait("boot"); // Wait for the semaphore that indicated we have completed booting.
310 | ESP_LOGD(LOG_TAG, "<< boot");
311 | }
312 |
313 | BootWiFi::BootWiFi() {
314 | m_httpServerStarted = false;
315 | setAccessPointCredentials("esp32", "password"); // Default access point credentials
316 | }
317 |
--------------------------------------------------------------------------------
/main/BootWiFi.h:
--------------------------------------------------------------------------------
1 | /*
2 | * BootWiFi.h
3 | *
4 | * Created on: Nov 25, 2016
5 | * Author: kolban
6 | */
7 |
8 | #ifndef MAIN_BOOTWIFI_H_
9 | #define MAIN_BOOTWIFI_H_
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | typedef void (*bootwifi_callback_t)(int rc);
16 | class BootWifiEventHandler;
17 |
18 | class BootWiFi {
19 | private:
20 | friend BootWifiEventHandler;
21 | void bootWiFi2();
22 | WiFi m_wifi;
23 | HttpServer m_httpServer;
24 | bool m_httpServerStarted;
25 | std::string m_ssid;
26 | std::string m_password;
27 | FreeRTOS::Semaphore m_completeSemaphore = FreeRTOS::Semaphore("completeSemaphore");
28 |
29 | public:
30 | BootWiFi();
31 | void setAccessPointCredentials(std::string ssid, std::string password);
32 | void boot();
33 | };
34 |
35 | #endif /* MAIN_BOOTWIFI_H_ */
36 |
--------------------------------------------------------------------------------
/main/ESP32Explorer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * ESP32Explorer.h
3 | *
4 | * Created on: May 22, 2017
5 | * Author: kolban
6 | */
7 |
8 | #ifndef MAIN_ESP32EXPLORER_H_
9 | #define MAIN_ESP32EXPLORER_H_
10 |
11 | class ESP32_Explorer {
12 | public:
13 | ESP32_Explorer();
14 | virtual ~ESP32_Explorer();
15 | void start();
16 | };
17 |
18 | #endif /* MAIN_ESP32EXPLORER_H_ */
19 |
--------------------------------------------------------------------------------
/main/FILESYSTEM_JSON.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | static char tag[] = "FILESYSTEM_JSON";
12 | JsonObject FILESYSTEM_GET_JSON_CONTENT(std::string path) {
13 | // Stat the file to make sure it is there and to determine what kind of a file
14 | // it is.
15 | struct stat statBuf;
16 | int rc = stat(path.c_str(), &statBuf);
17 |
18 | JsonObject obj = JSON::createObject();
19 | if (rc == -1) {
20 | ESP_LOGE(tag, "Failed to stat file %s, errno=%s", path.c_str(), strerror(errno));
21 | obj.setInt("errno", errno);
22 | return obj;
23 | }
24 | obj.setString("path", path);
25 | std::vector parts = FileSystem::pathSplit(path);
26 | obj.setString("name", parts[parts.size()-1]);
27 | // Do one thing if the file is a regular file.
28 | if (S_ISREG(statBuf.st_mode)) {
29 | obj.setBoolean("directory", false);
30 | File file(path.c_str());
31 | std::string data = file.getContent(true);
32 | obj.setString("data", data);
33 | }
34 | // Do a different thing if the file is a directory.
35 | else if (S_ISDIR(statBuf.st_mode)) {
36 | obj.setBoolean("directory", true);
37 |
38 | } // End ... found a directory.
39 | return obj;
40 | } // FILESYSTEM_GET_JSON_CONTENT
41 |
42 |
43 | /**
44 | * @brief Get the content of the specified path as a JSON object.
45 | * @param [in] path The path to access.
46 | * @return A JSON object containing what was found at the path.
47 | */
48 | JsonObject FILESYSTEM_GET_JSON_DIRECTORY(std::string path, bool isRecursive) {
49 | ESP_LOGD(tag, "FILESYSTEM_GET_JSON_DIRECTORY: path is %s", path.c_str());
50 |
51 | // Stat the file to make sure it is there and to determine what kind of a file
52 | // it is.
53 | struct stat statBuf;
54 | int rc = stat(path.c_str(), &statBuf);
55 |
56 | JsonObject obj = JSON::createObject();
57 | if (rc == -1) {
58 | ESP_LOGE(tag, "Failed to stat file, errno=%s", strerror(errno));
59 | obj.setInt("errno", errno);
60 | return obj;
61 | }
62 |
63 | obj.setString("path", path);
64 | std::vector parts = FileSystem::pathSplit(path);
65 | obj.setString("name", parts[parts.size()-1]);
66 |
67 | // Do one thing if the file is a regular file.
68 | if (S_ISREG(statBuf.st_mode)) {
69 | obj.setBoolean("directory", false);
70 | }
71 | // Do a different thing if the file is a directory.
72 | else if (S_ISDIR(statBuf.st_mode)) {
73 | obj.setBoolean("directory", true);
74 | JsonArray dirArray = JSON::createArray();
75 | obj.setArray("dir", dirArray);
76 |
77 | ESP_LOGD(tag, "Processing directory: %s", path.c_str());
78 | std::vector files = FileSystem::getDirectoryContents(path);
79 |
80 | // Now that we have the list of files in the directory, iterator over them adding them
81 | // to our array of entries.
82 | for (std::vector::iterator it = files.begin(); it!= files.end(); it++) {
83 | if (isRecursive) {
84 | JsonObject dirEntry = FILESYSTEM_GET_JSON_DIRECTORY(path + "/" + (*it).getName(), isRecursive);
85 | dirArray.addObject(dirEntry);
86 | } else {
87 | JsonObject dirEntry = JSON::createObject();
88 | dirEntry.setString("name", (*it).getName());
89 | dirEntry.setInt("type", (*it).getType());
90 | dirArray.addObject(dirEntry);
91 | }
92 |
93 | } // End ... for each entry in the directory.
94 | } // End ... found a directory.
95 | return obj;
96 | } // FILESYSTEM_GET_JSON_DIRECTORY
97 |
--------------------------------------------------------------------------------
/main/GPIO_JSON.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | extern "C" {
4 | #include
5 | }
6 |
7 | JsonObject GPIO_JSON() {
8 | JsonObject obj = JSON::createObject();
9 | JsonArray tmpArr = JSON::createArray();
10 | int i;
11 | for (i=0;i<32; i++) {
12 | tmpArr.addBoolean((GPIO.out & (1<
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | extern "C" {
14 | #include
15 | }
16 | #include "I2C.h"
17 |
18 | JsonObject I2C_READ(std::map parts) {
19 | uint8_t SDA, SCL, ADDR, REG;
20 | uint8_t bytes = atoi(parts.at("bytesCount").c_str());
21 | SDA = atoi(parts.at("sda").c_str());
22 | SCL = atoi(parts.at("scl").c_str());
23 | ADDR = atoi(parts.at("address").c_str());
24 | REG = atoi(parts.at("register").c_str());
25 |
26 |
27 | JsonObject obj = JSON::createObject();
28 | JsonObject tmpObj = JSON::createObject();
29 | I2C* i2c = new I2C();
30 | i2c->init(ADDR, (gpio_num_t)SDA, (gpio_num_t)SCL);
31 |
32 | i2c->beginTransaction();
33 | i2c->write(REG);
34 | i2c->endTransaction();
35 |
36 | uint8_t data[bytes];
37 | i2c->beginTransaction();
38 | i2c->read(data, bytes-1, true);
39 | i2c->read(data+bytes-1, false);
40 | i2c->endTransaction();
41 | //i2c->stop();
42 | delete i2c;
43 |
44 | for(int i=0;i parts) {
56 | uint8_t SDA, SCL, ADDR, REG;
57 | std::string hex_byte;
58 | uint8_t bytes = atoi(parts.at("bytesCount").c_str());
59 | uint8_t dat[1];
60 |
61 | SDA = atoi(parts.at("sda").c_str());
62 | SCL = atoi(parts.at("scl").c_str());
63 | ADDR = atoi(parts.at("address").c_str());
64 | REG = atoi(parts.at("register").c_str());
65 | dat[0] = atoi(parts.at("data").c_str());
66 |
67 | JsonObject obj = JSON::createObject();
68 | JsonObject tmpObj = JSON::createObject();
69 |
70 | printf("write to reg: %d, val: %d", REG, dat[0]);
71 | I2C* i2c = new I2C();
72 | i2c->init(ADDR, (gpio_num_t)SDA, (gpio_num_t)SCL);
73 |
74 | i2c->beginTransaction();
75 | i2c->write(REG);
76 | /*
77 | i2c->write(dat, bytes-1, true);
78 | i2c->write(dat[bytes-1], false);*/
79 | i2c->write(dat[0], false);
80 | i2c->endTransaction();
81 | delete i2c;
82 |
83 |
84 | obj.setObject("error", tmpObj);
85 | // free(dat);
86 | return obj;
87 | }
88 |
--------------------------------------------------------------------------------
/main/I2C_SCAN.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * I2C_SCAN.cpp
3 | *
4 | * Created on: 18.09.2017
5 | * Author: darek
6 | */
7 |
8 |
9 | #include "sdkconfig.h"
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | //static const char *LOG_TAG = "I2C_SCAN";
17 |
18 | /**
19 | * @begin Scan the I2C ports.
20 | * @return A JsonObject that describes the I2C scan.
21 | */
22 | JsonObject I2C_SCAN_JSON() {
23 | JsonObject obj = JSON::createObject();
24 | JsonObject tmpObj = JSON::createObject();
25 | JsonArray tmpArr = JSON::createArray();
26 | //tmpArr = JSON::createArray();
27 | int i;
28 | printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
29 | printf("00: ");
30 |
31 | I2C i2c;
32 | // i2c.init(0);
33 |
34 | for (i=3; i<0x78; i++) { // Loop over each of the possible I2C addresses.
35 | bool slavePresent = i2c.slavePresent(i);
36 |
37 | if (i%16 == 0) {
38 | std::stringstream ss;
39 | ss << "address " << std::hex << (i-16);
40 | obj.setObject(ss.str(), tmpObj);
41 | tmpObj = JSON::createObject();
42 | printf("\n%.2x:", i);
43 | }
44 | std::stringstream ss;
45 | ss << "address " << std::hex << i;
46 | if (slavePresent) {
47 | tmpObj.setBoolean(ss.str(), true);
48 | tmpArr.addBoolean(true);
49 | printf(" %.2x", i);
50 | } else {
51 | tmpObj.setBoolean(ss.str(), false);
52 | tmpArr.addBoolean(false);
53 | printf(" --");
54 | }
55 | } // End for each of the I2C addresses.
56 | printf("\n");
57 | obj.setObject("70", tmpObj);
58 | obj.setArray("present", tmpArr);
59 | //obj.setObject("I2C", tmpObj);
60 | return obj;
61 | } // I2C_SCAN_JSON
62 |
--------------------------------------------------------------------------------
/main/SYSTEM_JSON.cpp:
--------------------------------------------------------------------------------
1 | #include "sdkconfig.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | const static char LOG_TAG[] = "SYSTEM_JSON";
17 | /**
18 | * @brief Obtain a JSON object describing a partition.
19 | *
20 | * {
21 | * "type":
22 | * "subType":
23 | * "size":
24 | * "address":
25 | * "encrypted":
26 | * "label":
27 | * }
28 | */
29 | static JsonObject fromPartition(esp_partition_t *pPartition) {
30 | JsonObject obj = JSON::createObject();
31 | obj.setInt("type", pPartition->type); // type
32 | obj.setInt("subType", pPartition->subtype); // subType
33 | obj.setInt("size", pPartition->size); // size
34 | obj.setInt("address", pPartition->address); // address
35 | obj.setBoolean("encrypted", pPartition->encrypted); // encrypted
36 | obj.setString("label", std::string(pPartition->label)); // label
37 | return obj;
38 | } // fromPartition
39 |
40 |
41 | /**
42 | * @brief Create a JSON object from a TaskStatus_t.
43 | *
44 | * {
45 | * "name":
46 | * "stackHighWater":
47 | * "priority":
48 | * "taskNumber":
49 | * "state":
50 | * }
51 | * @param [in] pTaskStatus The task status to turn into a JSON object.
52 | * @return A JSON object from a TaskStatus_t.
53 | */
54 | static JsonObject fromTaskStatus(TaskStatus_t *pTaskStatus) {
55 | JsonObject obj = JSON::createObject();
56 | obj.setString("name", pTaskStatus->pcTaskName); // name
57 | obj.setInt("stackHighWater", pTaskStatus->usStackHighWaterMark); // stackHighWater
58 | obj.setInt("priority", pTaskStatus->uxCurrentPriority); // priority
59 | obj.setInt("taskNumber", pTaskStatus->xTaskNumber); // taskNumber
60 | std::string state = "";
61 | switch(pTaskStatus->eCurrentState) {
62 | case eReady: {
63 | state = "Ready";
64 | break;
65 | }
66 | case eRunning: {
67 | state = "Running";
68 | break;
69 | }
70 | case eBlocked: {
71 | state = "Blocked";
72 | break;
73 | }
74 | case eSuspended: {
75 | state = "Suspended";
76 | break;
77 | }
78 | case eDeleted: {
79 | state = "Deleted";
80 | break;
81 | }
82 | }
83 | obj.setString("state", state); // state
84 | return obj;
85 | } // fromTaskStatus
86 |
87 |
88 | /**
89 | * @brief Create the JSON object to return to the caller that provides us information
90 | * about the system as a whole.
91 | *
92 | * The returned object contains:
93 | * {
94 | * "model": // ESP32 model number
95 | * "cores": // Number of ESP32 cores
96 | * "revision": // ESP32 revision
97 | * "hasEmbeddedFlash":
98 | * "hasWiFi": // Is WiFi present?
99 | * "hasBLE": // Is BLE present?
100 | * "hasBT": // Is BT classic present?
101 | * "espVersion": // Version of ESP-IDF
102 | * "freeHeap": // Amount of heap free
103 | * "time": // Time since boot
104 | * "taskCount": // Number of FreeRTOS tasks
105 | * "partitions": // Partitions structure
106 | * [
107 | * {
108 | * "type":
109 | * "subType":
110 | * "size":
111 | * "address":
112 | * "encrypted":
113 | * "label":
114 | * },
115 | * ...
116 | * ]
117 | * "taskStatus": [
118 | * {
119 | * "name":
120 | * "stackHighWater":
121 | * "priority":
122 | * "taskNumber":
123 | * "state":
124 | * },
125 | * ...
126 | * ]
127 | * }
128 | *
129 | * @return A JSON Object describing the data.
130 | */
131 | JsonObject SYSTEM_JSON() {
132 | JsonObject obj = JSON::createObject();
133 | esp_chip_info_t chipInfo;
134 | esp_chip_info(&chipInfo);
135 | obj.setInt("model", chipInfo.model);
136 | obj.setInt("cores", chipInfo.cores);
137 | obj.setInt("revision", chipInfo.revision);
138 | obj.setBoolean("hasEmbeddedFlash", chipInfo.features & CHIP_FEATURE_EMB_FLASH);
139 | obj.setBoolean("hasWifi", chipInfo.features & CHIP_FEATURE_WIFI_BGN);
140 | obj.setBoolean("hasBLE", chipInfo.features & CHIP_FEATURE_BLE);
141 | obj.setBoolean("hasBT", chipInfo.features & CHIP_FEATURE_BT);
142 | obj.setString("espVersion", System::getIDFVersion());
143 | obj.setInt("freeHeap", System::getFreeHeapSize());
144 | //obj.setInt("minimumFreeHeap", System::getMinimumFreeHeapSize());
145 | struct timeval tv;
146 | gettimeofday(&tv, nullptr);
147 | obj.setDouble("time", tv.tv_sec + tv.tv_usec / 1000000.0);
148 | int taskCount = uxTaskGetNumberOfTasks();
149 | obj.setInt("taskCount", taskCount);
150 |
151 | #if( configUSE_TRACE_FACILITY == 1 )
152 | TaskStatus_t *pTaskStatusArray = new TaskStatus_t[taskCount];
153 | assert(pTaskStatusArray != nullptr);
154 | taskCount = ::uxTaskGetSystemState(pTaskStatusArray, taskCount, nullptr);
155 | std::sort(pTaskStatusArray, pTaskStatusArray+taskCount, [](const TaskStatus_t& a, const TaskStatus_t& b) {
156 | return strcasecmp(a.pcTaskName, b.pcTaskName) < 0;
157 | });
158 |
159 | JsonArray arr2 = JSON::createArray();
160 | for (int i=0; i
2 | #include
3 | #include
4 | #include
5 |
6 | JsonObject WIFI_JSON() {
7 | JsonObject obj = JSON::createObject();
8 | obj.setString("mode", WiFi::getMode());
9 | obj.setString("staMac", WiFi::getStaMac());
10 | obj.setString("apMac", WiFi::getApMac());
11 | obj.setString("staSSID", WiFi::getStaSSID());
12 | obj.setString("apSSID", WiFi::getApSSID());
13 |
14 | JsonObject apIpInfo = JSON::createObject();
15 | tcpip_adapter_ip_info_t ipInfo = WiFi::getApIpInfo();
16 | apIpInfo.setString("ip", GeneralUtils::ipToString((uint8_t *)&(ipInfo.ip)));
17 | apIpInfo.setString("gw", GeneralUtils::ipToString((uint8_t *)&(ipInfo.gw)));
18 | apIpInfo.setString("netmask", GeneralUtils::ipToString((uint8_t *)&(ipInfo.netmask)));
19 | obj.setObject("apIpInfo", apIpInfo);
20 |
21 | JsonObject staIpInfo = JSON::createObject();
22 | ipInfo = WiFi::getStaIpInfo();
23 | staIpInfo.setString("ip", GeneralUtils::ipToString((uint8_t *)&(ipInfo.ip)));
24 | staIpInfo.setString("gw", GeneralUtils::ipToString((uint8_t *)&(ipInfo.gw)));
25 | staIpInfo.setString("netmask", GeneralUtils::ipToString((uint8_t *)&(ipInfo.netmask)));
26 | obj.setObject("staIpInfo", staIpInfo);
27 | return obj;
28 | } // WIFI_JSON
29 |
--------------------------------------------------------------------------------
/main/common.h:
--------------------------------------------------------------------------------
1 | /*
2 | * common.h
3 | *
4 | * Created on: Nov 16, 2017
5 | * Author: esp32
6 | */
7 |
8 | #ifndef MAIN_COMMON_H_
9 | #define MAIN_COMMON_H_
10 |
11 | #include "WS2812.h"
12 |
13 | extern WS2812* strip1;
14 |
15 |
16 |
17 |
18 | #endif /* MAIN_COMMON_H_ */
19 |
--------------------------------------------------------------------------------
/main/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 |
--------------------------------------------------------------------------------
/main/main.cpp:
--------------------------------------------------------------------------------
1 | #include "Memory.h"
2 | #include "sdkconfig.h"
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include "ESP32Explorer.h"
14 | #include "bt.h"
15 | #include "BootWiFi.h"
16 |
17 | //#define BOOTWIFI
18 |
19 | #ifndef BOOTWIFI
20 | //static const char WIFI_SSID[] = "sweetie";
21 | //static const char WIFI_PASSWORD[] = "l16wint!";
22 | static const char *WIFI_SSID = "Orange-8F54";
23 | static const char *WIFI_PASSWORD = "33413006";
24 | #endif
25 |
26 | extern "C" {
27 | int app_main(void);
28 | }
29 |
30 | //static const char* LOG_TAG = "ESP32_Explorer_MAIN"; // Logging tag
31 |
32 |
33 | class ESP32_ExplorerTask: public Task {
34 | void run(void* data) override {
35 | ESP32_Explorer* pESP32_Explorer = new ESP32_Explorer();
36 | pESP32_Explorer->start();
37 | }
38 | }; // ESP32_ExplorerTask
39 |
40 |
41 | /**
42 | * @brief Wifi management task.
43 | */
44 | class WiFiTask: public Task {
45 | void run(void *data) override {
46 | #ifdef BOOTWIFI
47 | BootWiFi boot = BootWiFi();
48 | boot.boot();
49 | #else
50 | WiFi *pWifi = new WiFi(); // Can't delete at the end of the task.
51 | pWifi->setIPInfo("192.168.1.99", "192.168.1.1", "255.255.255.0");
52 | pWifi->connectAP(WIFI_SSID, WIFI_PASSWORD);
53 | #endif
54 | ESP32_ExplorerTask *pESP32_ExplorerTask = new ESP32_ExplorerTask();
55 | pESP32_ExplorerTask->setStackSize(6000);
56 | pESP32_ExplorerTask->start();
57 | } // End run
58 | }; // WiFiTask
59 |
60 |
61 | void task_webserver(void* ignore) {
62 | WiFiTask* pMyTask = new WiFiTask();
63 | pMyTask->setStackSize(6000);
64 | pMyTask->start();
65 | FreeRTOS::deleteTask();
66 | } // task_webserver
67 |
68 |
69 |
70 | /**
71 | * @brief Main entry point.
72 | */
73 | int app_main(void) {
74 | //Memory::init(300);
75 | esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); //FIXME waiting for response from esp-idf issue
76 | task_webserver(nullptr);
77 | return 0;
78 | } // app_main
79 |
--------------------------------------------------------------------------------
/main/selectAP.h:
--------------------------------------------------------------------------------
1 | unsigned char selectAP_html[] = {
2 | 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74,
3 | 0x6d, 0x6c, 0x3e, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x0a, 0x3c,
4 | 0x68, 0x65, 0x61, 0x64, 0x3e, 0x0a, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20,
5 | 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x22, 0x55, 0x54, 0x46,
6 | 0x2d, 0x38, 0x22, 0x3e, 0x0a, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e,
7 | 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x57, 0x69, 0x46, 0x69, 0x3c,
8 | 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x0a, 0x3c, 0x2f, 0x68, 0x65,
9 | 0x61, 0x64, 0x3e, 0x0a, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x0a, 0x3c,
10 | 0x21, 0x2d, 0x2d, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x2d, 0x2d,
11 | 0x3e, 0x0a, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65,
12 | 0x3d, 0x22, 0x7a, 0x6f, 0x6f, 0x6d, 0x3a, 0x20, 0x33, 0x35, 0x30, 0x25,
13 | 0x3b, 0x22, 0x3e, 0x0a, 0x3c, 0x68, 0x31, 0x3e, 0x53, 0x65, 0x6c, 0x65,
14 | 0x63, 0x74, 0x20, 0x57, 0x69, 0x46, 0x69, 0x3c, 0x2f, 0x68, 0x31, 0x3e,
15 | 0x0a, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6f,
16 | 0x6e, 0x3d, 0x22, 0x73, 0x73, 0x69, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63,
17 | 0x74, 0x65, 0x64, 0x22, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x3d,
18 | 0x22, 0x70, 0x6f, 0x73, 0x74, 0x22, 0x3e, 0x0a, 0x3c, 0x74, 0x61, 0x62,
19 | 0x6c, 0x65, 0x3e, 0x0a, 0x3c, 0x74, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x0a,
20 | 0x3c, 0x74, 0x72, 0x3e, 0x0a, 0x3c, 0x74, 0x64, 0x3e, 0x53, 0x53, 0x49,
21 | 0x44, 0x3a, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x0a, 0x3c, 0x74, 0x64, 0x3e,
22 | 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d,
23 | 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x63,
24 | 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x3d, 0x22, 0x6f, 0x66, 0x66, 0x22,
25 | 0x20, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x61, 0x70, 0x69, 0x74, 0x61, 0x6c,
26 | 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x6e, 0x6f, 0x6e, 0x65, 0x22, 0x20, 0x6e,
27 | 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x73, 0x69, 0x64, 0x22, 0x20, 0x2f,
28 | 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x0a, 0x3c, 0x2f, 0x74, 0x72, 0x3e,
29 | 0x0a, 0x3c, 0x74, 0x72, 0x3e, 0x0a, 0x3c, 0x74, 0x64, 0x3e, 0x50, 0x61,
30 | 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x3c, 0x2f, 0x74, 0x64, 0x3e,
31 | 0x0a, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20,
32 | 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20,
33 | 0x61, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x3d,
34 | 0x22, 0x6f, 0x66, 0x66, 0x22, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x61,
35 | 0x70, 0x69, 0x74, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x6e, 0x6f,
36 | 0x6e, 0x65, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x61,
37 | 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x20, 0x2f, 0x3e, 0x3c, 0x2f,
38 | 0x74, 0x64, 0x3e, 0x0a, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x0a, 0x3c, 0x74,
39 | 0x72, 0x3e, 0x0a, 0x3c, 0x74, 0x64, 0x3e, 0x49, 0x50, 0x20, 0x61, 0x64,
40 | 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x0a,
41 | 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74,
42 | 0x79, 0x70, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20, 0x61,
43 | 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x3d, 0x22,
44 | 0x6f, 0x66, 0x66, 0x22, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x61, 0x70,
45 | 0x69, 0x74, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x6e, 0x6f, 0x6e,
46 | 0x65, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x70, 0x22,
47 | 0x20, 0x2f, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x0a, 0x3c, 0x2f, 0x74,
48 | 0x72, 0x3e, 0x0a, 0x3c, 0x74, 0x72, 0x3e, 0x0a, 0x3c, 0x74, 0x64, 0x3e,
49 | 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x20, 0x61, 0x64, 0x64, 0x72,
50 | 0x65, 0x73, 0x73, 0x3a, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x0a, 0x3c, 0x74,
51 | 0x64, 0x3e, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70,
52 | 0x65, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20, 0x61, 0x75, 0x74,
53 | 0x6f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x3d, 0x22, 0x6f, 0x66,
54 | 0x66, 0x22, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x61, 0x70, 0x69, 0x74,
55 | 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x6e, 0x6f, 0x6e, 0x65, 0x22,
56 | 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x67, 0x77, 0x22, 0x20, 0x2f,
57 | 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x0a, 0x3c, 0x2f, 0x74, 0x72, 0x3e,
58 | 0x0a, 0x3c, 0x74, 0x72, 0x3e, 0x0a, 0x3c, 0x74, 0x64, 0x3e, 0x4e, 0x65,
59 | 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x3a, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x0a,
60 | 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74,
61 | 0x79, 0x70, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20, 0x61,
62 | 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x3d, 0x22,
63 | 0x6f, 0x66, 0x66, 0x22, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x61, 0x70,
64 | 0x69, 0x74, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x3d, 0x22, 0x6e, 0x6f, 0x6e,
65 | 0x65, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6e, 0x65, 0x74,
66 | 0x6d, 0x61, 0x73, 0x6b, 0x22, 0x20, 0x2f, 0x3e, 0x3c, 0x2f, 0x74, 0x64,
67 | 0x3e, 0x0a, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x0a, 0x3c, 0x2f, 0x74, 0x62,
68 | 0x6f, 0x64, 0x79, 0x3e, 0x0a, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65,
69 | 0x3e, 0x0a, 0x20, 0x3c, 0x70, 0x3e, 0x0a, 0x3c, 0x69, 0x6e, 0x70, 0x75,
70 | 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x73, 0x75, 0x62, 0x6d,
71 | 0x69, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x53,
72 | 0x75, 0x62, 0x6d, 0x69, 0x74, 0x22, 0x3e, 0x0a, 0x3c, 0x2f, 0x70, 0x3e,
73 | 0x0a, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x0a, 0x3c, 0x64, 0x69,
74 | 0x76, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72,
75 | 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x36, 0x70, 0x78, 0x3b, 0x22, 0x3e, 0x0a,
76 | 0x54, 0x68, 0x65, 0x20, 0x49, 0x50, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
77 | 0x73, 0x73, 0x2c, 0x20, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x20,
78 | 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
79 | 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x20, 0x61, 0x72, 0x65, 0x20,
80 | 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2e, 0x20, 0x20, 0x49,
81 | 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69,
82 | 0x65, 0x64, 0x0a, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x76, 0x61, 0x6c,
83 | 0x75, 0x65, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
84 | 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68,
85 | 0x65, 0x20, 0x57, 0x69, 0x46, 0x69, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73,
86 | 0x73, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x0a, 0x3c, 0x2f, 0x64,
87 | 0x69, 0x76, 0x3e, 0x0a, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x3c,
88 | 0x21, 0x2d, 0x2d, 0x20, 0x45, 0x6e, 0x64, 0x20, 0x2d, 0x2d, 0x3e, 0x0a,
89 | 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x0a, 0x3c, 0x2f, 0x68, 0x74,
90 | 0x6d, 0x6c, 0x3e
91 | };
92 | unsigned int selectAP_html_len = 1059;
93 |
--------------------------------------------------------------------------------
/partitions.csv:
--------------------------------------------------------------------------------
1 | # Name, Type, SubType, Offset, Size, Flags
2 | # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 | nvs, data, nvs, 0x9000, 0x6000,
4 | phy_init, data, phy, 0xf000, 0x1000,
5 | factory, app, factory, 0x10000, 2M,
6 | storage, data, fat, 0x300000, 1M,
7 |
--------------------------------------------------------------------------------