├── .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 | --------------------------------------------------------------------------------