├── .gitignore
├── LICENSE
├── README.md
├── app
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── FILTERURLS.TXT
│ ├── filter.gif
│ └── httpproxy.conf
│ ├── java
│ ├── HttpProxy.java
│ ├── httpproxy
│ │ ├── ChunkedDataTransfer.java
│ │ ├── HttpProxyRequest.java
│ │ ├── HttpProxyResponse.java
│ │ ├── HttpProxyServer.java
│ │ └── android
│ │ │ ├── BootUpReceiver.java
│ │ │ ├── HttpProxyActivity.java
│ │ │ └── HttpProxyService.java
│ ├── proxy
│ │ ├── BlockedHosts.java
│ │ ├── BlockedUrls.java
│ │ ├── HttpProxy.java
│ │ └── Transmitter.java
│ └── util
│ │ ├── AsyncBulkLogger.java
│ │ ├── DateRetriever.java
│ │ ├── ExecutionEnvironment.java
│ │ ├── ExecutionEnvironmentInterface.java
│ │ ├── FileLogger.java
│ │ ├── GroupedLogger.java
│ │ ├── HugePackedSet.java
│ │ ├── LRUCache.java
│ │ ├── Logger.java
│ │ ├── LoggerInterface.java
│ │ ├── ObjectPackagingManager.java
│ │ ├── PackedSortedList.java
│ │ ├── TimeoutListener.java
│ │ ├── TimeoutTime.java
│ │ ├── TimoutNotificator.java
│ │ ├── Utils.java
│ │ ├── conpool
│ │ ├── Connection.java
│ │ ├── PooledConnectionInputStream.java
│ │ └── PooledConnectionOutputStream.java
│ │ └── http
│ │ └── HttpHeader.java
│ └── res
│ ├── drawable-hdpi
│ └── icon.png
│ ├── drawable-ldpi
│ └── icon.png
│ ├── drawable-mdpi
│ └── icon.png
│ ├── drawable-xhdpi
│ └── icon.png
│ ├── drawable-xxhdpi
│ └── icon.png
│ ├── drawable-xxxhdpi
│ └── icon.png
│ ├── drawable
│ ├── button_default.xml
│ ├── button_focused.xml
│ ├── button_pressed.xml
│ ├── checkbox_active.xml
│ ├── checkbox_inactive.xml
│ ├── custom_button.xml
│ └── custom_checkbox.xml
│ ├── layout-v17
│ └── main.xml
│ ├── layout-v23
│ └── main.xml
│ ├── layout-v4
│ └── main.xml
│ ├── values-af
│ └── strings.xml
│ ├── values-ar
│ └── strings.xml
│ ├── values-ca
│ └── strings.xml
│ ├── values-cs
│ └── strings.xml
│ ├── values-da
│ └── strings.xml
│ ├── values-de
│ └── strings.xml
│ ├── values-el
│ └── strings.xml
│ ├── values-es-rES
│ └── strings.xml
│ ├── values-fi
│ └── strings.xml
│ ├── values-fr
│ └── strings.xml
│ ├── values-he
│ └── strings.xml
│ ├── values-hi
│ └── strings.xml
│ ├── values-hr
│ └── strings.xml
│ ├── values-hu
│ └── strings.xml
│ ├── values-it
│ └── strings.xml
│ ├── values-iw
│ └── strings.xml
│ ├── values-ja
│ └── strings.xml
│ ├── values-ko
│ └── strings.xml
│ ├── values-nl
│ └── strings.xml
│ ├── values-no
│ └── strings.xml
│ ├── values-pl
│ └── strings.xml
│ ├── values-pt-rBR
│ └── strings.xml
│ ├── values-pt-rPT
│ └── strings.xml
│ ├── values-ro
│ └── strings.xml
│ ├── values-ru
│ └── strings.xml
│ ├── values-sr
│ └── strings.xml
│ ├── values-sv-rSE
│ └── strings.xml
│ ├── values-tr
│ └── strings.xml
│ ├── values-uk
│ └── strings.xml
│ ├── values-vi
│ └── strings.xml
│ ├── values-zh-rCN
│ └── strings.xml
│ ├── values-zh-rTW
│ └── strings.xml
│ └── values
│ ├── strings.xml
│ ├── styles.xml
│ └── themes.xml
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── personalHTTPproxy_icon.zip
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | #built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 |
18 | # Windows thumbnail db
19 | Thumbs.db
20 |
21 | # OSX files
22 | .DS_Store
23 |
24 | # Android Studio
25 | *.iml
26 | .idea
27 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
28 | .gradle
29 | build/
30 | .navigation
31 | captures/
32 | output.json
33 |
34 | #NDK
35 | obj/
36 | .externalNativeBuild
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # personalhttpproxy
2 | http://www.zenz-solutions.de/personalhttpproxy/
3 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | android {
3 | compileSdkVersion 16
4 | buildToolsVersion "27.0.3"
5 |
6 | defaultConfig {
7 | applicationId "httpproxy.android"
8 | minSdkVersion 9
9 | targetSdkVersion 9
10 | }
11 |
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
16 | }
17 | }
18 | }
19 |
20 | dependencies {
21 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
38 |
39 |
40 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/assets/FILTERURLS.TXT:
--------------------------------------------------------------------------------
1 | # List of wildcard based URL patterns which are filtered
2 | # Some examples below
3 |
4 | *://*adserve*
5 | *://*.google.*/uds/*file=ads*
6 | *://*.googleadservices.*/*
7 | *://adwords.google.*/*
8 | *://adservices.google.*/*
--------------------------------------------------------------------------------
/app/src/main/assets/filter.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngoZenz/personalhttpproxy/cbce29ae23cdfa07fe6fc917aad8f8590ee7ca2b/app/src/main/assets/filter.gif
--------------------------------------------------------------------------------
/app/src/main/assets/httpproxy.conf:
--------------------------------------------------------------------------------
1 | # localOnly = true|false - if true, only local connections are allowed.
2 | localOnly = true
3 |
4 | # AUTOSTART = true|false - used only by Android version.
5 | # if true andoid app is started automatically on device boot completed.
6 | AUTOSTART = false
7 |
8 | # listenPort - the network port for listening for proxy requests.
9 | listenPort = 8088
10 |
11 | # traffic log configuration for a rotating traffic log (trafficlog_0.log, trafficlog_1.log, ...)
12 | # enableTrafficLog = true|false - true: trafficlog enabled, false: trafficlog is OFF
13 | # trafficLogSize - max size of a log slot file in bytes / default 1 MB
14 | # trafficLogName - the name of the log /default trafficlog
15 | # trafficLogSlotCount - number of log slots for log rotation / default 2
16 |
17 | enableTrafficLog = true
18 | trafficLogName = trafficlog
19 | trafficLogSize = 1048576
20 | trafficLogSlotCount = 2
21 |
22 | # chainedProxyHost - in case another chained proxy should be used, it can be configured.
23 | # uncomment following line and assign proxy host name!
24 | #chainedProxyHost = proxy
25 |
26 | # chainedProxyPort - in case another chained proxy should be used, it can be configured.
27 | # uncomment following line and assign proxy host port!
28 | #chainedProxyPort = 8080
29 |
30 | # debug = true|false - if true, all communication is written out.
31 | debug = false
32 |
33 | # filterHostsFile - file path of filter hosts text file containing hosts which are filtered.
34 | # comment in case you want to disable filtering!
35 | filterHostsFile = FILTERHOSTS.TXT
36 |
37 | # filterAutoUpdateURL - the URL from were the filterHostsFile gets automatically updated.
38 | # you can specify different URLs seperated by ';' for an concatenated filterHostsFile.
39 | # Comment in case you want to disable the automatic update of the filter host file!
40 | # As a comment, huge filterlist below (about 3000000 entries).
41 | # The active one is smaller but good as well.
42 | # filterAutoUpdateURL = https://adaway.org/hosts.txt; http://www.montanamenagerie.org/hostsfile/hosts.txt
43 | filterAutoUpdateURL = https://adaway.org/hosts.txt; https://hosts-file.net/ad_servers.txt; http://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext
44 |
45 | # previousAutoUpdateURL - the URL from were the last filterHostsFile was automatically updated .
46 | # DO NOT CHANGE! - will be set internally!
47 | previousAutoUpdateURL =
48 |
49 | # reloadIntervalDays - specifies the number of days, after the filter gets updated when configured.
50 | reloadIntervalDays =7
51 |
52 | # filterURLsFile - file path of URL text file containing wildcard based URL patterns which are filtered
53 | # comment in case you want to disable URL filtering!
54 | # NOTE: Auto Update not supported for URL filter yet (only implemented for host filter)!
55 | # filterURLsFile = FILTERURLS.TXT
56 |
57 | # filterResponseFile - path to file containing http response for requests to filtered hosts.
58 | # the default "filter.gif" is a 1 pixel gif file which prevents ugly errors in the browser.
59 | filterResponseFile = filter.gif
60 |
61 | # overrule filterHostFile with filter.=true|false (true will be blocked, false will not be blocked).
62 | filter.unister-adservices.com = true
63 | filter.rad.msn.com = true
64 | filter.live.rads.msn.com = true
65 | filter.ads1.msn.com = true
66 | filter.static.2mdn.net = true
67 | filter.g.msn.com = true
68 | filter.a.ads2.msads.net = true
69 | filter.b.ads2.msads.net = true
70 | filter.ac3.msn.com = true
71 | filter.apps.skype.com = true
72 | filter.mobileads.msn.com = true
73 |
74 | #allow t-online attachments
75 |
76 | filter.js.cit.api.here.com=false
77 | filter.dlvr.t-online.de=false
78 |
79 | #allow bild.de
80 | filter.cdn1.smartadserver.com = false
81 | filter.ec-ns.sascdn.com = false
82 |
83 |
--------------------------------------------------------------------------------
/app/src/main/java/HttpProxy.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 |
24 |
25 |
26 |
27 | public class HttpProxy
28 |
29 | {
30 | //only for compatibility reasons with previous start scripts when HttpProxy was still in the root package
31 |
32 | public static void main(String args[]) {
33 | proxy.HttpProxy.main(args);
34 | }
35 |
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/httpproxy/ChunkedDataTransfer.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package httpproxy;
24 |
25 | import java.io.IOException;
26 | import java.io.OutputStream;
27 |
28 | public class ChunkedDataTransfer {
29 |
30 |
31 |
32 | private OutputStream out;
33 | private static int TRAILEREND = 218762506; // \r\n\r\n
34 | private static short LINEEND = 3338; // \r\n
35 | private StringBuffer chunkHeader = new StringBuffer();
36 | private int remainingChunkLength = 0;
37 | private boolean chunkedRequestTermination = false;
38 | private boolean chunkTermination = false;
39 | private short last2Bytes = 0;
40 | private int last4Bytes = 0;
41 |
42 | public int lastBytesProcessed;
43 |
44 | public ChunkedDataTransfer(OutputStream out) {
45 | this.out = out;
46 |
47 | }
48 |
49 |
50 |
51 | public boolean write(int b) throws IOException {
52 | return write(new byte[] {(byte) b},0,1);
53 | }
54 |
55 |
56 | private void writeThrough(byte[] buf, int offs, int len) throws IOException {
57 | if (out != null)
58 | out.write(buf,offs,len);
59 | }
60 |
61 | public boolean write(byte[] buf, int offs, int length) throws IOException {
62 |
63 | boolean allBytesProcessed = false;
64 | int len = length;
65 | lastBytesProcessed = 0;
66 |
67 | while (!allBytesProcessed) {
68 |
69 | if (remainingChunkLength != 0 && ! chunkTermination ) { //receiving chunk
70 |
71 | int len2process = Math.min(len, remainingChunkLength);
72 | remainingChunkLength=remainingChunkLength-len2process;
73 | writeThrough(buf,offs,len2process);
74 | if (remainingChunkLength == 0) {
75 | chunkTermination=true;
76 | remainingChunkLength = 2; // next receive empty line
77 | }
78 | offs= offs+len2process;
79 | len = len-len2process;
80 | allBytesProcessed = (len == 0);
81 |
82 | } else if (chunkTermination) {
83 | last2Bytes = (short) ((last2Bytes <<8)+ (int)(buf[offs] & 0xff));
84 | remainingChunkLength--;
85 | writeThrough(buf,offs,1);
86 | offs++;
87 | len--;
88 | allBytesProcessed = (len == 0);
89 | if (remainingChunkLength == 0) { //termination completed
90 | if (last2Bytes != LINEEND)
91 | throw new IOException("Invalid Chunk Termination!"); // Invalid finalization
92 |
93 | if (out != null)
94 | out.flush();
95 |
96 | chunkHeader = new StringBuffer();
97 | chunkTermination = false;
98 | last2Bytes = 0;
99 | }
100 |
101 | } else if (chunkHeader != null) { // we are receiving a header
102 | chunkHeader.append((char) (buf[offs]& 0xff));
103 | last2Bytes = (short) ((last2Bytes <<8)+ (int) (buf[offs]& 0xff));
104 | if (last2Bytes == LINEEND) { //header complete
105 | last2Bytes = 0; //reset
106 | try {
107 | remainingChunkLength = Integer.parseInt(chunkHeader.toString().trim(), 16);
108 | } catch (NumberFormatException nfe) {
109 | throw new IOException("Can not parse ChunkHeader to HEX Number:"+chunkHeader.toString().trim());
110 | }
111 | if (remainingChunkLength == 0) { //final chunk
112 | chunkedRequestTermination = true;
113 | last4Bytes = LINEEND; // next receive (possibly empty) trailer
114 | }
115 | chunkHeader = null;
116 | }
117 | writeThrough(buf,offs,1);
118 | offs++;
119 | len--;
120 | allBytesProcessed = (len == 0);
121 | } else if(chunkedRequestTermination) { //receive trailer until \r\n\r\n
122 | last4Bytes = (last4Bytes <<8)+ (int) (buf[offs]& 0xff);
123 | writeThrough(buf,offs,1);
124 | offs++;
125 | len--;
126 | allBytesProcessed = (len == 0);
127 |
128 | if (last4Bytes == TRAILEREND) {
129 | if (out != null)
130 | out.flush();
131 |
132 | lastBytesProcessed = lastBytesProcessed + length-len;
133 | return false;
134 | }
135 |
136 | } else throw new IOException ("Invalid ChunkedDataTransfer State!");
137 | }
138 | lastBytesProcessed = lastBytesProcessed + length;
139 | return true;
140 | }
141 |
142 |
143 |
144 | public void initChunkedTransfer() {
145 | chunkHeader = new StringBuffer();
146 | remainingChunkLength = 0;
147 | chunkedRequestTermination = false;
148 | chunkTermination=false;
149 | chunkTermination = false;
150 | last2Bytes = 0;
151 | }
152 |
153 |
154 | }
155 |
--------------------------------------------------------------------------------
/app/src/main/java/httpproxy/HttpProxyRequest.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 |
24 | package httpproxy;
25 |
26 | import java.io.ByteArrayOutputStream;
27 | import java.io.IOException;
28 | import java.io.OutputStream;
29 |
30 |
31 |
32 | public class HttpProxyRequest extends OutputStream {
33 | private static int HEADEREND = 218762506; // \r\n\r\n
34 | private HttpProxyServer server;
35 | private int last4Bytes = 0;
36 | private ByteArrayOutputStream headerBytes = null;
37 | boolean ssl = false;
38 | private long reqContentLength=0;
39 | private int bytesBodySent=0;
40 | private boolean chunked;
41 | private ChunkedDataTransfer chunkedTransfer;
42 | private OutputStream sslOut;
43 | private boolean closed = false;
44 |
45 |
46 | public HttpProxyRequest(HttpProxyServer server) {
47 | this.server = server;
48 | }
49 |
50 | public synchronized void initRequest() {
51 | last4Bytes = 0;
52 | headerBytes = new ByteArrayOutputStream();
53 | ssl = false;
54 | server.current_status = HttpProxyServer.READ_REQUEST_HEADER;
55 | notifyAll();
56 | }
57 |
58 |
59 | @Override
60 | public void write(int b) throws IOException {
61 | write(new byte[] {(byte) b},0,1);
62 | }
63 |
64 | @Override
65 | public synchronized void write(byte[] b) throws IOException {
66 | write(b,0,b.length);
67 | }
68 |
69 |
70 | @Override
71 | public synchronized void write(byte[] b, int offs, int len) throws IOException {
72 |
73 | server.resetIdleTimeOut();
74 | boolean processed = false;
75 |
76 | while (!processed) {
77 |
78 | int processedBytes = 0;
79 |
80 | if (closed)
81 | throw new IOException ("Server already closed!");
82 |
83 | if (server.current_status == HttpProxyServer.READ_REQUEST_HEADER) {
84 |
85 | last4Bytes = (last4Bytes <<8)+ (b[offs] & 0xFF);
86 | processedBytes=1;
87 | headerBytes.write(b[offs] & 0xFF);
88 | if (last4Bytes == HEADEREND) {
89 | headerBytes.flush();
90 | server.requestHeaderReceived(headerBytes.toByteArray());
91 | headerBytes=null;
92 | }
93 | } else if (server.current_status== HttpProxyServer.PROCESS_REQUEST_BODY) {
94 | processed = true;
95 | processedBytes = writeRequestBody(b,offs,len);
96 |
97 | } else if (ssl) {
98 | sslOut.write(b,offs, len);
99 | processedBytes =len;
100 | } else {
101 | try {
102 | wait(); //block Writer until current request is processed
103 | } catch (InterruptedException e) {
104 | throw new IOException(e.getMessage());
105 | }
106 | }
107 | offs = offs+processedBytes;
108 | len = len - processedBytes;
109 | processed = (len == 0);
110 | }
111 | }
112 |
113 | public int writeRequestBody(byte[] b, int offs, int len) throws IOException {
114 | if (!chunked) {
115 | int cnt = (int)Math.min(len, reqContentLength-bytesBodySent);
116 | server.httpSrv_Out.write(b, offs,cnt);
117 | bytesBodySent = bytesBodySent+cnt;
118 | if (bytesBodySent == reqContentLength) {
119 | server.requestComplete();
120 | }
121 | return cnt;
122 | } else {
123 | boolean chunkFinal = !chunkedTransfer.write(b, offs,len);
124 | int processedBytes = chunkedTransfer.lastBytesProcessed;
125 | if (chunkFinal) { // if no more bytes -> done
126 | chunkedTransfer= null; // not needed anymore - GC to take it
127 | server.requestComplete();
128 | }
129 | return processedBytes;
130 | }
131 | }
132 |
133 |
134 | public synchronized void startSSL() {
135 |
136 | ssl = true;
137 | sslOut=server.httpSrv_Out;
138 | if (sslOut == null) //sslOut might be null in case connection was already closed before SSL request initialization
139 | closed = true;
140 | notifyAll();
141 | }
142 |
143 | @Override
144 | public void close() {
145 | server.close();
146 | }
147 |
148 | public synchronized void closeRequest() {
149 | if (closed)
150 | return;
151 | closed = true;
152 | sslOut = null;
153 | notifyAll();
154 | }
155 |
156 |
157 |
158 | @Override
159 | public synchronized void flush() throws IOException {
160 | if (closed)
161 | return;
162 |
163 | if (!ssl && server.current_status!= HttpProxyServer.PROCESS_REQUEST_BODY)
164 | return; //content was already flushed in server.requestComplete(). Response is already in process!
165 |
166 | if (ssl)
167 | sslOut.flush();
168 |
169 | else if (server.httpSrv_Out != null) //Might be no server is connected
170 | server.httpSrv_Out.flush();
171 |
172 | }
173 |
174 | public void initRequestBody(long reqContentLength, boolean chunked) {
175 | this.chunked = chunked;
176 | this.reqContentLength=reqContentLength;
177 | this.bytesBodySent = 0;
178 | if (chunked)
179 | chunkedTransfer= new ChunkedDataTransfer(server.httpSrv_Out);
180 | }
181 |
182 | }
183 |
--------------------------------------------------------------------------------
/app/src/main/java/httpproxy/HttpProxyResponse.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package httpproxy;
24 |
25 |
26 | import java.io.ByteArrayInputStream;
27 | import java.io.IOException;
28 | import java.io.InputStream;
29 | import java.net.SocketTimeoutException;
30 |
31 | import util.Logger;
32 | import util.http.HttpHeader;
33 |
34 |
35 | public class HttpProxyResponse extends InputStream {
36 |
37 | private static String HEXFILLSTR ="00000000";
38 | private static int STATIC_HEADER_LEN=HEXFILLSTR.length();
39 | private static int MIN_CHUNK_LEN = 512;
40 |
41 | private HttpProxyServer server;
42 | private ByteArrayInputStream headerIn = null;
43 | private InputStream srvHttp_In = null;
44 | private byte[] chunk = null;
45 | private boolean finalChunk = false;
46 | private int chunkOffs =0;
47 | private int chunkCount =0;
48 |
49 |
50 | private long contentLength = 0;
51 | private boolean chunkedSrvRes = false;
52 | private boolean chunkedProxyRes = false;
53 | private int contentSent = 0;
54 | private ChunkedDataTransfer chunkedTransfer = null;
55 |
56 | private boolean responseComplete = false;
57 | private boolean connectionClose = false;
58 | private boolean eof = false;
59 | private boolean ssl = false;
60 | private int available = 0;
61 | private boolean closed = false;
62 |
63 |
64 | public HttpProxyResponse(HttpProxyServer server) {
65 | this.server = server;
66 | }
67 |
68 |
69 | @Override
70 | public int read() throws IOException {
71 | byte[] b = new byte[1];
72 | int r = read(b);
73 | if (r == -1)
74 | return -1;
75 |
76 | return b[0] & 0xFF;
77 | }
78 |
79 |
80 | @Override
81 | public int read(byte[] b) throws IOException {
82 | return read(b,0,b.length);
83 | }
84 |
85 |
86 | private String getFixedLengthHexString(int number) {
87 | String hexStr = Integer.toHexString(number);
88 | hexStr = HEXFILLSTR.substring(0,STATIC_HEADER_LEN-hexStr.length())+hexStr;
89 | return hexStr;
90 | }
91 |
92 | @Override
93 | public synchronized int read(byte[] b, int off, int len) throws IOException {
94 | int r = readInternal(b,off,len);
95 | server.resetIdleTimeOut();
96 | return r;
97 | }
98 |
99 | private synchronized int readInternal(byte[] b, int off, int len) throws IOException {
100 |
101 | if (server.closed)
102 | throw new IOException ("Server already closed!");
103 |
104 | if (! (server.current_status == HttpProxyServer.PROCESS_RESPONSE_BODY || server.current_status == HttpProxyServer.RETURN_RESPONSE_HEADER)) {
105 | try {
106 | wait(server.soTimeout);
107 | if (! (server.current_status == HttpProxyServer.PROCESS_RESPONSE_BODY || server.current_status == HttpProxyServer.RETURN_RESPONSE_HEADER)) {
108 | if (server.soTimeout != 0)
109 | throw new SocketTimeoutException();
110 | }
111 | if (server.closed)
112 | throw new IOException ("Server already closed!");
113 |
114 | } catch (InterruptedException e) {
115 | throw new IOException (e.getMessage());
116 | }
117 | }
118 | if (eof)
119 | return -1;
120 |
121 |
122 | if (server.current_status == HttpProxyServer.RETURN_RESPONSE_HEADER) {
123 | int r = headerIn.read(b, off, Math.min(len, headerIn.available()));
124 | available = headerIn.available();
125 | if (headerIn.available() == 0) {
126 | server.current_status = HttpProxyServer.PROCESS_RESPONSE_BODY;
127 | headerIn = null; //GC should take it
128 | if (contentLength == 0 && !chunkedSrvRes) { // empty Body
129 | responseComplete= true;
130 | server.responseFinished(!connectionClose);
131 | }
132 | }
133 | return r;
134 | } else if (server.current_status == HttpProxyServer.PROCESS_RESPONSE_BODY) {
135 |
136 | if (chunkedProxyRes) {
137 | if (chunkOffs == chunkCount) {
138 | int chunkSize = getBestSize(len);
139 | if (len >=chunkSize+STATIC_HEADER_LEN+4) {
140 | //read directly into buffer without need to copy and return full chunk
141 | int count = srvHttp_In.read(b, STATIC_HEADER_LEN+2, chunkSize);
142 |
143 | if (count == -1) {
144 | //final chunk
145 | System.arraycopy("0\r\n\r\n".getBytes(), 0, b, 0, 5);
146 | server.responseFinished(chunkedSrvRes && !connectionClose);
147 | responseComplete= true;
148 | return 5;
149 | }
150 |
151 | byte[] hexheader=(getFixedLengthHexString(count)+"\r\n").getBytes();
152 | System.arraycopy(hexheader, 0, b, 0, STATIC_HEADER_LEN+2);
153 | b[count+STATIC_HEADER_LEN+2]=13;
154 | b[count+STATIC_HEADER_LEN+3]=10;
155 | return count+STATIC_HEADER_LEN+4;
156 | }
157 | chunk = new byte[chunkSize];
158 | chunkCount = srvHttp_In.read(chunk);
159 | if (chunkCount != -1) {
160 | byte[] chunkHeader = (getFixedLengthHexString(chunkCount)+"\r\n").getBytes();
161 | byte[] fullChunk = new byte[chunkHeader.length+chunkCount+2];
162 | System.arraycopy(chunkHeader, 0, fullChunk, 0, chunkHeader.length);
163 | System.arraycopy(chunk, 0, fullChunk, chunkHeader.length, chunkCount);
164 |
165 | //don't forget \r\n at the end of the chunk
166 | fullChunk[fullChunk.length-2] = 13;
167 | fullChunk[fullChunk.length-1] = 10;
168 | chunk = fullChunk;
169 |
170 | } else {
171 | //final chunk
172 | finalChunk = true;
173 | chunk = "0\r\n\r\n".getBytes();
174 | }
175 | chunkCount = chunk.length;
176 | chunkOffs = 0;
177 | available = chunkCount;
178 | }
179 | int count = Math.min(available, len);
180 | System.arraycopy(chunk, chunkOffs, b, off, count);
181 | chunkOffs= chunkOffs+count;
182 | available = chunkCount-chunkOffs;
183 |
184 | if (finalChunk && chunkOffs == chunkCount) {
185 | server.responseFinished(chunkedSrvRes && !connectionClose);
186 | responseComplete= true;
187 | }
188 | return count;
189 |
190 | } else if (chunkedSrvRes) {
191 |
192 | int r = srvHttp_In.read(b,off,len);
193 | available = srvHttp_In.available();
194 | if (!chunkedTransfer.write(b,off,r)) { // No more bytes, chunked Data completed and terminated
195 | if (chunkedTransfer.lastBytesProcessed != r)
196 | throw new IOException (r-chunkedTransfer.lastBytesProcessed+" bytes left in chunked HTTP Response but final chunk received!");
197 | server.responseFinished(!connectionClose);
198 | responseComplete= true;
199 | chunkedTransfer = null; //GC clean up
200 | }
201 | return r;
202 |
203 | } else if (contentLength > 0) {
204 |
205 | int r = srvHttp_In.read(b,off,(int)Math.min(len, contentLength));
206 | available = srvHttp_In.available();
207 | contentSent=contentSent+r;
208 |
209 | if (contentSent == contentLength) {
210 | server.responseFinished(!connectionClose);
211 | responseComplete= true;
212 | }
213 | return r;
214 | } else if (ssl) {
215 |
216 | int r = srvHttp_In.read(b,off,len);
217 | available = srvHttp_In.available();
218 |
219 | if (r == -1) {
220 | server.responseFinished(false);
221 | responseComplete= true;
222 | eof = true;
223 | }
224 | return r;
225 | }
226 |
227 | }
228 | throw new IOException("Invalid state!");
229 | }
230 |
231 |
232 | private int getBestSize(int len) {
233 | // get best chunk size so that it fits into a buffer of len bytes including overhead
234 | if (len < MIN_CHUNK_LEN)
235 | return MIN_CHUNK_LEN; //minimum 512 bytes chunk
236 |
237 | return (len-STATIC_HEADER_LEN-4);
238 |
239 | }
240 |
241 |
242 | public synchronized void startResponse(HttpHeader header, InputStream in, boolean ssl) {
243 |
244 | responseComplete = false;
245 | chunkedProxyRes = false;
246 | chunkedSrvRes = false;
247 | eof = false;
248 | contentSent = 0;
249 | srvHttp_In = in;
250 | this.ssl = ssl;
251 |
252 | HttpHeader resHeader=header;
253 | server.resetIdleTimeOut();
254 | if (resHeader == null) {
255 | try {
256 | if (!ssl) {
257 | try {
258 | server.setHttpServerReadTimeOut(server.INIT_CON_TO);
259 | resHeader = new HttpHeader(in, HttpHeader.RESPONSE_HEADER);
260 | if (resHeader.getResponseCode()== 100) //continue! real header next!
261 | resHeader = new HttpHeader(in, HttpHeader.RESPONSE_HEADER);
262 | } finally {
263 | server.setHttpServerReadTimeOut(server.soTimeout);
264 | }
265 | }
266 | else
267 | resHeader = new HttpHeader("HTTP/1.1 200 Connection established\r\nProxy-agent: Personal-Proxy/1.1", HttpHeader.RESPONSE_HEADER);
268 |
269 | } catch (IOException e) {
270 | startErrorResponse("HTTP/1.1 500 No valid Reponse from server!","No valid Reponse from server!\r\n"+e.getMessage());
271 | return;
272 | }
273 | }
274 |
275 | //System.out.println(resHeader.getHeaderString());
276 | connectionClose = resHeader.getConnectionClose();
277 | resHeader.setValue("Connection","Keep-Alive"); //proxy supports persistent connections
278 | this.contentLength= resHeader.getContentLength();
279 | this.chunkedSrvRes=resHeader.chunkedTransfer();
280 |
281 |
282 | if (chunkedSrvRes) {
283 | chunkedTransfer = new ChunkedDataTransfer(null);
284 | } else if (contentLength == -1 && !ssl) { //do chunked Response in case there is no contentlength set
285 | resHeader.setValue("Transfer-Encoding","chunked");
286 | chunkedProxyRes = true;
287 | chunkOffs =0;
288 | chunkCount =0;
289 | finalChunk = false;
290 | }
291 |
292 | headerIn = new ByteArrayInputStream (resHeader.getHeaderString().getBytes());
293 | available = headerIn.available();
294 |
295 | server.current_status= HttpProxyServer.RETURN_RESPONSE_HEADER;
296 | notifyAll();
297 | }
298 |
299 | public void close() {
300 | server.close();
301 | }
302 |
303 | public synchronized void closeResponse() {
304 | if (closed)
305 | return;
306 | closed = true;
307 | notifyAll();
308 | }
309 |
310 |
311 | public void startErrorResponse(String status, String body) {
312 | HttpHeader header;
313 | try {
314 | header = new HttpHeader(status+"\r\n", HttpHeader.RESPONSE_HEADER);
315 | header.setValue("Content-Length", ""+body.length());
316 | header.setValue("Connection", "close");
317 | startResponse(null, new ByteArrayInputStream((header.getHeaderString()+body).getBytes()), false);
318 | } catch (IOException e) {
319 | Logger.getLogger().logException(e);
320 | }
321 | }
322 |
323 |
324 |
325 |
326 | }
327 |
--------------------------------------------------------------------------------
/app/src/main/java/httpproxy/HttpProxyServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package httpproxy;
24 |
25 |
26 | import java.io.BufferedInputStream;
27 | import java.io.BufferedOutputStream;
28 | import java.io.ByteArrayInputStream;
29 | import java.io.IOException;
30 | import java.io.InputStream;
31 | import java.io.OutputStream;
32 | import java.net.InetSocketAddress;
33 | import java.net.Proxy;
34 | import java.net.Socket;
35 | import java.net.SocketException;
36 | import java.util.Set;
37 |
38 | import util.DateRetriever;
39 | import util.Logger;
40 | import util.LoggerInterface;
41 | import util.TimeoutListener;
42 | import util.TimeoutTime;
43 | import util.TimoutNotificator;
44 | import util.conpool.Connection;
45 | import util.http.HttpHeader;
46 |
47 | public class HttpProxyServer extends Socket implements TimeoutListener {
48 |
49 | public static final byte READ_REQUEST_HEADER = 1;
50 | public static final byte CONTACT_SERVER = 2;
51 | public static final byte SEND_REQUEST_HEADER = 3;
52 | public static final byte PROCESS_REQUEST_BODY = 4;
53 | public static final byte READ_RESPONSE_HEADER = 5;
54 | public static final byte RETURN_RESPONSE_HEADER = 6;
55 | public static final byte PROCESS_RESPONSE_BODY = 7;
56 |
57 | public static final int IDLE_TO=300000;
58 | public static final int INIT_CON_TO=120000;
59 |
60 | private static byte[]TUNNEL_RQ_FILTER_RESP = "HTTP/1.1 403 Forbidden\r\n\r\n".getBytes();
61 | private LoggerInterface TRAFFIC_LOG;
62 | private TimeoutTime idleTimeout;
63 |
64 | private String clientID="";
65 | private boolean useProxy = false;
66 | private Proxy chainedProxy = null;
67 |
68 | private Set hostFilter = null;
69 | private Set urlFilter = null;
70 | private byte[] filterResponse;
71 |
72 | public boolean closed = false;
73 |
74 | public byte current_status = 0;
75 |
76 | private HttpProxyRequest request;
77 | private HttpProxyResponse response;
78 | private String urlLogEntry=null;
79 | protected HttpHeader reqHeader = null;
80 |
81 |
82 | private Connection httpServer = null;
83 |
84 | public InputStream httpSrv_In=null;
85 | public OutputStream httpSrv_Out=null;
86 | public int soTimeout = 0;
87 |
88 |
89 | private class NullOutput extends OutputStream {
90 | @Override
91 | public void write(int arg0) throws IOException {
92 | }
93 | }
94 |
95 |
96 | public HttpProxyServer() {
97 | current_status = READ_REQUEST_HEADER; //Initial State
98 | request = new HttpProxyRequest(this);
99 | request.initRequest();
100 | response = new HttpProxyResponse(this);
101 | idleTimeout = new TimeoutTime(TimoutNotificator.getInstance());
102 | idleTimeout.setTimeout(IDLE_TO);
103 | TimoutNotificator.getInstance().register(this);
104 | TRAFFIC_LOG = Logger.getLogger();
105 |
106 | }
107 |
108 | public HttpProxyServer(LoggerInterface trafficLogger, String clientID, Proxy chainedProxy, Set hostFilter, Set urlFilter, byte[] filterResponse) {
109 | this();
110 |
111 | TRAFFIC_LOG=trafficLogger;
112 |
113 | if (chainedProxy != null) {
114 | useProxy = true;
115 | this.chainedProxy = chainedProxy;
116 | }
117 | this.clientID = clientID;
118 | this.hostFilter = hostFilter;
119 | this.urlFilter = urlFilter;
120 | this.filterResponse = filterResponse;
121 | }
122 |
123 |
124 |
125 | public OutputStream getOutputStream() {
126 | return request;
127 |
128 | }
129 |
130 | public InputStream getInputStream() {
131 | return response;
132 | }
133 |
134 |
135 | private String getURL4LogEntry() {
136 | //URL for log Entry ==> cut on first ? as otherwise that might get huge!
137 | String urlLogEntry = this.getURL(reqHeader);
138 | int idx = urlLogEntry.indexOf('?');
139 |
140 | if (idx != -1)
141 | urlLogEntry = urlLogEntry.substring(0, idx);
142 |
143 | return urlLogEntry;
144 | }
145 |
146 | public void requestHeaderReceived(byte[] headerBytes) {
147 | try {
148 | reqHeader = new HttpHeader(new ByteArrayInputStream(headerBytes), HttpHeader.REQUEST_HEADER);
149 |
150 | if (TRAFFIC_LOG!=null)
151 | urlLogEntry = getURL4LogEntry(); // reqHeader will be deleted later for saving memory - so we need to keep the URL for the traffic log
152 |
153 | } catch (IOException e1) {
154 | current_status= READ_RESPONSE_HEADER;
155 | response.startErrorResponse("HTTP/1.1 400 Bad Request!","Request Parsing failed!\r\n"+e1.getMessage());
156 | return;
157 | }
158 |
159 | boolean ssl=reqHeader.tunnelMode;
160 | long reqContentLength = reqHeader.getContentLength();
161 | boolean chunkedReq = reqHeader.chunkedTransfer();
162 |
163 | current_status = CONTACT_SERVER;
164 | boolean filtered;
165 | try {
166 | filtered = contactServer();
167 | } catch (IOException e) {
168 | current_status= READ_RESPONSE_HEADER;
169 | response.startErrorResponse("HTTP/1.1 503 Server Connect Failed!","Server Connect Failed!\n"+e.getMessage());
170 | return;
171 | }
172 | try {
173 | if (!ssl) {
174 | current_status = SEND_REQUEST_HEADER;
175 | sendRequestHeader();
176 | reqHeader = null; //GC to clean up
177 | if (reqContentLength > 0 || chunkedReq ) {
178 | current_status = PROCESS_REQUEST_BODY;
179 | request.initRequestBody(reqContentLength, chunkedReq);
180 | request.notifyAll(); //notify request to receive request body
181 | } else {
182 | requestComplete();
183 | }
184 |
185 | } else {
186 | if (useProxy) {
187 | sendRequestHeader();
188 | httpSrv_Out.flush();
189 | }
190 | HttpHeader tunnelResponse = null;
191 |
192 | current_status= READ_RESPONSE_HEADER;
193 |
194 | if (useProxy || filtered)
195 | tunnelResponse = new HttpHeader(httpSrv_In, HttpHeader.RESPONSE_HEADER);
196 |
197 | response.startResponse(tunnelResponse, httpSrv_In, true);
198 | request.startSSL();
199 | }
200 | } catch (IOException e2) {
201 | current_status= READ_RESPONSE_HEADER;
202 | response.startErrorResponse("HTTP/1.1 500 Server Error!","Request Sent failed!\n"+e2.getMessage());
203 | return;
204 | }
205 | }
206 |
207 |
208 | public void requestComplete() throws IOException {
209 | httpSrv_Out.flush();
210 | current_status= READ_RESPONSE_HEADER;
211 | response.startResponse(null, httpSrv_In, false);
212 | }
213 |
214 |
215 | private void sendRequestHeader() throws IOException {
216 | httpSrv_Out.write(reqHeader.getServerRequestHeader(useProxy).getBytes());
217 | httpSrv_Out.flush(); // flush as soon as possible to prevent pooled connection to be closed by http server
218 | }
219 |
220 |
221 |
222 | private String getURL(HttpHeader reqHeader){
223 | String url;
224 | if (reqHeader.tunnelMode) {
225 | if (reqHeader.remote_port != 443)
226 | url = "https://"+reqHeader.hostEntry+"/";
227 | else
228 | url = "https://"+reqHeader.remote_host_name+"/";
229 | } else {
230 | if (reqHeader.remote_port != 80)
231 | url = "http://"+reqHeader.hostEntry+reqHeader.url;
232 | else
233 | url = "http://"+reqHeader.remote_host_name+reqHeader.url;
234 | }
235 | return url;
236 | }
237 |
238 |
239 | private boolean filter(HttpHeader reqHeader) {
240 | if (hostFilter != null && hostFilter.contains(reqHeader.remote_host_name)) {
241 | Logger.getLogger().logLine("FILTERED:"+reqHeader.remote_host_name);
242 | return true;
243 | } else if (urlFilter != null) {
244 | String url = getURL(reqHeader);
245 | if (urlFilter.contains(url)) {
246 | Logger.getLogger().logLine("FILTERED:"+url);
247 | return true;
248 | } else return false;
249 |
250 | } else return false;
251 |
252 | }
253 |
254 | protected boolean contactServer() throws IOException {
255 |
256 | boolean filter = filter(reqHeader);
257 | if (filter) {
258 | httpSrv_Out = new NullOutput();
259 |
260 | if (reqHeader.tunnelMode)
261 | httpSrv_In = new ByteArrayInputStream(TUNNEL_RQ_FILTER_RESP);
262 | else
263 | httpSrv_In = new ByteArrayInputStream(filterResponse);
264 |
265 | } else {
266 | Logger.getLogger().logLine("REQUESTING:"+reqHeader.remote_host_name+" on port "+reqHeader.remote_port);
267 | if (useProxy)
268 | httpServer = Connection.connect((InetSocketAddress)chainedProxy.address(),INIT_CON_TO);
269 | else
270 | httpServer = Connection.connect(reqHeader.remote_host_name,reqHeader.remote_port,INIT_CON_TO);
271 |
272 | httpSrv_In = new BufferedInputStream(httpServer.getInputStream());
273 | httpSrv_Out = new BufferedOutputStream ( httpServer.getOutputStream());
274 |
275 |
276 | setHttpServerReadTimeOut(soTimeout);
277 | }
278 | return filter;
279 | }
280 |
281 |
282 | protected synchronized void releaseServer(boolean reuse) {
283 |
284 | if (httpSrv_In== null)
285 | return; // already released by other thread
286 |
287 | if (httpServer != null && TRAFFIC_LOG!=null) {
288 | long traffic[] = httpServer.getTraffic();
289 | TRAFFIC_LOG.logLine(DateRetriever.getDateString()+", "+clientID+", "+httpServer.getDestination()+", "+traffic[0]+", "+traffic[1]+", "+urlLogEntry);
290 | } else if (TRAFFIC_LOG!=null) //no connection - filtered!
291 | TRAFFIC_LOG.logLine(DateRetriever.getDateString()+", "+clientID+", , 0, 0, "+ urlLogEntry);
292 |
293 | if (httpServer != null)
294 | httpServer.release(reuse);
295 |
296 | httpServer = null;
297 | httpSrv_In = null;
298 | httpSrv_Out = null;
299 | }
300 |
301 |
302 |
303 |
304 | public void responseFinished(boolean reuseServer) {
305 | releaseServer(reuseServer);
306 | urlLogEntry = null; //reset
307 | request.initRequest();
308 | }
309 |
310 | @Override
311 | public void close() {
312 | if (closed)
313 | return;
314 | TimoutNotificator.getInstance().unregister(this);
315 | closed = true;
316 |
317 | if (httpServer != null) //connection is not finished we cannot reuse
318 | releaseServer(false);
319 |
320 | response.closeResponse();
321 | request.closeRequest();
322 |
323 | }
324 |
325 | @Override
326 | public void setSoTimeout(int timeout) throws SocketException {
327 | soTimeout = timeout;
328 | setHttpServerReadTimeOut(timeout);
329 | }
330 |
331 | protected void setHttpServerReadTimeOut(int to) throws SocketException {
332 | if (httpServer != null) //might be null when not yet connected or in case of blocked host with filter response
333 | httpServer.setSoTimeout(to);
334 | }
335 |
336 |
337 | @Override
338 | public void shutdownInput() throws IOException {
339 | //nothing
340 | }
341 |
342 | @Override
343 | public void shutdownOutput() throws IOException {
344 | //nothing
345 | }
346 |
347 | @Override
348 | public void timeoutNotification() {
349 | close();
350 | }
351 |
352 | @Override
353 | public long getTimoutTime() {
354 | return idleTimeout.getTimeout();
355 | }
356 |
357 | public void resetIdleTimeOut() {
358 | idleTimeout.setTimeout(IDLE_TO);
359 | }
360 |
361 |
362 | }
363 |
--------------------------------------------------------------------------------
/app/src/main/java/httpproxy/android/BootUpReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 | package httpproxy.android;
23 |
24 | import java.io.File;
25 | import java.io.FileInputStream;
26 | import java.io.InputStream;
27 | import java.util.Properties;
28 |
29 | import android.content.BroadcastReceiver;
30 | import android.content.Context;
31 | import android.content.Intent;
32 | import android.os.Environment;
33 |
34 | public class BootUpReceiver extends BroadcastReceiver{
35 |
36 | @Override
37 | public void onReceive(Context context, Intent intent) {
38 | Properties config;
39 | if ((config = getConfig()) != null && Boolean.parseBoolean(config.getProperty("AUTOSTART", "false"))) {
40 | HttpProxyActivity.BOOT_START=true;
41 | Intent i = new Intent(context, HttpProxyActivity.class);
42 | i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
43 | context.startActivity(i);
44 | }
45 |
46 | }
47 |
48 |
49 | public Properties getConfig() {
50 |
51 | File propsFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/PersonalHttpProxy/httpproxy.conf");
52 |
53 | try {
54 | InputStream in = new FileInputStream(propsFile);
55 | Properties config= new Properties();
56 | config.load(in);
57 | in.close();
58 | return config;
59 | } catch (Exception e ) {
60 | return null;
61 | }
62 | }
63 |
64 | }
--------------------------------------------------------------------------------
/app/src/main/java/httpproxy/android/HttpProxyService.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 | package httpproxy.android;
23 |
24 |
25 | import proxy.HttpProxy;
26 | import util.ExecutionEnvironment;
27 | import util.ExecutionEnvironmentInterface;
28 | import util.Logger;
29 | import android.app.Notification;
30 | import android.app.PendingIntent;
31 | import android.app.Service;
32 | import android.content.Context;
33 | import android.content.Intent;
34 | import android.os.IBinder;
35 | import android.os.PowerManager;
36 | import android.os.PowerManager.WakeLock;
37 |
38 | public class HttpProxyService extends Service implements ExecutionEnvironmentInterface {
39 |
40 | public static HttpProxy httpproxy = null;
41 | private static WakeLock wakeLock = null;
42 |
43 | @Override
44 | public void onStart(Intent intent, int startId) {
45 | super.onStart(intent, startId);
46 | ExecutionEnvironment.setEnvironment(this);
47 | try {
48 | Notification notification = new Notification();
49 | Intent notificationIntent = new Intent(this, HttpProxyActivity.class);
50 | PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
51 | notification.setLatestEventInfo(this, "PersonalHttpProxy", "Running", pendingIntent);
52 | startForeground(23, notification);
53 | if (httpproxy != null) {
54 | Logger.getLogger().logLine("HTTPproxy already running!");
55 | } else {
56 | try {
57 | HttpProxy.WORKDIR=HttpProxyActivity.WORKPATH.getAbsolutePath()+"/";
58 | httpproxy = new HttpProxy();
59 | httpproxy.initMainLoop(new String[] {"-async"});
60 | Logger.getLogger().logLine("HTTPproxy started!");
61 | } catch (Exception e) {
62 | httpproxy = null;
63 | Logger.getLogger().logException(e);
64 | }
65 | }
66 | } catch (Exception e) {
67 | Logger.getLogger().logException(e);
68 | }
69 | }
70 |
71 | @Override
72 | public void onDestroy() {
73 | try {
74 | if (httpproxy != null) {
75 | httpproxy.stop();
76 | Logger.getLogger().logLine("HTTPproxy stopped!");
77 | }
78 | httpproxy = null;
79 | } catch (Exception e) {
80 | Logger.getLogger().logException(e);
81 | }
82 |
83 | }
84 |
85 | @Override
86 | public IBinder onBind(Intent intent) {
87 | // TODO Auto-generated method stub
88 | return null;
89 | }
90 |
91 | public int onStartCommand(Intent intent, int flags, int startId) {
92 | onStart(intent, startId);
93 | // We want this service to continue running until it is explicitly
94 | // stopped, so return sticky.
95 | return START_STICKY;
96 | }
97 |
98 | @Override
99 | public void wakeLock() {
100 | wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
101 | wakeLock.acquire();
102 | }
103 |
104 | @Override
105 | public void releaseWakeLock() {
106 | WakeLock wl = wakeLock;
107 | if (wl != null)
108 | wl.release();
109 | }
110 |
111 | @Override
112 | public String getWorkDir() {
113 | return HttpProxyActivity.WORKPATH.getAbsolutePath()+"/";
114 | }
115 | }
--------------------------------------------------------------------------------
/app/src/main/java/proxy/BlockedHosts.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalDNSFilter 1.5
3 | Copyright (C) 2017 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personaldnsfilter
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package proxy;
24 |
25 | import java.io.IOException;
26 | import java.util.Collection;
27 | import java.util.Hashtable;
28 | import java.util.Iterator;
29 | import java.util.Set;
30 |
31 | import util.HugePackedSet;
32 | import util.LRUCache;
33 | import util.ObjectPackagingManager;
34 | import util.Utils;
35 |
36 | public class BlockedHosts implements Set{
37 |
38 | private static class MyPackagingManager implements ObjectPackagingManager {
39 |
40 | @Override
41 | public int objectSize() {
42 | return 8;
43 | }
44 |
45 | @Override
46 | public Object bytesToObject(byte[] data, int offs){
47 | return Utils.byteArrayToLong(data, offs);
48 | }
49 |
50 | @Override
51 | public void objectToBytes(Object object, byte[] data, int offs) {
52 | Utils.writeLongToByteArray((Long)object, data, offs);
53 | }
54 |
55 | }
56 |
57 | private static ObjectPackagingManager PACK_MGR = new MyPackagingManager();
58 | private static Object NOT_NULL = new Object();
59 | private LRUCache okCache;
60 | private LRUCache filterListCache;
61 | private Hashtable hostsFilterOverRule;
62 |
63 | private int sharedLocks = 0;
64 | private boolean exclusiveLock = false;
65 |
66 | private HugePackedSet blockedHostsHashes;
67 |
68 | public BlockedHosts(int maxCountEstimate, int okCacheSize, int filterListCacheSize, Hashtable hostsFilterOverRule) {
69 | okCache = new LRUCache(okCacheSize);
70 | filterListCache = new LRUCache(filterListCacheSize);
71 | this.hostsFilterOverRule= hostsFilterOverRule;
72 |
73 | int slots = maxCountEstimate / 6000;
74 | if ((slots % 2) == 0)
75 | slots++;
76 |
77 | blockedHostsHashes = new HugePackedSet(slots, PACK_MGR);
78 | }
79 |
80 | private BlockedHosts(HugePackedSet blockedHostsHashes, int okCacheSize, int filterListCacheSize, Hashtable hostsFilterOverRule) {
81 | this.blockedHostsHashes = blockedHostsHashes;
82 | okCache = new LRUCache(okCacheSize);
83 | filterListCache = new LRUCache(filterListCacheSize);
84 | this.hostsFilterOverRule= hostsFilterOverRule;
85 | }
86 |
87 |
88 | synchronized public void lock(int type) {
89 | if (type == 0) {
90 | while (exclusiveLock) {
91 | try {
92 | wait();
93 | } catch (Exception e) {
94 | // ignore
95 | }
96 | }
97 | sharedLocks++;
98 | } else if (type == 1) {
99 | while (!(sharedLocks == 0) || (exclusiveLock)) {
100 | try {
101 | wait();
102 | } catch (InterruptedException e) {
103 | // ignore
104 | }
105 | }
106 |
107 | exclusiveLock = true;
108 | }
109 | }
110 |
111 | synchronized public void unLock(int type) {
112 | if (type == 0) {
113 | if (sharedLocks > 0) {
114 | sharedLocks--;
115 | if (sharedLocks == 0) {
116 | notifyAll();
117 | }
118 | }
119 | } else if (type == 1) {
120 | if (exclusiveLock) {
121 | exclusiveLock = false;
122 | notifyAll();
123 | }
124 | }
125 | }
126 |
127 |
128 | public static boolean checkIndexVersion(String path) throws IOException {
129 | return HugePackedSet.checkIndexVersion(path);
130 | }
131 |
132 | public static BlockedHosts loadPersistedIndex(String path, boolean inMemory, int okCacheSize, int filterListCacheSize, Hashtable hostsFilterOverRule) throws IOException {
133 | return new BlockedHosts(HugePackedSet.load(path, inMemory, PACK_MGR), okCacheSize, filterListCacheSize, hostsFilterOverRule);
134 | }
135 |
136 | public void persist(String path) throws IOException {
137 | blockedHostsHashes.persist(path);
138 | }
139 |
140 | public void prepareInsert(String host) {
141 | blockedHostsHashes.prepareInsert(Utils.getLongStringHash(host));
142 | }
143 |
144 | public void finalPrepare() {
145 | blockedHostsHashes.finalPrepare();
146 | }
147 |
148 | @Override
149 | public boolean add(Object host) {
150 | return blockedHostsHashes.add(Utils.getLongStringHash((String) host));
151 | }
152 |
153 | @Override
154 | public boolean contains(Object object) {
155 |
156 | try {
157 | lock(0); //shared read lock ==> block Updates of the structure
158 |
159 | String hostName = (String) object;
160 | long hosthash = Utils.getLongStringHash(hostName);
161 | if (okCache.get(hosthash) != null)
162 | return false;
163 | else if (filterListCache.get(hosthash) != null)
164 | return true;
165 | else if (contains(hostName, hosthash)) {
166 | filterListCache.put(hosthash, NOT_NULL);
167 | return true;
168 | } else {
169 | okCache.put(hosthash, NOT_NULL);
170 | return false;
171 | }
172 | } finally {
173 | unLock(0);
174 | }
175 | }
176 |
177 |
178 | private boolean contains(String hostName, long hosthash) {
179 |
180 | if (hostsFilterOverRule!= null) {
181 | Object val = hostsFilterOverRule.get(hostName);
182 | if (val != null)
183 | return ((Boolean) val).booleanValue();
184 | }
185 | if (blockedHostsHashes.contains(hosthash))
186 | return true;
187 |
188 | int idx = hostName.indexOf('.');
189 | while (idx != -1) {
190 | hostName = hostName.substring(idx + 1);
191 |
192 | if (hostsFilterOverRule!= null) {
193 | Object val = hostsFilterOverRule.get(hostName);
194 | if (val != null)
195 | return ((Boolean) val).booleanValue();
196 | }
197 |
198 | if (blockedHostsHashes.contains(Utils.getLongStringHash(hostName)))
199 | return true;
200 | idx = hostName.indexOf('.');
201 | }
202 | return false;
203 | }
204 |
205 | public void clear() {
206 | blockedHostsHashes.clear();
207 | filterListCache.clear();
208 | okCache.clear();
209 | }
210 |
211 | protected void migrateTo(BlockedHosts hostFilter) {
212 |
213 | // should be under exclusive lock from caller
214 | okCache.clear();
215 | okCache = hostFilter.okCache;
216 |
217 | filterListCache.clear();
218 | filterListCache = hostFilter.filterListCache;
219 |
220 | hostsFilterOverRule = hostFilter.hostsFilterOverRule;
221 |
222 | blockedHostsHashes.migrateTo(hostFilter.blockedHostsHashes);
223 | }
224 |
225 | @Override
226 | public boolean addAll(Collection arg0) {
227 | throw new UnsupportedOperationException("Not supported!");
228 | }
229 |
230 | @Override
231 | public boolean containsAll(Collection arg0) {
232 | throw new UnsupportedOperationException("Not supported!");
233 | }
234 |
235 | @Override
236 | public boolean isEmpty() {
237 | // TODO Auto-generated method stub
238 | return blockedHostsHashes.isEmpty();
239 | }
240 |
241 | @Override
242 | public Iterator iterator() {
243 | throw new UnsupportedOperationException("Not supported!");
244 | }
245 |
246 | @Override
247 | public boolean remove(Object object) {
248 | throw new UnsupportedOperationException("Not supported!");
249 | }
250 |
251 | @Override
252 | public boolean removeAll(Collection arg0) {
253 | throw new UnsupportedOperationException("Not supported!");
254 | }
255 |
256 | @Override
257 | public boolean retainAll(Collection arg0) {
258 | throw new UnsupportedOperationException("Not supported!");
259 | }
260 |
261 | @Override
262 | public int size() {
263 | return blockedHostsHashes.size();
264 | }
265 |
266 | @Override
267 | public Object[] toArray() {
268 | throw new UnsupportedOperationException("Not supported!");
269 | }
270 |
271 | @Override
272 | public Object[] toArray(Object[] array) {
273 | throw new UnsupportedOperationException("Not supported!");
274 | }
275 |
276 |
277 |
278 | }
279 |
--------------------------------------------------------------------------------
/app/src/main/java/proxy/BlockedUrls.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package proxy;
24 |
25 | import java.io.BufferedReader;
26 | import java.io.IOException;
27 | import java.io.InputStream;
28 | import java.io.InputStreamReader;
29 | import java.util.Collection;
30 | import java.util.Hashtable;
31 | import java.util.Iterator;
32 | import java.util.Set;
33 | import java.util.Vector;
34 |
35 | import util.LRUCache;
36 | import util.Utils;
37 |
38 | public class BlockedUrls implements Set {
39 |
40 | private static int MAXPREFIX_LEN=20;
41 | private LRUCache okCache;
42 | private LRUCache filterListCache;
43 | private Hashtable urlFilterOverRule;
44 |
45 | private int sharedLocks = 0;
46 | private boolean exclusiveLock = false;
47 |
48 | private Vector blockedURLs;
49 |
50 | public BlockedUrls(int okCacheSize, int filterListCacheSize, Hashtable urlFilterOverRule) {
51 | okCache = new LRUCache(okCacheSize);
52 | filterListCache = new LRUCache(filterListCacheSize);
53 | this.urlFilterOverRule = urlFilterOverRule;
54 | blockedURLs = new Vector();
55 | }
56 |
57 | public void appyList(InputStream in) throws IOException {
58 | lock(1);
59 | try {
60 | clear();
61 | BufferedReader rin = new BufferedReader(new InputStreamReader(in));
62 | String entry;
63 | while ((entry = rin.readLine()) != null) {
64 | entry = entry.trim();
65 | if (!entry.startsWith("#") && !entry.equals(""))
66 | blockedURLs.addElement(entry.trim().split("\\*", -1));
67 | }
68 | rin.close();
69 | } finally {
70 | unLock(1);
71 | }
72 | }
73 |
74 | synchronized public void lock(int type) {
75 | if (type == 0) {
76 | while (exclusiveLock) {
77 | try {
78 | wait();
79 | } catch (Exception e) {
80 | // ignore
81 | }
82 | }
83 | sharedLocks++;
84 | } else if (type == 1) {
85 | while (!(sharedLocks == 0) || (exclusiveLock)) {
86 | try {
87 | wait();
88 | } catch (InterruptedException e) {
89 | // ignore
90 | }
91 | }
92 |
93 | exclusiveLock = true;
94 | }
95 | }
96 |
97 | synchronized public void unLock(int type) {
98 | if (type == 0) {
99 | if (sharedLocks > 0) {
100 | sharedLocks--;
101 | if (sharedLocks == 0) {
102 | notifyAll();
103 | }
104 | }
105 | } else if (type == 1) {
106 | if (exclusiveLock) {
107 | exclusiveLock = false;
108 | notifyAll();
109 | }
110 | }
111 | }
112 |
113 | @Override
114 | public boolean add(Object host) {
115 | throw new UnsupportedOperationException("Not supported!");
116 | }
117 |
118 | private String prefix(String str, int len) {
119 | if (str == null)
120 | return null;
121 | else return str.substring(0, Math.min(str.length(), len));
122 | }
123 |
124 | private boolean isPrefix(String str, String prefix, int len) {
125 | return prefix(str,len).equals(prefix);
126 | }
127 |
128 |
129 | @Override
130 | public boolean contains(Object object) {
131 |
132 | // Positive and negative URL match caches are used as wildcard matching is expensive.
133 | // Optimized Caching as URLs can get pretty long.
134 | // URL match data is cached with the longhash as key and a URL prefix (maximum length MAXPREFIX_LEN) as value.
135 | // When checking, it is checked if the cache contains an entry (longhash, prefix).
136 | // should be pretty safe - however there might be very rare cases of false positives ==> ignored for now!
137 |
138 | try {
139 | lock(0); // shared read lock ==> block Updates of the structure
140 |
141 | String url = (String) object;
142 |
143 | //in OK Cache ==> Not filtered
144 | if (isPrefix(url, (String)okCache.get(Utils.getLongStringHash(url)), MAXPREFIX_LEN))
145 | return false;
146 | //else in negative cache ==> Filtered
147 | else if (isPrefix(url, (String) filterListCache.get(Utils.getLongStringHash(url)),MAXPREFIX_LEN))
148 | return true;
149 | //else check wildcards and update caches
150 | else if (containsMatch(url)) {
151 | filterListCache.put(Utils.getLongStringHash(url), prefix(url,MAXPREFIX_LEN));
152 | return true;
153 | } else {
154 | okCache.put(Utils.getLongStringHash(url), prefix(url,MAXPREFIX_LEN));
155 | return false;
156 | }
157 | } finally {
158 | unLock(0);
159 | }
160 | }
161 |
162 | private boolean containsMatch(String url) {
163 |
164 | if (urlFilterOverRule != null) {
165 | Object val = urlFilterOverRule.get(url);
166 | if (val != null)
167 | return ((Boolean) val).booleanValue();
168 | }
169 | Iterator it = blockedURLs.iterator();
170 | while (it.hasNext()) {
171 | String[] fixedParts = (String[]) it.next();
172 | if (wildCardMatch(fixedParts, url))
173 | return true;
174 | }
175 | return false;
176 | }
177 |
178 | public static boolean wildCardMatch(String[] fixedParts, String url) {
179 |
180 | // Iterate over the parts.
181 | for (int i = 0; i < fixedParts.length; i++) {
182 | String part = fixedParts[i];
183 |
184 | int idx = -1;
185 | if (i < fixedParts.length-1)
186 | idx = url.indexOf(part);
187 | else
188 | idx = url.lastIndexOf(part);
189 |
190 |
191 | if (i == 0 && !part.equals("") && idx != 0) {
192 | // i == 0 ==> we are on the first fixed part
193 | // first fixed part is not empty ==> Matching String must start with first fixed part
194 | // if not, no match!
195 | return false;
196 | }
197 |
198 | if (i == fixedParts.length-1 && !part.equals("") && idx + part.length() != url.length()) {
199 | // i == last part
200 | // last part is not empty ==> Matching String must end with last part
201 | // if not, no match
202 | return false;
203 | }
204 |
205 | // part not detected in the text.
206 | if (idx == -1) {
207 | return false;
208 | }
209 |
210 | // Move ahead, towards the right of the text.
211 | url = url.substring(idx + part.length());
212 |
213 | }
214 |
215 | return true;
216 | }
217 |
218 | public void clear() {
219 | blockedURLs.clear();
220 | filterListCache.clear();
221 | okCache.clear();
222 | }
223 |
224 | @Override
225 | public boolean addAll(Collection arg0) {
226 | throw new UnsupportedOperationException("Not supported!");
227 | }
228 |
229 | @Override
230 | public boolean containsAll(Collection arg0) {
231 | throw new UnsupportedOperationException("Not supported!");
232 | }
233 |
234 | @Override
235 | public boolean isEmpty() {
236 | // TODO Auto-generated method stub
237 | throw new UnsupportedOperationException("Not supported!");
238 | }
239 |
240 | @Override
241 | public Iterator iterator() {
242 | throw new UnsupportedOperationException("Not supported!");
243 | }
244 |
245 | @Override
246 | public boolean remove(Object object) {
247 | throw new UnsupportedOperationException("Not supported!");
248 | }
249 |
250 | @Override
251 | public boolean removeAll(Collection arg0) {
252 | throw new UnsupportedOperationException("Not supported!");
253 | }
254 |
255 | @Override
256 | public boolean retainAll(Collection arg0) {
257 | throw new UnsupportedOperationException("Not supported!");
258 | }
259 |
260 | @Override
261 | public int size() {
262 | throw new UnsupportedOperationException("Not supported!");
263 | }
264 |
265 | @Override
266 | public Object[] toArray() {
267 | throw new UnsupportedOperationException("Not supported!");
268 | }
269 |
270 | @Override
271 | public Object[] toArray(Object[] array) {
272 | throw new UnsupportedOperationException("Not supported!");
273 | }
274 |
275 | }
276 |
--------------------------------------------------------------------------------
/app/src/main/java/proxy/Transmitter.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | PersonalHttpProxy 1.5
4 | Copyright (C) 2013-2015 Ingo Zenz
5 |
6 | This program is free software; you can redistribute it and/or
7 | modify it under the terms of the GNU General Public License
8 | as published by the Free Software Foundation; either version 2
9 | of the License, or (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program; if not, write to the Free Software
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 |
20 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
21 | Contact:i.z@gmx.net
22 | */
23 |
24 | package proxy;
25 |
26 | import java.io.*;
27 | import java.net.*;
28 |
29 | import util.Logger;
30 |
31 |
32 | public class Transmitter implements Runnable {
33 | Socket source = null;
34 | Socket dest = null;
35 | HttpProxy proxy = null;
36 | String role = null;
37 |
38 | InputStream in = null;
39 | OutputStream out = null;
40 |
41 | public Transmitter(Socket source, Socket dest, HttpProxy proxy, String role) {
42 | this.proxy = proxy;
43 | this.dest = dest;
44 | this.source = source;
45 | this.role = role;
46 | }
47 |
48 | public boolean start() {
49 | try {
50 | in = source.getInputStream();
51 | out = dest.getOutputStream();
52 | } catch (Exception e) {
53 | System.out.println(role + ":Exception during startup " + e.toString());
54 | return (false);
55 | }
56 |
57 | Thread transferThread = new Thread(this);
58 | transferThread.start();
59 | return (true);
60 | }
61 |
62 | public void run() {
63 |
64 | try {
65 | int r = 0;
66 | byte[] b = new byte[5096];
67 |
68 | while ((r = in.read(b)) != -1) {
69 |
70 | out.write(b, 0, r);
71 | out.flush();
72 |
73 | if (proxy.debug) {
74 | for (int i = 0; i < r; i++)
75 | if (!((b[i] < 64 && b[i] > 32) || (b[i] < 91 && b[i] > 64) || (b[i] < 123 && b[i] > 96)))
76 | if (b[i] != 10 && b[i] != 13)
77 | b[i] = 46;
78 | Logger.getLogger().log(new String(b, 0, r));
79 | }
80 |
81 | }
82 |
83 | proxy.cleanUp(0, role);
84 | } catch (IOException eio) {
85 | proxy.cleanUp(-1, role);
86 | } catch (Exception e) {
87 | Logger.getLogger().logException(e);
88 | proxy.cleanUp(-1, role);
89 | }
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/app/src/main/java/util/AsyncBulkLogger.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2016 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | import java.io.IOException;
26 | import java.io.PipedInputStream;
27 | import java.io.PipedOutputStream;
28 | import java.io.PrintStream;
29 |
30 | public class AsyncBulkLogger implements LoggerInterface, Runnable {
31 |
32 | private LoggerInterface out = null;
33 | private PipedOutputStream pout;
34 | private PrintStream psout;
35 | private PipedInputStream pin;
36 | private boolean closed = false;
37 | private boolean timeStampEnabled = false;
38 |
39 | public AsyncBulkLogger(LoggerInterface out) throws IOException {
40 | this.out = out;
41 | logOpen();
42 | }
43 |
44 | public void enableTimestamp(boolean enable) {
45 | timeStampEnabled = enable;
46 | }
47 |
48 | private void logOpen() throws IOException {
49 | pin = new PipedInputStream(10240);
50 | pout = new PipedOutputStream(pin);
51 | psout = new PrintStream(pout, true);
52 |
53 | Thread t = new Thread(this);
54 | t.setDaemon(true);
55 | t.start();
56 | }
57 |
58 | public void closeLogger() {
59 | synchronized (pin) {
60 | try {
61 | closed = true;
62 | pout.close();
63 | pin.notifyAll();
64 | } catch (IOException e) {
65 | e.printStackTrace();
66 | }
67 | }
68 | }
69 |
70 |
71 | @Override
72 | public void logLine(String txt) {
73 | synchronized (psout) {
74 | synchronized (pin) {
75 | if (timeStampEnabled)
76 | psout.print(DateRetriever.getDateString() + " ");
77 | psout.println(txt);
78 | pin.notifyAll();
79 | }
80 | }
81 | }
82 |
83 | @Override
84 | public void logException(Exception e) {
85 | synchronized (psout) {
86 | synchronized (pin) {
87 | if (timeStampEnabled)
88 | psout.print(DateRetriever.getDateString() + " ");
89 | e.printStackTrace(psout);
90 | pin.notifyAll();
91 | }
92 | }
93 | }
94 |
95 | @Override
96 | public void log(String txt) {
97 | synchronized (psout) {
98 | synchronized (pin) {
99 | if (timeStampEnabled)
100 | psout.print(DateRetriever.getDateString() + " ");
101 | psout.print(txt);
102 | pin.notifyAll();
103 | }
104 | }
105 | }
106 |
107 | @Override
108 | public void run() {
109 |
110 | byte[] buf = new byte[4096];
111 | int r = 0;
112 |
113 | while (!closed) {
114 | try {
115 | synchronized (pin) {
116 |
117 | while ((pin.available() <= 0) && !closed) {
118 | try {
119 | pin.wait();
120 | } catch (InterruptedException e) {
121 | // TODO Auto-generated catch block
122 | e.printStackTrace();
123 | }
124 | }
125 | if (!closed)
126 | r = pin.read(buf);
127 | }
128 |
129 | if (!closed) {
130 |
131 | out.log(new String(buf, 0, r));
132 |
133 | }
134 | } catch (Exception e) {
135 | e.printStackTrace();
136 | }
137 |
138 | }
139 |
140 | }
141 |
142 | }
143 |
--------------------------------------------------------------------------------
/app/src/main/java/util/DateRetriever.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 |
24 | package util;
25 |
26 | import java.util.Calendar;
27 |
28 | public class DateRetriever implements Runnable {
29 |
30 | private static int PRECISION_MILLIS = 1000;
31 | private static DateRetriever RETRIEVER_INSTANCE = new DateRetriever();
32 |
33 | private Thread _thread = null;
34 | private String current;
35 | private boolean picked = false;
36 |
37 |
38 |
39 | public static String getDateString() {
40 | return RETRIEVER_INSTANCE.retrieveDateString();
41 | }
42 |
43 | private String int2Str(int val) {
44 | if (val < 10)
45 | return "0" + val;
46 | else
47 | return "" + val;
48 | }
49 |
50 | private String dateStr(Calendar cal) {
51 |
52 | return (int2Str(cal.get(Calendar.MONTH) + 1)) + "/" + int2Str(cal.get(Calendar.DAY_OF_MONTH)) + "/" + cal.get(Calendar.YEAR) + " " + int2Str(cal.get(Calendar.HOUR_OF_DAY)) + ":" + int2Str(cal.get(Calendar.MINUTE)) + ":"
53 | + int2Str(cal.get(Calendar.SECOND));
54 | }
55 |
56 | private synchronized String retrieveDateString() {
57 | picked=true;
58 | if (_thread != null) {
59 | return current;
60 | } else {
61 | current = dateStr(Calendar.getInstance());
62 | _thread = new Thread(this);
63 | _thread.setDaemon(true);
64 | _thread.start();
65 |
66 | return current;
67 | }
68 |
69 | }
70 |
71 |
72 | private void waitMillis(long millis) {
73 | try {
74 | wait(millis);
75 | } catch (InterruptedException e) {
76 | Logger.getLogger().logException(e);
77 | }
78 |
79 | }
80 |
81 | @Override
82 | public synchronized void run() {
83 | _thread = Thread.currentThread();
84 |
85 | waitMillis(PRECISION_MILLIS); //initial date set already - will be valid for PRECISION_MILLIS milliseconds - No need to update the date
86 | while (picked) {
87 | current = dateStr(Calendar.getInstance());
88 | picked=false;
89 | waitMillis(PRECISION_MILLIS);
90 | }
91 | _thread = null;
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/app/src/main/java/util/ExecutionEnvironment.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | public class ExecutionEnvironment implements ExecutionEnvironmentInterface {
26 |
27 | private static ExecutionEnvironmentInterface m_Env;
28 | private static ExecutionEnvironmentInterface m_default = new ExecutionEnvironment();
29 |
30 |
31 | public static void setEnvironment(ExecutionEnvironmentInterface env) {
32 | m_Env = env;
33 | }
34 |
35 | public static ExecutionEnvironmentInterface getEnvironment() {
36 | if (m_Env != null)
37 | return m_Env;
38 | else
39 | return m_default;
40 | }
41 |
42 |
43 | @Override
44 | public void wakeLock() {
45 | // by default do nothing
46 |
47 | }
48 |
49 | @Override
50 | public void releaseWakeLock() {
51 | // by default do nothing
52 | }
53 |
54 | @Override
55 | public String getWorkDir() {
56 | return "./";
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/util/ExecutionEnvironmentInterface.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | public interface ExecutionEnvironmentInterface {
26 |
27 | public void wakeLock();
28 | public void releaseWakeLock();
29 | public String getWorkDir();
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/util/FileLogger.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2016 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | import java.io.File;
26 | import java.io.FileOutputStream;
27 | import java.io.IOException;
28 | import java.io.OutputStream;
29 | import java.io.PipedInputStream;
30 | import java.io.PipedOutputStream;
31 | import java.io.PrintStream;
32 |
33 | public class FileLogger implements LoggerInterface, Runnable {
34 |
35 | private String logFolderPath;
36 | private String name;
37 | private long slotSize;
38 | private int slotCount;
39 | private String header;
40 | private long curSlotSize = 0;
41 | private int curSlot = 0;
42 | private OutputStream fout = null;
43 | private PipedOutputStream pout;
44 | private PrintStream psout;
45 | private PipedInputStream pin;
46 | private boolean closed = false;
47 | private boolean timeStampEnabled = false;
48 |
49 | public FileLogger(String logFolderPath, String name, long slotSize, int slotCount, String header) throws IOException {
50 |
51 | if (slotSize < 1 || slotCount < 1)
52 | throw new IllegalArgumentException("slotSize and slotCount must not be less than 1");
53 | this.logFolderPath = logFolderPath+"/"+name;
54 | this.name = name;
55 | this.slotSize = slotSize;
56 | this.slotCount = slotCount;
57 | this.header = header;
58 | logOpen();
59 | }
60 |
61 | private void logOpen() throws IOException {
62 |
63 | File dir = new File(logFolderPath);
64 | if (!dir.exists())
65 | dir.mkdirs();
66 |
67 | long ts = 0;
68 | File f = null;
69 | for (int i = 0; i < slotCount; i++) {
70 | f = new File(logFolderPath + "/" + name + "_" + i + ".log");
71 | if (f.exists() && f.lastModified() > ts) {
72 | ts = f.lastModified();
73 | curSlotSize = f.length();
74 | curSlot = i;
75 | }
76 | }
77 |
78 | fout = new FileOutputStream(new File(logFolderPath + "/" + name + "_" + curSlot + ".log"), true);
79 |
80 | // Write log file header for new files
81 | if (curSlotSize == 0 && header != null) {
82 | fout.write((header + "\r\n").getBytes());
83 | fout.flush();
84 | }
85 |
86 | pin = new PipedInputStream(10240);
87 | pout = new PipedOutputStream(pin);
88 | psout = new PrintStream(pout, true);
89 |
90 | Thread t = new Thread(this);
91 | t.setDaemon(true);
92 | t.start();
93 | }
94 |
95 | public void closeLogger() {
96 | synchronized (pin) {
97 | try {
98 | closed = true;
99 | pout.close();
100 | fout.close();
101 | pin.notifyAll();
102 | } catch (IOException e) {
103 | e.printStackTrace();
104 | }
105 | }
106 | }
107 |
108 | public void enableTimestamp(boolean enable) {
109 | timeStampEnabled = enable;
110 | }
111 |
112 | @Override
113 | public void logLine(String txt) {
114 | synchronized (psout) {
115 | synchronized (pin) {
116 | if (timeStampEnabled)
117 | psout.print(DateRetriever.getDateString() + " ");
118 | psout.println(txt);
119 | pin.notifyAll();
120 | }
121 | }
122 | }
123 |
124 | @Override
125 | public void logException(Exception e) {
126 | synchronized (psout) {
127 | synchronized (pin) {
128 | if (timeStampEnabled)
129 | psout.print(DateRetriever.getDateString() + " ");
130 | e.printStackTrace(psout);
131 | pin.notifyAll();
132 | }
133 | }
134 | }
135 |
136 | @Override
137 | public void log(String txt) {
138 | synchronized (psout) {
139 | synchronized (pin) {
140 | if (timeStampEnabled)
141 | psout.print(DateRetriever.getDateString() + " ");
142 | psout.print(txt);
143 | pin.notifyAll();
144 | }
145 | }
146 | }
147 |
148 | private OutputStream getOutputStream() throws IOException {
149 | if (curSlotSize < slotSize)
150 | return fout;
151 | else {
152 |
153 | fout.flush();
154 | fout.close();
155 | curSlot = (curSlot + 1) % slotCount;
156 | File f = new File(logFolderPath + "/" + name + "_" + curSlot + ".log");
157 | fout = new FileOutputStream(f);
158 | curSlotSize = 0;
159 |
160 | // Write log file header for new files
161 | if (header != null) {
162 | fout.write((header + "\r\n").getBytes());
163 | fout.flush();
164 | }
165 | return fout;
166 | }
167 | }
168 |
169 | @Override
170 | public void run() {
171 |
172 | byte[] buf = new byte[2048];
173 | int r = 0;
174 | int avail = 0;
175 |
176 | while (!closed) {
177 | try {
178 | synchronized (pin) {
179 |
180 | while (((avail = pin.available()) <= 0) && !closed) {
181 | try {
182 | pin.wait();
183 | } catch (InterruptedException e) {
184 | // TODO Auto-generated catch block
185 | e.printStackTrace();
186 | }
187 | }
188 | if (!closed)
189 | r = pin.read(buf);
190 | }
191 |
192 | if (!closed) {
193 | OutputStream out = getOutputStream();
194 | out.write(buf, 0, r);
195 | curSlotSize = curSlotSize + r;
196 |
197 | if (avail == r) // no more data in pin
198 | out.flush();
199 | }
200 | } catch (Exception e) {
201 | e.printStackTrace();
202 | }
203 |
204 | }
205 |
206 | }
207 |
208 | }
209 |
--------------------------------------------------------------------------------
/app/src/main/java/util/GroupedLogger.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | public class GroupedLogger implements LoggerInterface {
4 | LoggerInterface[] nestedLoggers;
5 |
6 |
7 | public GroupedLogger(LoggerInterface[] nestedLoggers) {
8 | this.nestedLoggers=nestedLoggers;
9 | }
10 |
11 | @Override
12 | public void logLine(String txt) {
13 | for (int i = 0; i MAX_ENTRIES);
43 | }
44 |
45 |
46 | @Override
47 | public synchronized Object put (Object key, Object value) {
48 | return super.put(key, value);
49 |
50 | }
51 |
52 | @Override
53 | public synchronized Object get (Object key) {
54 | return super.get(key);
55 |
56 | }
57 |
58 | @Override
59 | public synchronized Object remove (Object key) {
60 | return super.remove(key);
61 |
62 | }
63 |
64 | @Override
65 | public synchronized int size () {
66 | return super.size();
67 | }
68 |
69 | @Override
70 | public synchronized int hashCode () {
71 | return super.hashCode();
72 | }
73 |
74 | @Override
75 | public synchronized boolean equals (Object o) {
76 | return super.equals(o);
77 | }
78 |
79 | @Override
80 | public synchronized boolean isEmpty () {
81 | return super.isEmpty();
82 | }
83 |
84 | @Override
85 | public synchronized boolean containsKey (Object key) {
86 | return super.containsKey(key);
87 | }
88 |
89 | @Override
90 | public synchronized boolean containsValue (Object o) {
91 | return super.containsValue(o);
92 | }
93 |
94 |
95 | @Override
96 | public synchronized Collection values() {
97 | return super.values();
98 | }
99 |
100 | @Override
101 | public synchronized Set keySet() {
102 | return super.keySet();
103 | }
104 |
105 | @Override
106 | public synchronized Set entrySet() {
107 | return super.entrySet();
108 | }
109 |
110 | @Override
111 | public synchronized void putAll(Map m) {
112 | super.putAll(m);
113 | }
114 |
115 | @Override
116 | public synchronized void clear() {
117 | super.clear();
118 | }
119 |
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/app/src/main/java/util/Logger.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | import java.util.Hashtable;
26 |
27 | public class Logger implements LoggerInterface {
28 | private static Hashtable _loggers = new Hashtable();
29 | private static LoggerInterface m_logger;
30 | private static LoggerInterface m_default = new Logger();
31 |
32 | public static void setLogger(LoggerInterface logger) {
33 | m_logger = logger;
34 | }
35 |
36 | public static void setLogger(LoggerInterface logger, String id) {
37 | _loggers.put(id, logger);
38 | }
39 |
40 | public static void removeLogger(String id) {
41 | _loggers.remove(id);
42 | }
43 |
44 | public static LoggerInterface getLogger() {
45 | if (m_logger != null)
46 | return m_logger;
47 | else
48 | return m_default;
49 | }
50 |
51 | public static LoggerInterface getLogger(String id) {
52 | LoggerInterface l = (LoggerInterface) _loggers.get(id);
53 | if (l!= null)
54 | return l;
55 | return (LoggerInterface) getLogger();
56 | }
57 |
58 |
59 | @Override
60 | public void logLine(String txt) {
61 | System.out.println(txt);
62 |
63 | }
64 |
65 | @Override
66 | public void logException(Exception e) {
67 | e.printStackTrace();
68 |
69 | }
70 |
71 | @Override
72 | public void log(String txt) {
73 | System.out.print(txt);
74 |
75 | }
76 |
77 | @Override
78 | public void closeLogger() {
79 | // TODO Auto-generated method stub
80 |
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/util/LoggerInterface.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | public interface LoggerInterface {
26 | public void logLine(String txt);
27 |
28 | public void logException(Exception e);
29 |
30 | public void log(String txt);
31 |
32 | public void closeLogger();
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/util/ObjectPackagingManager.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | import java.io.IOException;
4 |
5 | public interface ObjectPackagingManager {
6 |
7 | public int objectSize();
8 |
9 | public Object bytesToObject(byte[] data, int offs);
10 |
11 | public void objectToBytes (Object object, byte[] data, int offs);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/util/PackedSortedList.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | PersonalHttpProxy 1.5
4 | Copyright (C) 2013-2015 Ingo Zenz
5 |
6 | This program is free software; you can redistribute it and/or
7 | modify it under the terms of the GNU General Public License
8 | as published by the Free Software Foundation; either version 2
9 | of the License, or (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program; if not, write to the Free Software
18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 |
20 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
21 | Contact:i.z@gmx.net
22 | */
23 |
24 | package util;
25 |
26 | import java.io.File;
27 | import java.io.FileInputStream;
28 | import java.io.FileNotFoundException;
29 | import java.io.FileOutputStream;
30 | import java.io.IOException;
31 | import java.io.RandomAccessFile;
32 | import java.util.Collection;
33 | import java.util.Collections;
34 | import java.util.Iterator;
35 | import java.util.List;
36 | import java.util.ListIterator;
37 | import java.util.RandomAccess;
38 |
39 | public class PackedSortedList implements List, RandomAccess {
40 |
41 | private boolean inMemory;
42 | private int object_size;
43 | private byte[] datapack = null;
44 | private int count = 0;
45 | private File persistedPackFile;
46 | private RandomAccessFile persistedPackData = null;
47 | private ObjectPackagingManager objMgr;
48 |
49 |
50 | public PackedSortedList(int size, ObjectPackagingManager objMgr) {
51 | this.objMgr = objMgr;
52 | this.object_size=objMgr.objectSize();
53 | datapack = new byte[size * object_size];
54 | inMemory = true;
55 | }
56 |
57 | private PackedSortedList(byte [] datapack, int count, boolean inMemory, File persistedPackFile, ObjectPackagingManager objMgr) {
58 | this.objMgr = objMgr;
59 | this.object_size=objMgr.objectSize();
60 | this.datapack=datapack;
61 | this.count = count;
62 | this.inMemory= inMemory;
63 | this.persistedPackFile=persistedPackFile;
64 | }
65 |
66 | private int binarySearch(Object key) {
67 | return Collections.binarySearch(this, key);
68 | }
69 |
70 | @Override
71 | public boolean add(Object key) {
72 |
73 | int pos = -(binarySearch(key) + 1);
74 | if (pos < 0) { // object already in list
75 | return false;
76 | } else {
77 | addInternal(pos, key);
78 | return true;
79 | }
80 | }
81 |
82 | private void addInternal(int pos, Object key) {
83 | if (pos != count) {
84 | System.arraycopy(datapack, pos * object_size, datapack, pos * object_size + object_size, ((count-pos)*object_size));
85 | }
86 | objMgr.objectToBytes(key, datapack, pos * object_size);
87 |
88 | count++;
89 | }
90 |
91 | @Override
92 | public void add(int arg0, Object arg1) {
93 | throw new UnsupportedOperationException();
94 |
95 | }
96 |
97 | @Override
98 | public boolean addAll(Collection collection) {
99 |
100 | Iterator it = collection.iterator();
101 |
102 | while (it.hasNext()) {
103 | add(it.next());
104 | }
105 | return true;
106 |
107 | }
108 |
109 | @Override
110 | public boolean addAll(int arg0, Collection arg1) {
111 | throw new UnsupportedOperationException();
112 | }
113 |
114 | @Override
115 | public void clear() {
116 | throw new UnsupportedOperationException();
117 |
118 | }
119 |
120 |
121 | private void releaseDataPack(boolean openedDataPack) {
122 | if (openedDataPack) {
123 | try {
124 | persistedPackData.close();
125 | } catch (IOException e) {
126 | //ignore
127 | }
128 | persistedPackData = null;
129 | }
130 |
131 | }
132 |
133 | private boolean aquireDataPack() throws FileNotFoundException {
134 | if (persistedPackData == null) {
135 | persistedPackData = new RandomAccessFile(persistedPackFile, "r");
136 | return true;
137 | }
138 | return false;
139 |
140 | }
141 |
142 | @Override
143 | public boolean contains(Object key) {
144 | int pos = -1;
145 | if (!inMemory) {
146 | synchronized(this) {
147 | boolean openedDataPack = false;
148 | try {
149 | openedDataPack = aquireDataPack();
150 | pos = binarySearch(key);
151 | } catch (Exception e) {
152 | throw new IllegalStateException (e);
153 | } finally {
154 | releaseDataPack(openedDataPack);
155 | }
156 | }
157 | } else pos = binarySearch(key);
158 | return (pos > -1);
159 | }
160 |
161 | @Override
162 | public boolean containsAll(Collection arg0) {
163 | throw new UnsupportedOperationException();
164 | }
165 |
166 | @Override
167 | public Object get(int pos) {
168 | if (pos >= count)
169 | return null;
170 |
171 | int offs = pos * object_size;
172 |
173 | if (inMemory)
174 | return objMgr.bytesToObject(datapack, offs);
175 | else {
176 | synchronized (this) {
177 | boolean openedDataPack = false;
178 | try {
179 | openedDataPack=aquireDataPack();
180 | persistedPackData.seek(offs);
181 | byte[] obj = new byte[object_size];
182 | persistedPackData.readFully(obj);
183 | return objMgr.bytesToObject(obj, 0);
184 | } catch (IOException e) {
185 | throw new IllegalStateException(e);
186 | } finally {
187 | releaseDataPack(openedDataPack);
188 | }
189 | }
190 | }
191 | }
192 |
193 | @Override
194 | public int indexOf(Object arg0) {
195 | throw new UnsupportedOperationException();
196 | }
197 |
198 | @Override
199 | public boolean isEmpty() {
200 | return (count ==0);
201 | }
202 |
203 | @Override
204 | public Iterator iterator() {
205 | throw new UnsupportedOperationException();
206 | }
207 |
208 | @Override
209 | public int lastIndexOf(Object arg0) {
210 | throw new UnsupportedOperationException();
211 | }
212 |
213 | @Override
214 | public ListIterator listIterator() {
215 | throw new UnsupportedOperationException();
216 | }
217 |
218 | @Override
219 | public ListIterator listIterator(int arg0) {
220 | throw new UnsupportedOperationException();
221 | }
222 |
223 | @Override
224 | public boolean remove(Object arg0) {
225 | throw new UnsupportedOperationException();
226 | }
227 |
228 | @Override
229 | public Object remove(int arg0) {
230 | throw new UnsupportedOperationException();
231 | }
232 |
233 | @Override
234 | public boolean removeAll(Collection arg0) {
235 | throw new UnsupportedOperationException();
236 | }
237 |
238 | @Override
239 | public boolean retainAll(Collection arg0) {
240 | throw new UnsupportedOperationException();
241 | }
242 |
243 | @Override
244 | public Object set(int arg0, Object arg1) {
245 | throw new UnsupportedOperationException();
246 | }
247 |
248 | @Override
249 | public int size() {
250 | return count;
251 | }
252 |
253 | @Override
254 | public List subList(int arg0, int arg1) {
255 | throw new UnsupportedOperationException();
256 | }
257 |
258 | @Override
259 | public Object[] toArray() {
260 | throw new UnsupportedOperationException();
261 | }
262 |
263 | @Override
264 | public Object[] toArray(Object[] arg0) {
265 | throw new UnsupportedOperationException();
266 | }
267 |
268 | public void persist(String path) throws IOException {
269 |
270 | if (!inMemory)
271 | throw new IOException("PackedSortedList can not be persisted when not in Memory!");
272 |
273 | FileOutputStream out = new FileOutputStream(path);
274 | out.write(datapack,0,count*object_size);
275 | out.flush();
276 | out.close();
277 | }
278 |
279 | public static PackedSortedList load(String path, boolean inMemory, ObjectPackagingManager objMgr) throws IOException {
280 | File f = new File(path);
281 | int size = (int) f.length();
282 | if (!f.exists() || !f.canRead())
283 | throw new IOException("Cannot read "+path);
284 |
285 | byte[] buf = null;
286 |
287 | if (inMemory) {
288 | FileInputStream in = new FileInputStream(f);
289 | buf = new byte[size];
290 |
291 | int r = 0;
292 | int offs = 0;
293 |
294 | while ((r = in.read(buf,offs,size-offs)) != -1 && offs != size)
295 | offs = offs+r;
296 |
297 |
298 | in.close();
299 | }
300 |
301 | return new PackedSortedList(buf, size / objMgr.objectSize(), inMemory, f, objMgr);
302 |
303 | }
304 |
305 | public void clearAndReleaseAllMemory() {
306 | count = 0;
307 | datapack = new byte[0];
308 | }
309 |
310 | }
311 |
--------------------------------------------------------------------------------
/app/src/main/java/util/TimeoutListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | public interface TimeoutListener {
26 |
27 | public void timeoutNotification();
28 | public long getTimoutTime();
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/util/TimeoutTime.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | public class TimeoutTime {
26 |
27 | private long timeout = Long.MAX_VALUE;
28 | private TimoutNotificator toHandler;
29 |
30 | public TimeoutTime(TimoutNotificator toHandler){
31 | this.toHandler=toHandler;
32 | }
33 |
34 | public synchronized void setTimeout(long millis) {
35 | if (millis <= 0)
36 | timeout = Long.MAX_VALUE;
37 | else timeout = toHandler.getCurrentTime()+millis;
38 | }
39 |
40 | public synchronized long getTimeout() {
41 | return timeout;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/util/TimoutNotificator.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | import java.util.HashSet;
26 | import java.util.Vector;
27 |
28 | public class TimoutNotificator implements Runnable {
29 |
30 |
31 | public static TimoutNotificator instance = new TimoutNotificator();
32 |
33 | public HashSet listeners = new HashSet();
34 | public boolean threadAvailable = false;
35 | private boolean stopped = false;
36 | private volatile long curTime = 0;
37 |
38 |
39 |
40 | public static TimoutNotificator getInstance() {
41 | return instance;
42 | }
43 |
44 | public static TimoutNotificator getNewInstance() {
45 | return new TimoutNotificator();
46 | }
47 |
48 | public synchronized void register(TimeoutListener listener) {
49 |
50 | listeners.add(listener);
51 |
52 | if (!threadAvailable) {
53 | curTime = System.currentTimeMillis();
54 | threadAvailable = true;
55 | Thread t = new Thread(this);
56 | t.setDaemon(true);
57 | t.start();
58 | }
59 | }
60 |
61 |
62 | @Override
63 | public void run() {
64 | Vector toListeners = new Vector();
65 | boolean exitThread = false;
66 | while (!exitThread) {
67 | synchronized (this) {
68 | toListeners.removeAllElements();
69 | curTime = System.currentTimeMillis();
70 | try {
71 | wait(1000);
72 | } catch (InterruptedException e) {
73 | // TODO Auto-generated catch block
74 | e.printStackTrace();
75 | }
76 | curTime = curTime+1000;
77 | if (!stopped) {
78 |
79 | TimeoutListener[] allListeners = (TimeoutListener[]) listeners.toArray(new TimeoutListener[0]);
80 | for (int i = 0; i < allListeners.length; i++) {
81 | long tOut = allListeners[i].getTimoutTime();
82 | if (curTime > tOut) {
83 | listeners.remove(allListeners[i]);
84 | toListeners.add(allListeners[i]);
85 | }
86 | }
87 | }
88 | exitThread = listeners.isEmpty() || stopped;
89 | if (exitThread)
90 | threadAvailable = false;
91 | }
92 | TimeoutListener[] allToListeners = (TimeoutListener[]) toListeners.toArray(new TimeoutListener[0]);
93 | for (int i = 0; i < allToListeners.length; i++) {
94 | allToListeners[i].timeoutNotification();
95 | }
96 | }
97 |
98 | }
99 |
100 | public synchronized void shutdown() {
101 | stopped = true;
102 | this.notifyAll();
103 | }
104 |
105 | public long getCurrentTime() {
106 | if (threadAvailable)
107 | return curTime;
108 | else
109 | return System.currentTimeMillis();
110 | }
111 |
112 | public synchronized void unregister(TimeoutListener l) {
113 | listeners.remove(l);
114 |
115 | }
116 |
117 |
118 |
119 | }
120 |
121 |
122 |
--------------------------------------------------------------------------------
/app/src/main/java/util/Utils.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util;
24 |
25 | import java.io.ByteArrayOutputStream;
26 | import java.io.File;
27 | import java.io.IOException;
28 | import java.io.InputStream;
29 | import java.io.ObjectOutputStream;
30 | import java.text.SimpleDateFormat;
31 | import java.util.Calendar;
32 | import java.util.Locale;
33 | import java.util.TimeZone;
34 |
35 | public class Utils {
36 |
37 | public static int byteArrayToInt(byte[] b)
38 | {
39 | return b[3] & 0xFF |
40 | (b[2] & 0xFF) << 8 |
41 | (b[1] & 0xFF) << 16 |
42 | (b[0] & 0xFF) << 24;
43 | }
44 |
45 | public static byte[] intToByteArray(int a)
46 | {
47 | return new byte[] {
48 | (byte) ((a >> 24) & 0xFF),
49 | (byte) ((a >> 16) & 0xFF),
50 | (byte) ((a >> 8) & 0xFF),
51 | (byte) (a & 0xFF)
52 | };
53 | }
54 |
55 | public static byte[] longToByteArray(long value) {
56 | return new byte[] {
57 | (byte) (value >> 56),
58 | (byte) (value >> 48),
59 | (byte) (value >> 40),
60 | (byte) (value >> 32),
61 | (byte) (value >> 24),
62 | (byte) (value >> 16),
63 | (byte) (value >> 8),
64 | (byte) value
65 | };
66 | }
67 |
68 | public static void writeLongToByteArray(long value, byte[] b, int offs) {
69 | b[offs + 0] = (byte)(value >> 56);
70 | b[offs + 1] = (byte)(value >> 48);
71 | b[offs + 2] = (byte)(value >> 40);
72 | b[offs + 3] = (byte)(value >> 32);
73 | b[offs + 4] = (byte)(value >> 24);
74 | b[offs + 5] = (byte)(value >> 16);
75 | b[offs + 6] = (byte)(value >> 8);
76 | b[offs + 7] = (byte)value;
77 | }
78 |
79 | public static long byteArrayToLong(byte[] b, int offs) {
80 | return (long) (b[7+offs] & 0xFF) |
81 | (long) (b[6+offs] & 0xFF) << 8 |
82 | (long) (b[5+offs] & 0xFF) << 16 |
83 | (long) (b[4+offs] & 0xFF) << 24 |
84 | (long) (b[3+offs] & 0xFF) << 32 |
85 | (long) (b[2+offs] & 0xFF) << 40 |
86 | (long) (b[1+offs] & 0xFF) << 48 |
87 | (long) (b[0+offs] & 0xFF) << 56;
88 | }
89 |
90 |
91 | public static long getLongStringHash (String str) {
92 | int a = 0;
93 | int b = 0;
94 | int len = str.length();
95 | byte[] bytes = str.getBytes();
96 | for (int i = 0; i 0 && last == 13)
122 | i = i-1;
123 |
124 | return str.substring(0, i);
125 | }
126 |
127 |
128 | public static String readLineFromStreamRN(InputStream in) throws IOException {
129 | return readLineFromStream(in,true);
130 | }
131 |
132 | public static String readLineFromStream(InputStream in) throws IOException {
133 | return readLineFromStream(in,false);
134 | }
135 |
136 |
137 | public static byte[] readFully(InputStream in, int bufSize) throws IOException {
138 | ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
139 | int r = 0;
140 | byte[] buf = new byte[bufSize];
141 | while ((r = in.read(buf, 0, bufSize)) != -1)
142 | bytesOut.write(buf, 0, r);
143 | return bytesOut.toByteArray();
144 |
145 | }
146 |
147 | public static byte[] serializeObject(Object obj) throws IOException {
148 | ByteArrayOutputStream objOut = new ByteArrayOutputStream();
149 | ObjectOutputStream dataOut = new ObjectOutputStream(objOut);
150 | dataOut.writeObject(obj);
151 | dataOut.flush();
152 | dataOut.close();
153 | return objOut.toByteArray();
154 | }
155 |
156 | public static String getServerTime() {
157 | Calendar calendar = Calendar.getInstance();
158 | SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
159 | dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
160 | return dateFormat.format(calendar.getTime());
161 | }
162 |
163 |
164 | public static String[] parseURI(String uri) throws IOException {
165 | try {
166 | String url = uri;
167 | url = url.substring(7);
168 | int idx = url.indexOf('/');
169 | if (idx == -1)
170 | idx = url.length();
171 | String hostEntry = url.substring(0, idx);
172 | if (idx == url.length())
173 | url = "/";
174 | else
175 | url = url.substring(idx);
176 |
177 | return new String[] {hostEntry,url};
178 | } catch (Exception e) {
179 | throw new IOException ("Cannot parse URI '"+uri+"'! - "+e.toString());
180 | }
181 | }
182 |
183 | public static void deleteFolder(String path) {
184 | File dir = new File(path);
185 | if (dir.exists() && dir.isDirectory()) {
186 |
187 | File[] files = dir.listFiles();
188 | for (int i = 0; i < files.length; i++) {
189 | if (files[i].isDirectory())
190 | deleteFolder(files[i].getAbsolutePath());
191 | else
192 | files[i].delete();
193 | }
194 | dir.delete();
195 | }
196 | }
197 |
198 | }
199 |
--------------------------------------------------------------------------------
/app/src/main/java/util/conpool/Connection.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util.conpool;
24 |
25 |
26 | import java.io.BufferedReader;
27 | import java.io.File;
28 | import java.io.FileInputStream;
29 | import java.io.IOException;
30 | import java.io.InputStream;
31 | import java.io.InputStreamReader;
32 | import java.io.OutputStream;
33 | import java.net.InetAddress;
34 | import java.net.InetSocketAddress;
35 | import java.net.Socket;
36 | import java.net.SocketException;
37 | import java.net.SocketTimeoutException;
38 | import java.util.HashMap;
39 | import java.util.HashSet;
40 | import java.util.Hashtable;
41 | import java.util.StringTokenizer;
42 | import java.util.Vector;
43 |
44 | import util.ExecutionEnvironment;
45 | import util.TimeoutListener;
46 | import util.TimeoutTime;
47 | import util.TimoutNotificator;
48 |
49 |
50 | public class Connection implements TimeoutListener {
51 |
52 | private Socket socket = null;
53 | private InputStream socketIn;
54 | private OutputStream socketOut;
55 | private PooledConnectionInputStream in;
56 | private PooledConnectionOutputStream out;
57 | String poolKey;
58 | TimeoutTime timeout;
59 | boolean aquired = true;
60 | boolean valid = true;
61 |
62 | private static HashMap connPooled = new HashMap();
63 | private static HashSet connAquired = new HashSet();
64 | private static Hashtable CUSTOM_HOSTS = getCustomHosts();
65 | private static int POOLTIMEOUT_SECONDS = 300;
66 | private static TimoutNotificator toNotify = TimoutNotificator.getNewInstance();
67 |
68 | private Connection(String host, int port, int conTimeout) throws IOException {
69 | InetAddress adr=null;
70 | if (CUSTOM_HOSTS != null)
71 | adr = (InetAddress) CUSTOM_HOSTS.get(host);
72 | if (adr == null)
73 | adr = InetAddress.getByName(host);
74 | InetSocketAddress sadr = new InetSocketAddress(adr,port);
75 | poolKey = host + ":" + port;
76 | initConnection(sadr,conTimeout);
77 | timeout = new TimeoutTime(toNotify);
78 |
79 | }
80 |
81 |
82 | private static Hashtable getCustomHosts() {
83 | File hostsFile = new File(ExecutionEnvironment.getEnvironment().getWorkDir()+"hosts");
84 | String entry = null;
85 | Hashtable custom_hosts = null;
86 | try {
87 | if (hostsFile.exists()) {
88 | custom_hosts = new Hashtable();
89 | BufferedReader fin = new BufferedReader(new InputStreamReader(new FileInputStream(hostsFile)));
90 | while ((entry = fin.readLine()) != null) {
91 | String[] hostEntry = parseHosts(entry);
92 | if (hostEntry != null)
93 | custom_hosts.put(hostEntry[1], InetAddress.getByName(hostEntry[0]));
94 | }
95 | }
96 | } catch (IOException ioe){
97 | ioe.printStackTrace();
98 | }
99 | return custom_hosts;
100 | }
101 |
102 | private static String[] parseHosts(String line) {
103 | if (line.startsWith("#")|| line.trim().equals(""))
104 | return null;
105 | StringTokenizer tokens = new StringTokenizer(line);
106 | if (tokens.countTokens() >=2) {
107 | String ip = tokens.nextToken().trim();
108 | String host = tokens.nextToken().trim();
109 | return new String[]{ip,host};
110 | } else { //list with plain hosts
111 | String ip = "127.0.0.1";
112 | String host = tokens.nextToken().trim();
113 | return new String[]{ip,host};
114 | }
115 |
116 | }
117 |
118 |
119 | private Connection(InetSocketAddress sadr, int conTimeout) throws IOException {
120 | poolKey = sadr.getAddress().getHostAddress() + ":" + sadr.getPort();
121 | initConnection(sadr,conTimeout);
122 | timeout = new TimeoutTime(toNotify);
123 | }
124 |
125 | private void initConnection(InetSocketAddress sadr, int conTimeout) throws IOException {
126 | socket = new Socket();
127 |
128 | if (conTimeout > 0)
129 | socket.connect(sadr,conTimeout);
130 | else
131 | socket.connect(sadr);
132 |
133 | socketIn = socket.getInputStream();
134 | socketOut = socket.getOutputStream();
135 | }
136 |
137 |
138 | public static Connection connect(InetSocketAddress sadr, int conTimeout) throws IOException {
139 |
140 | Connection con = poolRemove(sadr.getAddress().getHostAddress(), sadr.getPort());
141 | if (con == null) {
142 | con = new Connection(sadr,conTimeout);
143 | }
144 | con.initStreams();
145 | connAquired.add(con);
146 | return con;
147 | }
148 |
149 | public static Connection connect(InetSocketAddress address) throws IOException {
150 | return connect(address,-1);
151 | }
152 |
153 | public static Connection connect(String host, int port, int conTimeout) throws IOException {
154 |
155 | Connection con = poolRemove(host, port);
156 | if (con == null) {
157 | con = new Connection(host, port, conTimeout);
158 | }
159 | con.initStreams();
160 | connAquired.add(con);
161 | return con;
162 | }
163 |
164 | public static Connection connect(String host, int port) throws IOException {
165 | return connect(host,port,-1);
166 | }
167 |
168 | public static void setPoolTimeoutSeconds(int secs) {
169 | POOLTIMEOUT_SECONDS=secs;
170 | }
171 |
172 | private void initStreams() {
173 | in = new PooledConnectionInputStream(socketIn);
174 | out = new PooledConnectionOutputStream(socketOut);
175 | }
176 |
177 | public static void invalidate() {
178 | synchronized (connPooled) {
179 | Vector[] destinations = (Vector[]) connPooled.values().toArray(new Vector[0]);
180 | for (int i = 0; i < destinations.length; i++) {
181 | Connection[] cons = (Connection[]) destinations[i].toArray(new Connection[0]);
182 | for (int ii = 0; ii < cons.length; ii++)
183 | cons[ii].release(false);
184 | }
185 |
186 | Connection[] cons = (Connection[]) connAquired.toArray(new Connection[0]);
187 | for (int i = 0; i < cons.length; i++)
188 | cons[i].release(false);
189 | }
190 | }
191 |
192 | public static void poolReuse(Connection con) {
193 | synchronized (connPooled) {
194 | if (!con.aquired)
195 | throw new IllegalStateException("Inconsistwent Connection State - Cannot release non aquired connection");
196 | con.aquired=false;
197 | Vector hostCons = (Vector) connPooled.get(con.poolKey);
198 | if (hostCons == null) {
199 | hostCons = new Vector();
200 | connPooled.put(con.poolKey, hostCons);
201 | }
202 | toNotify.register(con);
203 | con.timeout.setTimeout(POOLTIMEOUT_SECONDS*1000);
204 |
205 | hostCons.add(con);
206 | }
207 |
208 | }
209 |
210 | public static Connection poolRemove(String host, int port) {
211 | String key = host + ":" + port;
212 | synchronized (connPooled) {
213 | Vector hostCons = (Vector) connPooled.get(key);
214 | if (hostCons == null) {
215 | return null;
216 | }
217 | boolean found = false;
218 | Connection con = null;
219 | while (!found && !hostCons.isEmpty()) {
220 | con = (Connection) hostCons.remove(hostCons.size() - 1);
221 | if (con.aquired)
222 | throw new IllegalStateException("Inconsistent Connection State - Cannot take already aquired connection from pool!");
223 | con.aquired=true;
224 | toNotify.unregister(con);
225 | found = con.isAlive();
226 | if (!found) {
227 | con.release(false);
228 | con = null;
229 | }
230 | }
231 | if (hostCons.isEmpty())
232 | connPooled.remove(key);
233 |
234 | return con;
235 |
236 | }
237 | }
238 |
239 |
240 | private boolean isAlive() {
241 | // Must only be called when sure that there is no data to read - otherwise Illegal State!
242 |
243 | try {
244 | socket.setSoTimeout(1);
245 | int r = socketIn.read();
246 | if (r!=-1) {
247 | int avail = socketIn.available();
248 | byte buf[] = new byte [Math.max(avail, 10240)];
249 | socketIn.read(buf);
250 | String data = ((char)r)+new String(buf);
251 | }
252 | return false;
253 | } catch (SocketTimeoutException to) {
254 | try {
255 | socket.setSoTimeout(0);
256 | return true;
257 | } catch (SocketException e) {
258 | return false;
259 | }
260 | } catch (Exception e) {
261 | return false;
262 | }
263 | }
264 |
265 |
266 |
267 | public OutputStream getOutputStream() {
268 | return out;
269 | }
270 |
271 | public InputStream getInputStream() {
272 | return in;
273 | }
274 |
275 | public void release(boolean reuse) {
276 |
277 | if (!valid) //a killed connection already released
278 | return;
279 |
280 | connAquired.remove(this);
281 |
282 | if (reuse) {
283 | in.invalidate();
284 | out.invalidate();
285 | try {
286 | socket.setSoTimeout(0);
287 | } catch (SocketException e) {
288 | release(false);
289 | return;
290 | }
291 | poolReuse(this);
292 | } else {
293 | try {
294 | valid = false;
295 | socket.shutdownOutput();
296 | socket.shutdownInput();
297 | socket.close();
298 | } catch (IOException e) {
299 | // TODO Auto-generated catch block
300 | }
301 | }
302 | }
303 |
304 | public void setSoTimeout(int millis) throws SocketException {
305 | socket.setSoTimeout(millis);
306 | }
307 |
308 |
309 | @Override
310 | public void timeoutNotification() {
311 |
312 | boolean found = false;
313 |
314 | synchronized (connPooled) {
315 |
316 | Vector hostCons = (Vector) connPooled.get(poolKey);
317 | if (hostCons == null) {
318 | return;
319 | }
320 | found = hostCons.remove(this);
321 | if (hostCons.isEmpty())
322 | connPooled.remove(poolKey);
323 | }
324 | if (found) //if false, than connection was just taken by another thread
325 | release(false);
326 | }
327 |
328 | @Override
329 | public long getTimoutTime() {
330 | // TODO Auto-generated method stub
331 | return timeout.getTimeout();
332 | }
333 |
334 |
335 |
336 | // return count of received and sent bytes
337 | public long[] getTraffic() {
338 | if (!aquired)
339 | throw new IllegalStateException("Inconsistent Connection State - Connection is not aquired!");
340 | return new long[] {in.getTraffic(),out.getTraffic()};
341 | }
342 |
343 |
344 | // return destination (host:port)
345 | public String getDestination() {
346 | return poolKey;
347 | }
348 |
349 | }
350 |
--------------------------------------------------------------------------------
/app/src/main/java/util/conpool/PooledConnectionInputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2014 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util.conpool;
24 |
25 | import java.io.IOException;
26 | import java.io.InputStream;
27 |
28 | public class PooledConnectionInputStream extends InputStream {
29 |
30 | private InputStream in = null;
31 | private boolean valid = true;
32 | private long traffic = 0;
33 |
34 | public PooledConnectionInputStream (InputStream in) {
35 | this.in = in;
36 | }
37 |
38 | public void invalidate() {
39 | valid = false;
40 | }
41 |
42 | @Override
43 | public int read() throws IOException {
44 | int r = in.read();
45 | if (!valid)
46 | throw new IllegalStateException("Invalid:"+this);
47 |
48 | if (r != -1)
49 | traffic++;
50 |
51 | return r;
52 | }
53 |
54 | @Override
55 | public int read(byte[] b) throws IOException {
56 | return read(b,0,b.length);
57 | }
58 |
59 | @Override
60 | public int read(byte[] b, int offs, int len) throws IOException {
61 | int r = in.read(b,offs,len);
62 | if (!valid)
63 | throw new IllegalStateException("Invalid:"+this);
64 |
65 | traffic = traffic+r;
66 | return r;
67 | }
68 |
69 | @Override
70 | public void close () throws IOException {
71 | //do nothing
72 | }
73 |
74 | public long getTraffic() {
75 | return traffic;
76 | }
77 |
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/util/conpool/PooledConnectionOutputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2014 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util.conpool;
24 |
25 | import java.io.IOException;
26 | import java.io.OutputStream;
27 |
28 | public class PooledConnectionOutputStream extends OutputStream {
29 | private OutputStream out;
30 | private boolean valid = true;
31 | private long traffic = 0;
32 |
33 | public PooledConnectionOutputStream(OutputStream out){
34 | this.out= out;
35 | }
36 |
37 | public void invalidate() {
38 | valid = false;
39 | }
40 |
41 | @Override
42 | public void write(int b) throws IOException {
43 | out.write(b);
44 | traffic++;
45 | if (!valid)
46 | throw new IllegalStateException("Invalid:"+this);
47 | }
48 |
49 | @Override
50 | public void write(byte[] b) throws IOException {
51 | out.write(b);
52 | traffic = traffic+b.length;
53 | if (!valid)
54 | throw new IllegalStateException("Invalid:"+this);
55 |
56 | }
57 |
58 | @Override
59 | public void write(byte[] b, int offs, int len) throws IOException {
60 | out.write(b, offs,len);
61 | traffic = traffic+len;
62 | if (!valid)
63 | throw new IllegalStateException("Invalid:"+this);
64 | }
65 |
66 | @Override
67 | public void close () throws IOException {
68 | //do nothing
69 | }
70 |
71 | @Override
72 | public void flush() throws IOException {
73 | out.flush();
74 | if (!valid)
75 | throw new IllegalStateException("Invalid:"+this);
76 | }
77 |
78 | public long getTraffic() {
79 | return traffic;
80 | }
81 |
82 |
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/util/http/HttpHeader.java:
--------------------------------------------------------------------------------
1 | /*
2 | PersonalHttpProxy 1.5
3 | Copyright (C) 2013-2015 Ingo Zenz
4 |
5 | This program is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU General Public License
7 | as published by the Free Software Foundation; either version 2
8 | of the License, or (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | Find the latest version at http://www.zenz-solutions.de/personalhttpproxy
20 | Contact:i.z@gmx.net
21 | */
22 |
23 | package util.http;
24 |
25 | import java.io.ByteArrayInputStream;
26 | import java.io.IOException;
27 | import java.io.InputStream;
28 | import java.util.HashMap;
29 | import java.util.Iterator;
30 | import java.util.Vector;
31 |
32 | import util.Utils;
33 |
34 | public class HttpHeader {
35 |
36 | private static final String[] reqparamSequence = { "Cache-Control", "Connection", "Date", "Pragma", "Trailer", "Transfer-Encoding", "Upgrade", "Via", "Warning", "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", "Authorization",
37 | "Expect", "From", "Host", "If-Match", "If-Modified-Since", "If-None-Match", "If-Range", "If-Unmodified-Since", "Max-Forwards", "Proxy-Authorization", "Range", "Referer", "TE", "User-Agent", "Allow", "Content-Encoding",
38 | "Content-Language", "Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Type", "Expires", "Last-Modified", "extension-header" };
39 |
40 | public static final int REQUEST_HEADER = 1;
41 | public static final int RESPONSE_HEADER = 2;
42 |
43 | // Http Request Params
44 | public String remote_host_name = "";
45 | public String hostEntry;
46 | public String url;
47 | public String method;
48 | public int remote_port = 0;
49 |
50 | public boolean tunnelMode = false;
51 | public int responsecode = -1;
52 |
53 | // parsed HTTP Header
54 | private String _first;
55 | private Vector _keys = null;
56 | private HashMap _mapping = null;
57 |
58 | private int type;
59 |
60 | public HttpHeader(InputStream in, int type) throws IOException {
61 |
62 | _keys = new Vector();
63 | _mapping = new HashMap();
64 |
65 | if (type != REQUEST_HEADER && type != RESPONSE_HEADER)
66 | throw new IOException("INVALID TYPE!");
67 |
68 | this.type = type;
69 |
70 | _first = Utils.readLineFromStream(in,true);
71 | if (type == REQUEST_HEADER) {
72 | parseURI();
73 | if (hostEntry != null)
74 | setValue("Host", hostEntry);
75 | } else {
76 | if (!(_first.length() >= 12))
77 | throw new IOException("Invalid Response Header:" + _first);
78 |
79 | String _first12 = _first.substring(0, 12).toLowerCase();
80 | if (_first12.startsWith("http/")) {
81 | try {
82 | responsecode = Integer.parseInt(_first.substring(9, 12));
83 | _first = "HTTP/1.1 " + responsecode + _first.substring(12);
84 | } catch (Exception e) {
85 | throw new IOException(e.getMessage());
86 | }
87 | } else
88 | throw new IOException("Invalid Response Header:" + _first);
89 | }
90 |
91 | String next = Utils.readLineFromStream(in,true);
92 | String key;
93 | String value;
94 | while (!next.equals("")) {
95 | int index = next.indexOf(": ");
96 | if (index == -1) {
97 | index = next.indexOf(":"); // fallback ": without blank
98 | if (index == -1)
99 | throw new IOException("Invalid header:" + next);
100 | else {
101 | key = next.substring(0, index).trim();
102 | value = next.substring(index + 1).trim();
103 | }
104 | } else {
105 | key = next.substring(0, index).trim();
106 | value = next.substring(index + 2).trim();
107 | }
108 |
109 | String keyUpper = key.toUpperCase();
110 |
111 | String curVal = (String) _mapping.get(keyUpper);
112 | if (curVal == null) {
113 | _keys.add(key);
114 | _mapping.put(keyUpper, value);
115 | } else {
116 | if (!keyUpper.equals("CONTENT-LENGTH")) {
117 | if (!keyUpper.equals("HOST"))
118 | _mapping.put(keyUpper, curVal + "_,_" + value); // multiple values per key separated by "_,_" as "," only doesn't work for Set-Cookie expires setting
119 | } else if (!curVal.equals(value))
120 | throw new IOException("Invalid Header! Duplicated Content-Length with different values:" + curVal + "<>" + value + "!");
121 | }
122 | next = Utils.readLineFromStream(in,true);
123 | }
124 | if (hostEntry == null && type == REQUEST_HEADER) {
125 | hostEntry = getValue("Host");
126 | if (hostEntry != null) {
127 | parseHostEntry();
128 | } else
129 | throw new IOException("Bad Request - No Host specified!");
130 | }
131 | }
132 |
133 | public HttpHeader(int type) {
134 | _keys = new Vector();
135 | _mapping = new HashMap();
136 | this.type = type;
137 | }
138 |
139 | public HttpHeader(String headerStr, int type) throws IOException {
140 | this(new ByteArrayInputStream(headerStr.getBytes()), type);
141 | }
142 |
143 | private HttpHeader() {
144 | // TODO Auto-generated constructor stub
145 | }
146 |
147 | public HttpHeader clone() {
148 |
149 | HttpHeader clone = new HttpHeader();
150 |
151 | clone.remote_host_name = remote_host_name;
152 | clone.hostEntry = hostEntry;
153 | clone.url = url;
154 | clone.method = method;
155 | clone.remote_port = remote_port;
156 |
157 | clone.tunnelMode = tunnelMode;
158 | clone.responsecode = responsecode;
159 |
160 | clone._first = _first;
161 | clone._keys = (Vector) _keys.clone();
162 | clone._mapping = (HashMap) _mapping.clone();
163 | clone.type = type;
164 |
165 | return clone;
166 |
167 | }
168 |
169 | public void setRequest(String request) throws IOException {
170 | _first = request;
171 | parseURI();
172 | setValue("Host", hostEntry);
173 | }
174 |
175 | public String getResponseMessage() {
176 | if (type != RESPONSE_HEADER)
177 | throw new IllegalStateException(this + " is not a ResonseHeader!");
178 | return _first;
179 | }
180 |
181 | public int getResponseCode() {
182 | if (type != RESPONSE_HEADER)
183 | throw new IllegalStateException(this + " is not a ResonseHeader!");
184 | return responsecode;
185 | }
186 |
187 | public String getValue(String key) {
188 | return (String) _mapping.get(key.toUpperCase());
189 | }
190 |
191 | public void appendValueToHeaderString(StringBuffer headerString, String key, String value) {
192 | String[] tokens = value.split("_,_"); // multiple values per key!
193 | for (int i = 0; i < tokens.length; i++)
194 | headerString.append(key + ": " + tokens[i] + "\r\n");
195 | }
196 |
197 | public String getHeaderString() {
198 |
199 | StringBuffer headerString = new StringBuffer(_first + "\r\n");
200 | Iterator keyIt = _keys.iterator();
201 | while (keyIt.hasNext()) {
202 | String key = (String) keyIt.next();
203 | String value = (String) _mapping.get(key.toUpperCase());
204 | appendValueToHeaderString(headerString, key, value);
205 | }
206 | headerString.append("\r\n");
207 | return headerString.toString();
208 | }
209 |
210 | public String getServerRequestHeader(boolean useProxy) {
211 |
212 | String firstLn = _first;
213 |
214 | if (!tunnelMode) {
215 | if (useProxy)
216 | firstLn = method + " http://" + hostEntry + url + " HTTP/1.1";
217 | else
218 | firstLn = method + " " + url + " HTTP/1.1";
219 | }
220 | StringBuffer headerString = new StringBuffer(firstLn + "\r\n");
221 | HashMap mapping = (HashMap) _mapping.clone();
222 |
223 | for (int i = 0; i < reqparamSequence.length; i++) {
224 | String key = reqparamSequence[i];
225 | String value = (String) mapping.remove(key.toUpperCase());
226 | if (value != null) {
227 | if (useProxy && key.toUpperCase().equals("CONNECTION"))
228 | key = "Proxy-Connection";
229 | if (value.length() > 0) {
230 | appendValueToHeaderString(headerString, key, value);
231 | } else
232 | headerString.append(key + ":\r\n");
233 | }
234 | }
235 | Iterator keyIt = _keys.iterator();
236 | while (keyIt.hasNext()) {
237 | String key = (String) keyIt.next();
238 | String value = (String) mapping.remove(key.toUpperCase());
239 | if (value != null) {
240 | if (!useProxy && key.toUpperCase().equals("PROXY-CONNECTION"))
241 | key = "Connection";
242 | if (value.length() > 0) {
243 | appendValueToHeaderString(headerString, key, value);
244 | ;
245 | } else
246 | headerString.append(key + ":\r\n");
247 | }
248 | }
249 | headerString.append("\r\n");
250 | return headerString.toString();
251 | }
252 |
253 | public String getServerRequestHeader() {
254 | return getServerRequestHeader(false);
255 | }
256 |
257 | public long getContentLength() {
258 |
259 | if (responsecode == 304 || responsecode == 204)
260 | return 0;
261 |
262 | String val = getValue("Content-Length");
263 | if (val != null) {
264 | return Long.parseLong(val);
265 | }
266 |
267 | else
268 | return -1;
269 | }
270 |
271 | public boolean getConnectionClose() {
272 | String value = getValue("Connection");
273 | if (value == null)
274 | return false;
275 | else if (value.equalsIgnoreCase("close"))
276 | return true;
277 | else
278 | return false;
279 |
280 | }
281 |
282 | public boolean chunkedTransfer() {
283 | Object val = getValue("Transfer-Encoding");
284 | if (val != null)
285 | return ((String) val).equalsIgnoreCase("chunked");
286 | else
287 | return false;
288 | }
289 |
290 | public void setValue(String key, String value) {
291 | if (getValue(key) == null) {
292 | _keys.add(key);
293 | }
294 | _mapping.put(key.toUpperCase(), value);
295 | }
296 |
297 | public void setHostEntry(String hostEntry) throws IOException {
298 | this.hostEntry= hostEntry;
299 | setValue("Host",hostEntry);
300 | parseHostEntry();
301 | }
302 |
303 | private void parseURI() throws IOException {
304 |
305 | // format: / HTTP
306 | int idx = _first.indexOf(' ');
307 | int idx2 = _first.lastIndexOf(' ');
308 | if (idx == -1 || idx == idx2)
309 | throw new IOException("Bad Request:" + _first);
310 |
311 | method = _first.substring(0, idx);
312 | url = _first.substring(idx + 1, idx2);
313 | tunnelMode = (method.equalsIgnoreCase("CONNECT"));
314 | if (!tunnelMode) {
315 | if (url.length() >= 7 && url.substring(0, 7).equalsIgnoreCase("http://")) {
316 |
317 | url = url.substring(7);
318 | idx = url.indexOf('/');
319 | if (idx == -1)
320 | idx = url.length();
321 | hostEntry = url.substring(0, idx);
322 | if (idx == url.length())
323 | url = "/";
324 | else
325 | url = url.substring(idx);
326 | }
327 | } else
328 | hostEntry = url;
329 |
330 | if (hostEntry != null)
331 | parseHostEntry();
332 | }
333 |
334 | private void parseHostEntry() throws IOException {
335 | remote_port = 80;
336 | remote_host_name = hostEntry;
337 |
338 | int idx = hostEntry.lastIndexOf(":"); // check for the port number
339 | // take IPV6 into account!!! http://[2a00:1450:400a:804::1010]:80 HTTP/1.1
340 |
341 | if (idx != -1 && !hostEntry.endsWith("]")) {
342 | try {
343 | remote_port = Integer.parseInt(hostEntry.substring(idx + 1));
344 | } catch (NumberFormatException nfe) {
345 | throw new IOException("Bad Request - Cannot parse port to int:" + _first);
346 | }
347 | remote_host_name = hostEntry.substring(0, idx);
348 | }
349 |
350 | // IPV6 e.g. [2a00:1450:400a:804::1010]
351 | if (remote_host_name.startsWith("[") && remote_host_name.endsWith("]")) {
352 | remote_host_name = remote_host_name.substring(1, remote_host_name.length() - 1);
353 | }
354 |
355 | }
356 | }
357 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngoZenz/personalhttpproxy/cbce29ae23cdfa07fe6fc917aad8f8590ee7ca2b/app/src/main/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngoZenz/personalhttpproxy/cbce29ae23cdfa07fe6fc917aad8f8590ee7ca2b/app/src/main/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngoZenz/personalhttpproxy/cbce29ae23cdfa07fe6fc917aad8f8590ee7ca2b/app/src/main/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngoZenz/personalhttpproxy/cbce29ae23cdfa07fe6fc917aad8f8590ee7ca2b/app/src/main/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngoZenz/personalhttpproxy/cbce29ae23cdfa07fe6fc917aad8f8590ee7ca2b/app/src/main/res/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngoZenz/personalhttpproxy/cbce29ae23cdfa07fe6fc917aad8f8590ee7ca2b/app/src/main/res/drawable-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | -
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_focused.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | -
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/checkbox_active.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | -
23 |
24 |
25 |
26 |
27 |
28 |
34 |
38 |
39 |
40 |
41 |
42 |
43 | -
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/checkbox_inactive.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | -
23 |
24 |
25 |
26 |
27 |
28 |
34 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/custom_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/custom_checkbox.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v17/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
16 |
20 |
21 |
22 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
35 |
36 |
40 |
43 |
44 |
45 |
50 |
51 |
56 |
61 |
62 |
63 |
65 |
71 |
77 |
83 |
84 |
85 |
89 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v23/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
16 |
20 |
21 |
22 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
35 |
39 |
42 |
43 |
44 |
49 |
50 |
55 |
60 |
61 |
62 |
64 |
70 |
76 |
82 |
83 |
84 |
88 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v4/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
16 |
20 |
21 |
22 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
35 |
39 |
42 |
43 |
44 |
49 |
50 |
55 |
60 |
61 |
62 |
64 |
70 |
76 |
82 |
83 |
84 |
88 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/app/src/main/res/values-af/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP gevolmagtigde poort:
6 | Herbegin
7 | Verlaat
8 | Herlaai filter
9 | Gevorderde instellings
10 | Toestel slaap voorkom
11 | Outoloop
12 | Ontsper ad aan om te blokkeer
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ar/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | منفذ الوكيل HTTP
6 | بدء إعادة
7 | الخروج
8 | تحديث عامل تصفية
9 | الإعدادات المتقدمة
10 | منع نوم الجهاز
11 | التشغيل التلقائي
12 | تمكين حظر الإعلانات
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ca/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | Port d\'apoderat de HTTP:
6 | Reiniciar
7 | Surt
8 | Filtre de recàrrega
9 | Configuració avançada
10 | Impedir Repòs del Dispositiu
11 | Autoinici
12 | Permetre blocatge d\'anunci
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-cs/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP port proxy:
6 | Restartovat
7 | Ukončit
8 | Obnovit filtr
9 | Pokročilá nastavení
10 | Zabránit uspání zařízení
11 | Automatické spuštění
12 | Povolit blokování reklam
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-da/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP proxyport:
6 | Genstart
7 | Slut
8 | Genindlæs filter
9 | Avancerede indstillinger
10 | Stop enheden i at gå i dvale
11 | Automatisk start
12 | Aktiver annonceblokering
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP Proxy Port:
6 | Neustarten
7 | Beenden
8 | Filter neu laden
9 | Erweiterte Einstellungen
10 | Schlafmodus des Geräts verhindern
11 | Autostart
12 | Werbeblocker aktivieren
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-el/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | Θύρα διακομιστή μεσολάβησης HTTP:
6 | Επανεκκίνηση
7 | Έξοδος
8 | Επαναφόρτωση φίλτρο
9 | Σύνθετες ρυθμίσεις
10 | Αποφυγή του ύπνου συσκευή
11 | Αυτόματη εκκίνηση
12 | Ενεργοποιήσετε το κλείδωμα
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-es-rES/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Proxy
5 | Puerto de proxy HTTP:
6 | Reiniciar
7 | Salir
8 | Volver a cargar el filtro
9 | Ajustes avanzados
10 | Prevenir la suspensión
11 | Auto-Inicio
12 | Activar bloqueo
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-fi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP-välityspalvelimen portti:
6 | Käynnistä uudelleen
7 | Poistu
8 | Lataa suodatin uudelleen
9 | Lisäasetukset
10 | Estä laitteen lepotila
11 | Autom. käynnistys
12 | Ota mainostenesto käyttöön
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | Port du proxy HTTP :
6 | Redémarrage
7 | Quitter
8 | Recharger le filtre
9 | Paramètres avancés
10 | Empêcher le sommeil
11 | Exécution automatique
12 | Activer le blocage
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-he/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | יציאת ה-proxy של HTTP:
6 | הפעל מחדש
7 | צא
8 | מסנן טען מחדש
9 | הגדרות מתקדמות
10 | למנוע שינה התקן
11 | אתחול אוטומטי
12 | לאפשר חסימת מודעות
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-hi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTP प्रोक्सि
5 | HTTP प्रोक्सि पोर्ट:
6 | पुनरारंभ करें
7 | बाहर निकलें
8 | फ़िल्टर पुनः शुरु करें
9 | एडव्हान्स सेटिंग्ज
10 | डिवाइस स्लीप ना होने दे
11 | बन्द होने पर स्वत: आरंभ करे
12 | विज्ञापन-ब्लॉकिंग चलू करें
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-hr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP proxy port:
6 | Ponovo pokreni
7 | Zatvori
8 | Ponovo učitaj filter
9 | Napredne postavke
10 | Spriječi da uređaj prijeđe u stanje mirovanja
11 | Automatsko pokretanje
12 | Omogući blokiranje oglasa
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-hu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP proxy-port:
6 | Újraindítás
7 | Kilépés
8 | Szűrő visszatöltése
9 | Haladó beállítások
10 | Az eszköz alvó állapotának megakadályozása
11 | Automatikus indítás
12 | Hirdetés blokkolás bekapcsolása
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | Porta Proxy HTTP:
6 | Riavvia
7 | Esci
8 | Ricarica filtro
9 | Impostazioni Avanzate
10 | Previeni stand-by
11 | Avvio automatico
12 | Abilita Blocco pubblicità
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-iw/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | יציאת ה-proxy של HTTP:
6 | הפעל מחדש
7 | צא
8 | מסנן טען מחדש
9 | הגדרות מתקדמות
10 | למנוע שינה התקן
11 | אתחול אוטומטי
12 | לאפשר חסימת מודעות
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ja/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP プロキシ ポート:
6 | 再実行
7 | 終了
8 | ファイルの再読み込み
9 | 詳細設定
10 | デバイスをスリープさせない
11 | 自動起動
12 | 広告ブロックを有効にします。
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ko/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP 프록시 포트:
6 | 재시작
7 | 종료
8 | 재설정 필터
9 | 고급 설정
10 | 기기 휴면모드 방지
11 | 자동 시작
12 | 광고 차단 기능 설정하기
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-nl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP proxypoort:
6 | Herstart
7 | Sluiten
8 | Filer herladen
9 | Geavanceerde instellingen
10 | Apparaat blijft actief
11 | Autostart
12 | Advertentieblokkering inschakelen
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-no/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP proxy-porten:
6 | Omstart
7 | Avslutt
8 | Last filter på nytt
9 | Avanserte innstillinger
10 | Forhindre at apparatet går i sovemodus
11 | Start automatisk
12 | Aktiver annonseblokkering
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-pl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | Port serwera proxy HTTP:
6 | Zrestartuj
7 | Wyjdź
8 | Wczytaj ponownie filtr
9 | Ustawienia zaawansowane
10 | Zapobiegnij uśpieniu urządzenia
11 | Autostart
12 | Zezwól na blokowanie reklam
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-pt-rBR/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Proxy HTTP
5 | Porta do Proxy HTTP:
6 | Reiniciar
7 | Sair
8 | Recarregar filtro
9 | Configurações Avançadas
10 | Impedir Suspensão do Dispositivo
11 | Início Automático
12 | Habilitar Bloqueio de Anúncios
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-pt-rPT/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Proxy HTTP
5 | Porta do proxy HTTP:
6 | Reiniciar
7 | Sair
8 | Recarregar filtro
9 | Configurações avançadas
10 | Impedir que o dispositivo entre em modo de suspensão
11 | Auto iniciar
12 | Activar bloqueio de anúncios
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ro/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP proxy port:
6 | Repornește
7 | Iesire
8 | Reîncarcă filtrul
9 | Setări avansate
10 | Împiedică intrarea în repaus a dispozitivului
11 | Pornire automată
12 | Activează blocarea reclamelor
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTP-прокси
5 | Порт HTTP-прокси:
6 | Перезапуск
7 | Выйти
8 | Перезагрузить фильтр
9 | Дополнительные настройки
10 | Не давать устройству уснуть
11 | Автозапуск
12 | Включить блокировку рекламы
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-sr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ХТТПпроxy
5 | ХТТП проxy прикључак:
6 | Поновно покретање
7 | Излаз
8 | Пуњење филтера
9 | Напредна подешавања
10 | Спречавање уређај сна
11 | Аутоматско покретање
12 | Омогући блокирање огласа
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-sv-rSE/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | Http-proxy-porten:
6 | Starta om
7 | Lämna
8 | Ladda om filter
9 | Avancerade inställningar
10 | Förhindra enhets viloläge
11 | Autostart
12 | Aktivera annonsblockering
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-tr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP proxy portu:
6 | Yeniden Başlat
7 | Çıkış
8 | Filtreyi yeniden yükle
9 | Gelişmiş ayarlar
10 | Cihazın uykuya geçmesini önle
11 | Otomatik Başlatma
12 | Reklam engellemeyi etkinleştir
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-uk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP проксі-порт:
6 | Перезапустити
7 | Вихід
8 | Перезавантажити фільтр
9 | Додаткові налаштування
10 | Заборонити перехід пристрою в режим сну
11 | Автозапуск
12 | Увімкнути блокування реклами
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-vi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP proxy Cổng:
6 | Khởi động lại
7 | Thoát
8 | Tải lại bộ lọc
9 | Cài đặt nâng cao
10 | Ngăn thiết bị ngủ đông
11 | Tự khởi động
12 | Cho phép chặn quảng cáo
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP 代理端口:
6 | 重新启动
7 | 退出
8 | 重新加载过滤器
9 | 高级设置
10 | 防止设备睡眠
11 | 自动启动
12 | 启用广告拦截
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rTW/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Httpproxy
5 | 代理伺服器連接埠
6 | 重新下載
7 | 結束
8 | 重新載入篩選器
9 | 高級的設置
10 | 防止設備睡眠
11 | 自動啟動
12 | 啟用廣告阻止
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | HTTPproxy
5 | HTTP proxy port:
6 | Restart
7 | Exit
8 | Reload filter
9 | Advanced settings
10 | Prevent device sleep
11 | Autostart
12 | Enable ad-blocking
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | }
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:3.0.1'
8 | }
9 | }
10 |
11 | allprojects {
12 | repositories {
13 | jcenter()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngoZenz/personalhttpproxy/cbce29ae23cdfa07fe6fc917aad8f8590ee7ca2b/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/personalHTTPproxy_icon.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IngoZenz/personalhttpproxy/cbce29ae23cdfa07fe6fc917aad8f8590ee7ca2b/personalHTTPproxy_icon.zip
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------