diff --git a/.bzrignore b/.bzrignore new file mode 100644 index 0000000..20ffdaa --- /dev/null +++ b/.bzrignore @@ -0,0 +1,21 @@ +bin/android-netspoof.apk +bin/classes.dex +bin/resources.ap_ +bin/uk +bglarge.png +bgmedium.png +bgsmall.png +bin/android-netspoof.newproc.apk +bg-large.png +bg-med.png +bg-small.png +bin/android-netspoof.api8.apk +bzr.sf +obj +obj/local +bin/classes +bin/res +bin/android-netspoof.zip.apk +bin/AndroidManifest.xml +bin/dexedLibs +bin/jarlist.cache diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..7bc01d9 --- /dev/null +++ b/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..b1205b1 --- /dev/null +++ b/.project @@ -0,0 +1,33 @@ + + + android-netspoof + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..c223eae --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a0453 --- /dev/null +++ b/COPYING @@ -0,0 +1,621 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/bglarge.xcf b/bglarge.xcf new file mode 100644 index 0000000..c79764d Binary files /dev/null and b/bglarge.xcf differ diff --git a/bgmedium.xcf b/bgmedium.xcf new file mode 100644 index 0000000..5cc6534 Binary files /dev/null and b/bgmedium.xcf differ diff --git a/bgsmall.xcf b/bgsmall.xcf new file mode 100644 index 0000000..ebb00e3 Binary files /dev/null and b/bgsmall.xcf differ diff --git a/busybox.netspoof.config b/busybox.netspoof.config new file mode 100644 index 0000000..e76a7fe --- /dev/null +++ b/busybox.netspoof.config @@ -0,0 +1,1005 @@ +# +# Automatically generated make config: don't edit +# Busybox version: 1.19.2 +# Sun Oct 16 20:23:38 2011 +# +CONFIG_HAVE_DOT_CONFIG=y + +# +# Busybox Settings +# + +# +# General Configuration +# +CONFIG_DESKTOP=y +# CONFIG_EXTRA_COMPAT is not set +CONFIG_INCLUDE_SUSv2=y +# CONFIG_USE_PORTABLE_CODE is not set +CONFIG_PLATFORM_LINUX=y +CONFIG_FEATURE_BUFFERS_USE_MALLOC=y +# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set +# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set +CONFIG_SHOW_USAGE=y +CONFIG_FEATURE_VERBOSE_USAGE=y +CONFIG_FEATURE_COMPRESS_USAGE=y +CONFIG_FEATURE_INSTALLER=y +# CONFIG_INSTALL_NO_USR is not set +# CONFIG_LOCALE_SUPPORT is not set +CONFIG_UNICODE_SUPPORT=y +# CONFIG_UNICODE_USING_LOCALE is not set +# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_SUBST_WCHAR=63 +CONFIG_LAST_SUPPORTED_WCHAR=767 +# CONFIG_UNICODE_COMBINING_WCHARS is not set +# CONFIG_UNICODE_WIDE_WCHARS is not set +# CONFIG_UNICODE_BIDI_SUPPORT is not set +# CONFIG_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_UNICODE_PRESERVE_BROKEN is not set +CONFIG_LONG_OPTS=y +CONFIG_FEATURE_DEVPTS=y +# CONFIG_FEATURE_CLEAN_UP is not set +CONFIG_FEATURE_UTMP=y +CONFIG_FEATURE_WTMP=y +CONFIG_FEATURE_PIDFILE=y +CONFIG_FEATURE_SUID=y +CONFIG_FEATURE_SUID_CONFIG=y +CONFIG_FEATURE_SUID_CONFIG_QUIET=y +# CONFIG_SELINUX is not set +# CONFIG_FEATURE_PREFER_APPLETS is not set +CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" +CONFIG_FEATURE_SYSLOG=y +CONFIG_FEATURE_HAVE_RPC=y + +# +# Build Options +# +CONFIG_STATIC=y +# CONFIG_PIE is not set +# CONFIG_NOMMU is not set +# CONFIG_BUILD_LIBBUSYBOX is not set +# CONFIG_FEATURE_INDIVIDUAL is not set +# CONFIG_FEATURE_SHARED_BUSYBOX is not set +CONFIG_LFS=y +CONFIG_CROSS_COMPILER_PREFIX="arm-linux-gnueabi-" +CONFIG_EXTRA_CFLAGS="" + +# +# Debugging Options +# +# CONFIG_DEBUG is not set +# CONFIG_DEBUG_PESSIMIZE is not set +# CONFIG_WERROR is not set +CONFIG_NO_DEBUG_LIB=y +# CONFIG_DMALLOC is not set +# CONFIG_EFENCE is not set + +# +# Installation Options ("make install" behavior) +# +CONFIG_INSTALL_APPLET_SYMLINKS=y +# CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +# CONFIG_INSTALL_APPLET_DONT is not set +# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set +CONFIG_PREFIX="./_install" + +# +# Busybox Library Tuning +# +CONFIG_FEATURE_SYSTEMD=y +CONFIG_FEATURE_RTMINMAX=y +CONFIG_PASSWORD_MINLEN=6 +CONFIG_MD5_SIZE_VS_SPEED=2 +CONFIG_FEATURE_FAST_TOP=y +# CONFIG_FEATURE_ETC_NETWORKS is not set +CONFIG_FEATURE_USE_TERMIOS=y +CONFIG_FEATURE_EDITING=y +CONFIG_FEATURE_EDITING_MAX_LEN=1024 +# CONFIG_FEATURE_EDITING_VI is not set +CONFIG_FEATURE_EDITING_HISTORY=255 +CONFIG_FEATURE_EDITING_SAVEHISTORY=y +CONFIG_FEATURE_REVERSE_SEARCH=y +CONFIG_FEATURE_TAB_COMPLETION=y +# CONFIG_FEATURE_USERNAME_COMPLETION is not set +CONFIG_FEATURE_EDITING_FANCY_PROMPT=y +# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set +CONFIG_FEATURE_NON_POSIX_CP=y +# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set +CONFIG_FEATURE_COPYBUF_KB=4 +CONFIG_FEATURE_SKIP_ROOTFS=y +# CONFIG_MONOTONIC_SYSCALL is not set +CONFIG_IOCTL_HEX2STR_ERROR=y +CONFIG_FEATURE_HWIB=y + +# +# Applets +# + +# +# Archival Utilities +# +CONFIG_FEATURE_SEAMLESS_XZ=y +CONFIG_FEATURE_SEAMLESS_LZMA=y +CONFIG_FEATURE_SEAMLESS_BZ2=y +CONFIG_FEATURE_SEAMLESS_GZ=y +# CONFIG_FEATURE_SEAMLESS_Z is not set +# CONFIG_AR is not set +# CONFIG_FEATURE_AR_LONG_FILENAMES is not set +# CONFIG_FEATURE_AR_CREATE is not set +# CONFIG_BUNZIP2 is not set +# CONFIG_BZIP2 is not set +# CONFIG_CPIO is not set +# CONFIG_FEATURE_CPIO_O is not set +# CONFIG_FEATURE_CPIO_P is not set +# CONFIG_DPKG is not set +# CONFIG_DPKG_DEB is not set +# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set +# CONFIG_GUNZIP is not set +# CONFIG_GZIP is not set +# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set +# CONFIG_LZOP is not set +# CONFIG_LZOP_COMPR_HIGH is not set +# CONFIG_RPM2CPIO is not set +# CONFIG_RPM is not set +# CONFIG_TAR is not set +# CONFIG_FEATURE_TAR_CREATE is not set +# CONFIG_FEATURE_TAR_AUTODETECT is not set +# CONFIG_FEATURE_TAR_FROM is not set +# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set +# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +# CONFIG_FEATURE_TAR_GNU_EXTENSIONS is not set +# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set +# CONFIG_FEATURE_TAR_TO_COMMAND is not set +# CONFIG_FEATURE_TAR_UNAME_GNAME is not set +# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set +# CONFIG_FEATURE_TAR_SELINUX is not set +# CONFIG_UNCOMPRESS is not set +# CONFIG_UNLZMA is not set +# CONFIG_FEATURE_LZMA_FAST is not set +# CONFIG_LZMA is not set +# CONFIG_UNXZ is not set +# CONFIG_XZ is not set +# CONFIG_UNZIP is not set + +# +# Coreutils +# +# CONFIG_BASENAME is not set +CONFIG_CAT=y +CONFIG_DATE=y +CONFIG_FEATURE_DATE_ISOFMT=y +# CONFIG_FEATURE_DATE_NANO is not set +CONFIG_FEATURE_DATE_COMPAT=y +CONFIG_ID=y +# CONFIG_GROUPS is not set +CONFIG_TEST=y +CONFIG_FEATURE_TEST_64=y +CONFIG_TOUCH=y +CONFIG_TR=y +CONFIG_FEATURE_TR_CLASSES=y +CONFIG_FEATURE_TR_EQUIV=y +# CONFIG_BASE64 is not set +# CONFIG_WHO is not set +# CONFIG_USERS is not set +# CONFIG_CAL is not set +# CONFIG_CATV is not set +# CONFIG_CHGRP is not set +CONFIG_CHMOD=y +CONFIG_CHOWN=y +CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y +CONFIG_CHROOT=y +# CONFIG_CKSUM is not set +# CONFIG_COMM is not set +CONFIG_CP=y +CONFIG_FEATURE_CP_LONG_OPTIONS=y +CONFIG_CUT=y +CONFIG_DD=y +CONFIG_FEATURE_DD_SIGNAL_HANDLING=y +CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y +CONFIG_FEATURE_DD_IBS_OBS=y +# CONFIG_DF is not set +# CONFIG_FEATURE_DF_FANCY is not set +# CONFIG_DIRNAME is not set +# CONFIG_DOS2UNIX is not set +# CONFIG_UNIX2DOS is not set +CONFIG_DU=y +CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y +CONFIG_ECHO=y +CONFIG_FEATURE_FANCY_ECHO=y +CONFIG_ENV=y +CONFIG_FEATURE_ENV_LONG_OPTIONS=y +# CONFIG_EXPAND is not set +# CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set +# CONFIG_EXPR is not set +# CONFIG_EXPR_MATH_SUPPORT_64 is not set +# CONFIG_FALSE is not set +# CONFIG_FOLD is not set +# CONFIG_FSYNC is not set +# CONFIG_HEAD is not set +# CONFIG_FEATURE_FANCY_HEAD is not set +# CONFIG_HOSTID is not set +CONFIG_INSTALL=y +CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y +CONFIG_LN=y +CONFIG_LOGNAME=y +CONFIG_LS=y +CONFIG_FEATURE_LS_FILETYPES=y +CONFIG_FEATURE_LS_FOLLOWLINKS=y +CONFIG_FEATURE_LS_RECURSIVE=y +CONFIG_FEATURE_LS_SORTFILES=y +CONFIG_FEATURE_LS_TIMESTAMPS=y +CONFIG_FEATURE_LS_USERNAME=y +CONFIG_FEATURE_LS_COLOR=y +CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y +CONFIG_MD5SUM=y +CONFIG_MKDIR=y +CONFIG_FEATURE_MKDIR_LONG_OPTIONS=y +CONFIG_MKFIFO=y +CONFIG_MKNOD=y +CONFIG_MV=y +CONFIG_FEATURE_MV_LONG_OPTIONS=y +CONFIG_NICE=y +CONFIG_NOHUP=y +# CONFIG_OD is not set +# CONFIG_PRINTENV is not set +# CONFIG_PRINTF is not set +CONFIG_PWD=y +# CONFIG_READLINK is not set +# CONFIG_FEATURE_READLINK_FOLLOW is not set +# CONFIG_REALPATH is not set +CONFIG_RM=y +CONFIG_RMDIR=y +CONFIG_FEATURE_RMDIR_LONG_OPTIONS=y +CONFIG_SEQ=y +# CONFIG_SHA1SUM is not set +# CONFIG_SHA256SUM is not set +# CONFIG_SHA512SUM is not set +CONFIG_SLEEP=y +CONFIG_FEATURE_FANCY_SLEEP=y +CONFIG_FEATURE_FLOAT_SLEEP=y +# CONFIG_SORT is not set +# CONFIG_FEATURE_SORT_BIG is not set +# CONFIG_SPLIT is not set +# CONFIG_FEATURE_SPLIT_FANCY is not set +# CONFIG_STAT is not set +# CONFIG_FEATURE_STAT_FORMAT is not set +# CONFIG_STTY is not set +CONFIG_SUM=y +# CONFIG_SYNC is not set +# CONFIG_TAC is not set +# CONFIG_TAIL is not set +# CONFIG_FEATURE_FANCY_TAIL is not set +CONFIG_TEE=y +CONFIG_FEATURE_TEE_USE_BLOCK_IO=y +CONFIG_TRUE=y +# CONFIG_TTY is not set +# CONFIG_UNAME is not set +# CONFIG_UNEXPAND is not set +# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set +CONFIG_UNIQ=y +# CONFIG_USLEEP is not set +# CONFIG_UUDECODE is not set +# CONFIG_UUENCODE is not set +CONFIG_WC=y +CONFIG_FEATURE_WC_LARGE=y +CONFIG_WHOAMI=y +# CONFIG_YES is not set + +# +# Common options for cp and mv +# +# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set + +# +# Common options for ls, more and telnet +# +CONFIG_FEATURE_AUTOWIDTH=y + +# +# Common options for df, du, ls +# +CONFIG_FEATURE_HUMAN_READABLE=y + +# +# Common options for md5sum, sha1sum, sha256sum, sha512sum +# +CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y + +# +# Console Utilities +# +# CONFIG_CHVT is not set +# CONFIG_FGCONSOLE is not set +# CONFIG_CLEAR is not set +# CONFIG_DEALLOCVT is not set +# CONFIG_DUMPKMAP is not set +# CONFIG_KBD_MODE is not set +# CONFIG_LOADFONT is not set +# CONFIG_LOADKMAP is not set +# CONFIG_OPENVT is not set +CONFIG_RESET=y +# CONFIG_RESIZE is not set +# CONFIG_FEATURE_RESIZE_PRINT is not set +# CONFIG_SETCONSOLE is not set +# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set +# CONFIG_SETFONT is not set +# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set +CONFIG_DEFAULT_SETFONT_DIR="" +# CONFIG_SETKEYCODES is not set +# CONFIG_SETLOGCONS is not set +# CONFIG_SHOWKEY is not set +# CONFIG_FEATURE_LOADFONT_PSF2 is not set +# CONFIG_FEATURE_LOADFONT_RAW is not set + +# +# Debian Utilities +# +CONFIG_MKTEMP=y +# CONFIG_PIPE_PROGRESS is not set +# CONFIG_RUN_PARTS is not set +# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set +# CONFIG_FEATURE_RUN_PARTS_FANCY is not set +# CONFIG_START_STOP_DAEMON is not set +# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set +# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +# CONFIG_WHICH is not set + +# +# Editors +# +# CONFIG_PATCH is not set +# CONFIG_VI is not set +CONFIG_FEATURE_VI_MAX_LEN=0 +# CONFIG_FEATURE_VI_8BIT is not set +# CONFIG_FEATURE_VI_COLON is not set +# CONFIG_FEATURE_VI_YANKMARK is not set +# CONFIG_FEATURE_VI_SEARCH is not set +# CONFIG_FEATURE_VI_REGEX_SEARCH is not set +# CONFIG_FEATURE_VI_USE_SIGNALS is not set +# CONFIG_FEATURE_VI_DOT_CMD is not set +# CONFIG_FEATURE_VI_READONLY is not set +# CONFIG_FEATURE_VI_SETOPTS is not set +# CONFIG_FEATURE_VI_SET is not set +# CONFIG_FEATURE_VI_WIN_RESIZE is not set +# CONFIG_FEATURE_VI_ASK_TERMINAL is not set +# CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set +CONFIG_AWK=y +CONFIG_FEATURE_AWK_LIBM=y +# CONFIG_CMP is not set +# CONFIG_DIFF is not set +# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set +# CONFIG_FEATURE_DIFF_DIR is not set +# CONFIG_ED is not set +CONFIG_SED=y +CONFIG_FEATURE_ALLOW_EXEC=y + +# +# Finding Utilities +# +CONFIG_FIND=y +CONFIG_FEATURE_FIND_PRINT0=y +CONFIG_FEATURE_FIND_MTIME=y +CONFIG_FEATURE_FIND_MMIN=y +CONFIG_FEATURE_FIND_PERM=y +CONFIG_FEATURE_FIND_TYPE=y +CONFIG_FEATURE_FIND_XDEV=y +CONFIG_FEATURE_FIND_MAXDEPTH=y +CONFIG_FEATURE_FIND_NEWER=y +CONFIG_FEATURE_FIND_INUM=y +CONFIG_FEATURE_FIND_EXEC=y +CONFIG_FEATURE_FIND_USER=y +CONFIG_FEATURE_FIND_GROUP=y +CONFIG_FEATURE_FIND_NOT=y +CONFIG_FEATURE_FIND_DEPTH=y +CONFIG_FEATURE_FIND_PAREN=y +CONFIG_FEATURE_FIND_SIZE=y +CONFIG_FEATURE_FIND_PRUNE=y +CONFIG_FEATURE_FIND_DELETE=y +CONFIG_FEATURE_FIND_PATH=y +CONFIG_FEATURE_FIND_REGEX=y +# CONFIG_FEATURE_FIND_CONTEXT is not set +CONFIG_FEATURE_FIND_LINKS=y +CONFIG_GREP=y +CONFIG_FEATURE_GREP_EGREP_ALIAS=y +CONFIG_FEATURE_GREP_FGREP_ALIAS=y +CONFIG_FEATURE_GREP_CONTEXT=y +CONFIG_XARGS=y +CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y +CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y +CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y +CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y + +# +# Init Utilities +# +# CONFIG_BOOTCHARTD is not set +# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set +# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +# CONFIG_HALT is not set +# CONFIG_FEATURE_CALL_TELINIT is not set +CONFIG_TELINIT_PATH="" +# CONFIG_INIT is not set +# CONFIG_FEATURE_USE_INITTAB is not set +# CONFIG_FEATURE_KILL_REMOVED is not set +CONFIG_FEATURE_KILL_DELAY=0 +# CONFIG_FEATURE_INIT_SCTTY is not set +# CONFIG_FEATURE_INIT_SYSLOG is not set +# CONFIG_FEATURE_EXTRA_QUIET is not set +# CONFIG_FEATURE_INIT_COREDUMPS is not set +# CONFIG_FEATURE_INITRD is not set +CONFIG_INIT_TERMINAL_TYPE="" +# CONFIG_MESG is not set +# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set + +# +# Login/Password Management Utilities +# +# CONFIG_ADD_SHELL is not set +# CONFIG_REMOVE_SHELL is not set +# CONFIG_FEATURE_SHADOWPASSWDS is not set +# CONFIG_USE_BB_PWD_GRP is not set +# CONFIG_USE_BB_SHADOW is not set +# CONFIG_USE_BB_CRYPT is not set +# CONFIG_USE_BB_CRYPT_SHA is not set +# CONFIG_ADDUSER is not set +# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set +# CONFIG_FEATURE_CHECK_NAMES is not set +CONFIG_FIRST_SYSTEM_ID=0 +CONFIG_LAST_SYSTEM_ID=0 +# CONFIG_ADDGROUP is not set +# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set +# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set +# CONFIG_DELUSER is not set +# CONFIG_DELGROUP is not set +# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set +# CONFIG_GETTY is not set +CONFIG_LOGIN=y +# CONFIG_PAM is not set +CONFIG_LOGIN_SCRIPTS=y +CONFIG_FEATURE_NOLOGIN=y +CONFIG_FEATURE_SECURETTY=y +# CONFIG_PASSWD is not set +# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set +CONFIG_CRYPTPW=y +# CONFIG_CHPASSWD is not set +CONFIG_SU=y +CONFIG_FEATURE_SU_SYSLOG=y +CONFIG_FEATURE_SU_CHECKS_SHELLS=y +# CONFIG_SULOGIN is not set +# CONFIG_VLOCK is not set + +# +# Linux Ext2 FS Progs +# +# CONFIG_CHATTR is not set +CONFIG_FSCK=y +# CONFIG_LSATTR is not set +CONFIG_TUNE2FS=y + +# +# Linux Module Utilities +# +CONFIG_MODINFO=y +CONFIG_MODPROBE_SMALL=y +CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE=y +CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y +# CONFIG_INSMOD is not set +# CONFIG_RMMOD is not set +# CONFIG_LSMOD is not set +# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set +# CONFIG_MODPROBE is not set +# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set +# CONFIG_DEPMOD is not set + +# +# Options common to multiple modutils +# +# CONFIG_FEATURE_2_4_MODULES is not set +# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set +# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set +# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set +# CONFIG_FEATURE_MODUTILS_ALIAS is not set +# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set +CONFIG_DEFAULT_MODULES_DIR="/lib/modules" +CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" + +# +# Linux System Utilities +# +# CONFIG_BLOCKDEV is not set +# CONFIG_REV is not set +# CONFIG_ACPID is not set +# CONFIG_FEATURE_ACPID_COMPAT is not set +# CONFIG_BLKID is not set +# CONFIG_FEATURE_BLKID_TYPE is not set +CONFIG_DMESG=y +CONFIG_FEATURE_DMESG_PRETTY=y +# CONFIG_FBSET is not set +# CONFIG_FEATURE_FBSET_FANCY is not set +# CONFIG_FEATURE_FBSET_READMODE is not set +# CONFIG_FDFLUSH is not set +# CONFIG_FDFORMAT is not set +# CONFIG_FDISK is not set +# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set +# CONFIG_FEATURE_FDISK_WRITABLE is not set +# CONFIG_FEATURE_AIX_LABEL is not set +# CONFIG_FEATURE_SGI_LABEL is not set +# CONFIG_FEATURE_SUN_LABEL is not set +# CONFIG_FEATURE_OSF_LABEL is not set +# CONFIG_FEATURE_GPT_LABEL is not set +# CONFIG_FEATURE_FDISK_ADVANCED is not set +# CONFIG_FINDFS is not set +# CONFIG_FLOCK is not set +# CONFIG_FREERAMDISK is not set +# CONFIG_FSCK_MINIX is not set +CONFIG_MKFS_EXT2=y +# CONFIG_MKFS_MINIX is not set +# CONFIG_FEATURE_MINIX2 is not set +# CONFIG_MKFS_REISER is not set +# CONFIG_MKFS_VFAT is not set +# CONFIG_GETOPT is not set +# CONFIG_FEATURE_GETOPT_LONG is not set +CONFIG_HEXDUMP=y +CONFIG_FEATURE_HEXDUMP_REVERSE=y +CONFIG_HD=y +# CONFIG_HWCLOCK is not set +# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set +# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set +# CONFIG_IPCRM is not set +# CONFIG_IPCS is not set +CONFIG_LOSETUP=y +# CONFIG_LSPCI is not set +# CONFIG_LSUSB is not set +# CONFIG_MDEV is not set +# CONFIG_FEATURE_MDEV_CONF is not set +# CONFIG_FEATURE_MDEV_RENAME is not set +# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set +# CONFIG_FEATURE_MDEV_EXEC is not set +# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set +# CONFIG_MKSWAP is not set +# CONFIG_FEATURE_MKSWAP_UUID is not set +CONFIG_MORE=y +CONFIG_MOUNT=y +CONFIG_FEATURE_MOUNT_FAKE=y +CONFIG_FEATURE_MOUNT_VERBOSE=y +# CONFIG_FEATURE_MOUNT_HELPERS is not set +CONFIG_FEATURE_MOUNT_LABEL=y +CONFIG_FEATURE_MOUNT_NFS=y +CONFIG_FEATURE_MOUNT_CIFS=y +CONFIG_FEATURE_MOUNT_FLAGS=y +CONFIG_FEATURE_MOUNT_FSTAB=y +# CONFIG_PIVOT_ROOT is not set +# CONFIG_RDATE is not set +# CONFIG_RDEV is not set +# CONFIG_READPROFILE is not set +# CONFIG_RTCWAKE is not set +# CONFIG_SCRIPT is not set +# CONFIG_SCRIPTREPLAY is not set +# CONFIG_SETARCH is not set +# CONFIG_SWAPONOFF is not set +# CONFIG_FEATURE_SWAPON_PRI is not set +# CONFIG_SWITCH_ROOT is not set +CONFIG_UMOUNT=y +CONFIG_FEATURE_UMOUNT_ALL=y + +# +# Common options for mount/umount +# +CONFIG_FEATURE_MOUNT_LOOP=y +CONFIG_FEATURE_MOUNT_LOOP_CREATE=y +# CONFIG_FEATURE_MTAB_SUPPORT is not set +CONFIG_VOLUMEID=y + +# +# Filesystem/Volume identification +# +CONFIG_FEATURE_VOLUMEID_EXT=y +CONFIG_FEATURE_VOLUMEID_BTRFS=y +CONFIG_FEATURE_VOLUMEID_REISERFS=y +CONFIG_FEATURE_VOLUMEID_FAT=y +CONFIG_FEATURE_VOLUMEID_HFS=y +CONFIG_FEATURE_VOLUMEID_JFS=y +CONFIG_FEATURE_VOLUMEID_XFS=y +CONFIG_FEATURE_VOLUMEID_NTFS=y +CONFIG_FEATURE_VOLUMEID_ISO9660=y +CONFIG_FEATURE_VOLUMEID_UDF=y +CONFIG_FEATURE_VOLUMEID_LUKS=y +CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y +CONFIG_FEATURE_VOLUMEID_CRAMFS=y +CONFIG_FEATURE_VOLUMEID_ROMFS=y +CONFIG_FEATURE_VOLUMEID_SYSV=y +CONFIG_FEATURE_VOLUMEID_OCFS2=y +CONFIG_FEATURE_VOLUMEID_LINUXRAID=y + +# +# Miscellaneous Utilities +# +# CONFIG_CONSPY is not set +# CONFIG_LESS is not set +CONFIG_FEATURE_LESS_MAXLINES=0 +# CONFIG_FEATURE_LESS_BRACKETS is not set +# CONFIG_FEATURE_LESS_FLAGS is not set +# CONFIG_FEATURE_LESS_MARKS is not set +# CONFIG_FEATURE_LESS_REGEXP is not set +# CONFIG_FEATURE_LESS_WINCH is not set +# CONFIG_FEATURE_LESS_ASK_TERMINAL is not set +# CONFIG_FEATURE_LESS_DASHCMD is not set +# CONFIG_FEATURE_LESS_LINENUMS is not set +# CONFIG_NANDWRITE is not set +# CONFIG_NANDDUMP is not set +# CONFIG_SETSERIAL is not set +# CONFIG_UBIATTACH is not set +# CONFIG_UBIDETACH is not set +# CONFIG_UBIMKVOL is not set +# CONFIG_UBIRMVOL is not set +# CONFIG_UBIRSVOL is not set +# CONFIG_UBIUPDATEVOL is not set +# CONFIG_ADJTIMEX is not set +# CONFIG_BBCONFIG is not set +# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set +# CONFIG_BEEP is not set +CONFIG_FEATURE_BEEP_FREQ=0 +CONFIG_FEATURE_BEEP_LENGTH_MS=0 +# CONFIG_CHAT is not set +# CONFIG_FEATURE_CHAT_NOFAIL is not set +# CONFIG_FEATURE_CHAT_TTY_HIFI is not set +# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set +# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set +# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set +# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set +# CONFIG_FEATURE_CHAT_CLR_ABORT is not set +# CONFIG_CHRT is not set +# CONFIG_CROND is not set +# CONFIG_FEATURE_CROND_D is not set +# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set +CONFIG_FEATURE_CROND_DIR="" +# CONFIG_CRONTAB is not set +# CONFIG_DC is not set +# CONFIG_FEATURE_DC_LIBM is not set +# CONFIG_DEVFSD is not set +# CONFIG_DEVFSD_MODLOAD is not set +# CONFIG_DEVFSD_FG_NP is not set +# CONFIG_DEVFSD_VERBOSE is not set +# CONFIG_FEATURE_DEVFS is not set +# CONFIG_DEVMEM is not set +# CONFIG_EJECT is not set +# CONFIG_FEATURE_EJECT_SCSI is not set +# CONFIG_FBSPLASH is not set +# CONFIG_FLASHCP is not set +# CONFIG_FLASH_LOCK is not set +# CONFIG_FLASH_UNLOCK is not set +# CONFIG_FLASH_ERASEALL is not set +# CONFIG_IONICE is not set +# CONFIG_INOTIFYD is not set +# CONFIG_LAST is not set +# CONFIG_FEATURE_LAST_SMALL is not set +# CONFIG_FEATURE_LAST_FANCY is not set +# CONFIG_HDPARM is not set +# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set +# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set +# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set +CONFIG_MAKEDEVS=y +# CONFIG_FEATURE_MAKEDEVS_LEAF is not set +CONFIG_FEATURE_MAKEDEVS_TABLE=y +# CONFIG_MAN is not set +# CONFIG_MICROCOM is not set +# CONFIG_MOUNTPOINT is not set +# CONFIG_MT is not set +# CONFIG_RAIDAUTORUN is not set +# CONFIG_READAHEAD is not set +# CONFIG_RFKILL is not set +# CONFIG_RUNLEVEL is not set +# CONFIG_RX is not set +# CONFIG_SETSID is not set +# CONFIG_STRINGS is not set +# CONFIG_TASKSET is not set +# CONFIG_FEATURE_TASKSET_FANCY is not set +CONFIG_TIME=y +CONFIG_TIMEOUT=y +# CONFIG_TTYSIZE is not set +# CONFIG_VOLNAME is not set +# CONFIG_WALL is not set +# CONFIG_WATCHDOG is not set + +# +# Networking Utilities +# +# CONFIG_NAMEIF is not set +# CONFIG_FEATURE_NAMEIF_EXTENDED is not set +# CONFIG_NBDCLIENT is not set +CONFIG_NC=y +CONFIG_NC_SERVER=y +CONFIG_NC_EXTRA=y +# CONFIG_NC_110_COMPAT is not set +CONFIG_PING=y +CONFIG_PING6=y +CONFIG_FEATURE_FANCY_PING=y +# CONFIG_WHOIS is not set +CONFIG_FEATURE_IPV6=y +# CONFIG_FEATURE_UNIX_LOCAL is not set +CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y +# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set +# CONFIG_ARP is not set +# CONFIG_ARPING is not set +# CONFIG_BRCTL is not set +# CONFIG_FEATURE_BRCTL_FANCY is not set +# CONFIG_FEATURE_BRCTL_SHOW is not set +# CONFIG_DNSD is not set +# CONFIG_ETHER_WAKE is not set +# CONFIG_FAKEIDENTD is not set +# CONFIG_FTPD is not set +# CONFIG_FEATURE_FTP_WRITE is not set +# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set +# CONFIG_FTPGET is not set +# CONFIG_FTPPUT is not set +# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set +# CONFIG_HOSTNAME is not set +# CONFIG_HTTPD is not set +# CONFIG_FEATURE_HTTPD_RANGES is not set +# CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set +# CONFIG_FEATURE_HTTPD_SETUID is not set +# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set +# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set +# CONFIG_FEATURE_HTTPD_CGI is not set +# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set +# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set +# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set +# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set +# CONFIG_FEATURE_HTTPD_PROXY is not set +# CONFIG_FEATURE_HTTPD_GZIP is not set +# CONFIG_IFCONFIG is not set +# CONFIG_FEATURE_IFCONFIG_STATUS is not set +# CONFIG_FEATURE_IFCONFIG_SLIP is not set +# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +# CONFIG_FEATURE_IFCONFIG_HW is not set +# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set +# CONFIG_IFENSLAVE is not set +# CONFIG_IFPLUGD is not set +# CONFIG_IFUPDOWN is not set +CONFIG_IFUPDOWN_IFSTATE_PATH="" +# CONFIG_FEATURE_IFUPDOWN_IP is not set +# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set +# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set +# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set +# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set +# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set +# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set +# CONFIG_INETD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set +# CONFIG_FEATURE_INETD_RPC is not set +# CONFIG_IP is not set +# CONFIG_FEATURE_IP_ADDRESS is not set +# CONFIG_FEATURE_IP_LINK is not set +# CONFIG_FEATURE_IP_ROUTE is not set +# CONFIG_FEATURE_IP_TUNNEL is not set +# CONFIG_FEATURE_IP_RULE is not set +# CONFIG_FEATURE_IP_SHORT_FORMS is not set +# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set +# CONFIG_IPADDR is not set +# CONFIG_IPLINK is not set +# CONFIG_IPROUTE is not set +# CONFIG_IPTUNNEL is not set +# CONFIG_IPRULE is not set +# CONFIG_IPCALC is not set +# CONFIG_FEATURE_IPCALC_FANCY is not set +# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set +# CONFIG_NETSTAT is not set +# CONFIG_FEATURE_NETSTAT_WIDE is not set +# CONFIG_FEATURE_NETSTAT_PRG is not set +# CONFIG_NSLOOKUP is not set +# CONFIG_NTPD is not set +# CONFIG_FEATURE_NTPD_SERVER is not set +# CONFIG_PSCAN is not set +CONFIG_ROUTE=y +# CONFIG_SLATTACH is not set +# CONFIG_TCPSVD is not set +# CONFIG_TELNET is not set +# CONFIG_FEATURE_TELNET_TTYPE is not set +# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set +# CONFIG_TELNETD is not set +# CONFIG_FEATURE_TELNETD_STANDALONE is not set +# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set +# CONFIG_TFTP is not set +# CONFIG_TFTPD is not set +# CONFIG_FEATURE_TFTP_GET is not set +# CONFIG_FEATURE_TFTP_PUT is not set +# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set +# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set +# CONFIG_TFTP_DEBUG is not set +# CONFIG_TRACEROUTE is not set +# CONFIG_TRACEROUTE6 is not set +# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set +# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set +# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set +# CONFIG_TUNCTL is not set +# CONFIG_FEATURE_TUNCTL_UG is not set +# CONFIG_UDHCPD is not set +# CONFIG_DHCPRELAY is not set +# CONFIG_DUMPLEASES is not set +# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set +# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set +CONFIG_DHCPD_LEASES_FILE="" +# CONFIG_UDHCPC is not set +# CONFIG_FEATURE_UDHCPC_ARPING is not set +# CONFIG_FEATURE_UDHCP_PORT is not set +CONFIG_UDHCP_DEBUG=0 +# CONFIG_FEATURE_UDHCP_RFC3397 is not set +# CONFIG_FEATURE_UDHCP_8021Q is not set +CONFIG_UDHCPC_DEFAULT_SCRIPT="" +CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0 +CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" +# CONFIG_UDPSVD is not set +# CONFIG_VCONFIG is not set +CONFIG_WGET=y +CONFIG_FEATURE_WGET_STATUSBAR=y +CONFIG_FEATURE_WGET_AUTHENTICATION=y +CONFIG_FEATURE_WGET_LONG_OPTIONS=y +CONFIG_FEATURE_WGET_TIMEOUT=y +# CONFIG_ZCIP is not set + +# +# Print Utilities +# +# CONFIG_LPD is not set +# CONFIG_LPR is not set +# CONFIG_LPQ is not set + +# +# Mail Utilities +# +# CONFIG_MAKEMIME is not set +CONFIG_FEATURE_MIME_CHARSET="" +# CONFIG_POPMAILDIR is not set +# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_REFORMIME is not set +# CONFIG_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_SENDMAIL is not set + +# +# Process Utilities +# +# CONFIG_IOSTAT is not set +# CONFIG_MPSTAT is not set +# CONFIG_NMETER is not set +# CONFIG_PMAP is not set +# CONFIG_POWERTOP is not set +# CONFIG_PSTREE is not set +# CONFIG_PWDX is not set +# CONFIG_SMEMCAP is not set +# CONFIG_UPTIME is not set +# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set +CONFIG_FREE=y +# CONFIG_FUSER is not set +CONFIG_KILL=y +CONFIG_KILLALL=y +CONFIG_KILLALL5=y +CONFIG_PGREP=y +# CONFIG_PIDOF is not set +# CONFIG_FEATURE_PIDOF_SINGLE is not set +# CONFIG_FEATURE_PIDOF_OMIT is not set +# CONFIG_PKILL is not set +# CONFIG_PS is not set +# CONFIG_FEATURE_PS_WIDE is not set +# CONFIG_FEATURE_PS_TIME is not set +# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set +# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set +# CONFIG_RENICE is not set +# CONFIG_BB_SYSCTL is not set +# CONFIG_TOP is not set +# CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set +# CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set +# CONFIG_FEATURE_TOP_SMP_CPU is not set +# CONFIG_FEATURE_TOP_DECIMALS is not set +# CONFIG_FEATURE_TOP_SMP_PROCESS is not set +# CONFIG_FEATURE_TOPMEM is not set +# CONFIG_FEATURE_SHOW_THREADS is not set +CONFIG_WATCH=y + +# +# Runit Utilities +# +# CONFIG_RUNSV is not set +# CONFIG_RUNSVDIR is not set +# CONFIG_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_SV is not set +CONFIG_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_SVLOGD is not set +# CONFIG_CHPST is not set +# CONFIG_SETUIDGID is not set +# CONFIG_ENVUIDGID is not set +# CONFIG_ENVDIR is not set +# CONFIG_SOFTLIMIT is not set +# CONFIG_CHCON is not set +# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set +# CONFIG_GETENFORCE is not set +# CONFIG_GETSEBOOL is not set +# CONFIG_LOAD_POLICY is not set +# CONFIG_MATCHPATHCON is not set +# CONFIG_RESTORECON is not set +# CONFIG_RUNCON is not set +# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set +# CONFIG_SELINUXENABLED is not set +# CONFIG_SETENFORCE is not set +# CONFIG_SETFILES is not set +# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_SETSEBOOL is not set +# CONFIG_SESTATUS is not set + +# +# Shells +# +CONFIG_ASH=y +CONFIG_ASH_BASH_COMPAT=y +# CONFIG_ASH_IDLE_TIMEOUT is not set +CONFIG_ASH_JOB_CONTROL=y +CONFIG_ASH_ALIAS=y +CONFIG_ASH_GETOPTS=y +CONFIG_ASH_BUILTIN_ECHO=y +CONFIG_ASH_BUILTIN_PRINTF=y +CONFIG_ASH_BUILTIN_TEST=y +CONFIG_ASH_CMDCMD=y +# CONFIG_ASH_MAIL is not set +CONFIG_ASH_OPTIMIZE_FOR_SIZE=y +CONFIG_ASH_RANDOM_SUPPORT=y +CONFIG_ASH_EXPAND_PRMT=y +# CONFIG_CTTYHACK is not set +# CONFIG_HUSH is not set +# CONFIG_HUSH_BASH_COMPAT is not set +# CONFIG_HUSH_BRACE_EXPANSION is not set +# CONFIG_HUSH_HELP is not set +# CONFIG_HUSH_INTERACTIVE is not set +# CONFIG_HUSH_SAVEHISTORY is not set +# CONFIG_HUSH_JOB is not set +# CONFIG_HUSH_TICK is not set +# CONFIG_HUSH_IF is not set +# CONFIG_HUSH_LOOPS is not set +# CONFIG_HUSH_CASE is not set +# CONFIG_HUSH_FUNCTIONS is not set +# CONFIG_HUSH_LOCAL is not set +# CONFIG_HUSH_RANDOM_SUPPORT is not set +# CONFIG_HUSH_EXPORT_N is not set +# CONFIG_HUSH_MODE_X is not set +# CONFIG_MSH is not set +CONFIG_FEATURE_SH_IS_ASH=y +# CONFIG_FEATURE_SH_IS_HUSH is not set +# CONFIG_FEATURE_SH_IS_NONE is not set +# CONFIG_FEATURE_BASH_IS_ASH is not set +# CONFIG_FEATURE_BASH_IS_HUSH is not set +CONFIG_FEATURE_BASH_IS_NONE=y +CONFIG_SH_MATH_SUPPORT=y +CONFIG_SH_MATH_SUPPORT_64=y +CONFIG_FEATURE_SH_EXTRA_QUIET=y +# CONFIG_FEATURE_SH_STANDALONE is not set +# CONFIG_FEATURE_SH_NOFORK is not set +CONFIG_FEATURE_SH_HISTFILESIZE=y + +# +# System Logging Utilities +# +# CONFIG_SYSLOGD is not set +# CONFIG_FEATURE_ROTATE_LOGFILE is not set +# CONFIG_FEATURE_REMOTE_LOG is not set +# CONFIG_FEATURE_SYSLOGD_DUP is not set +# CONFIG_FEATURE_SYSLOGD_CFG is not set +CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 +# CONFIG_FEATURE_IPC_SYSLOG is not set +CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 +# CONFIG_LOGREAD is not set +# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set +# CONFIG_KLOGD is not set +# CONFIG_FEATURE_KLOGD_KLOGCTL is not set +# CONFIG_LOGGER is not set diff --git a/gen/uk/digitalsquid/netspoofer/BuildConfig.java b/gen/uk/digitalsquid/netspoofer/BuildConfig.java new file mode 100644 index 0000000..5e0f222 --- /dev/null +++ b/gen/uk/digitalsquid/netspoofer/BuildConfig.java @@ -0,0 +1,6 @@ +/** Automatically generated file. DO NOT MODIFY */ +package uk.digitalsquid.netspoofer; + +public final class BuildConfig { + public final static boolean DEBUG = true; +} \ No newline at end of file diff --git a/gen/uk/digitalsquid/netspoofer/R.java b/gen/uk/digitalsquid/netspoofer/R.java new file mode 100644 index 0000000..fa50102 --- /dev/null +++ b/gen/uk/digitalsquid/netspoofer/R.java @@ -0,0 +1,285 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package uk.digitalsquid.netspoofer; + +public final class R { + public static final class attr { + } + public static final class drawable { + public static final int bg=0x7f020000; + public static final int file=0x7f020001; + public static final int folder=0x7f020002; + public static final int icon=0x7f020003; + public static final int status=0x7f020004; + } + public static final class id { + public static final int TableRow01=0x7f080045; + public static final int TableRow02=0x7f080016; + public static final int TableRow03=0x7f080019; + public static final int TableRow04=0x7f08001c; + public static final int TableRow06=0x7f080022; + public static final int TableRow07=0x7f080025; + public static final int TableRow08=0x7f080028; + public static final int TextView01=0x7f08000f; + public static final int cancel=0x7f08003d; + public static final int checkbox=0x7f080058; + public static final int contactDev=0x7f08000c; + public static final int description=0x7f080050; + public static final int devsite=0x7f080005; + public static final int dlButton=0x7f080052; + public static final int dlProgress=0x7f08002b; + public static final int dlProgressBar=0x7f08002c; + public static final int dlStatus=0x7f080054; + public static final int dlprogress=0x7f080055; + public static final int dlprogresstext=0x7f080056; + public static final int fdButtonCancel=0x7f080035; + public static final int fdButtonCreate=0x7f080036; + public static final int fdButtonNew=0x7f080030; + public static final int fdButtonSelect=0x7f080031; + public static final int fdEditTextFile=0x7f080034; + public static final int fdLinearLayoutCreate=0x7f080032; + public static final int fdLinearLayoutList=0x7f08002e; + public static final int fdLinearLayoutSelect=0x7f08002f; + public static final int fdrowimage=0x7f080038; + public static final int fdrowtext=0x7f080039; + public static final int goback=0x7f08006a; + public static final int horizontalScrollView1=0x7f080002; + public static final int imageView1=0x7f080001; + public static final int ipBox=0x7f080011; + public static final int linearLayout1=0x7f080000; + public static final int linearLayout2=0x7f080009; + public static final int linearLayout3=0x7f08000b; + public static final int linearLayout4=0x7f080003; + public static final int loading=0x7f08003f; + public static final int logoutput=0x7f08005e; + public static final int logscroller=0x7f08005d; + public static final int myIf=0x7f080048; + public static final int myIfText=0x7f080049; + public static final int myIp=0x7f080043; + public static final int myIpText=0x7f080044; + public static final int netSpoofMenuItemAbout=0x7f080069; + public static final int netSpoofMenuItemPrefs=0x7f080068; + public static final int ok=0x7f08003e; + public static final int path=0x7f080037; + public static final int progress=0x7f08003a; + public static final int redlconfirm=0x7f080051; + public static final int refreshWeb=0x7f080053; + public static final int relativeLayout01=0x7f08002d; + public static final int reportBug=0x7f08000d; + public static final int routerDescription=0x7f08004d; + public static final int routerIp=0x7f080046; + public static final int routerIpText=0x7f080047; + public static final int routerList=0x7f08004e; + public static final int routerName=0x7f08004c; + public static final int scanProgressBar=0x7f080063; + public static final int scanProgressRefresh=0x7f080065; + public static final int scanProgressText=0x7f080064; + public static final int scrollView1=0x7f080008; + public static final int setupButton=0x7f080041; + public static final int sfWebView=0x7f080057; + public static final int spoofDescription=0x7f08005a; + public static final int spoofList=0x7f08005b; + public static final int spoofTitle=0x7f080059; + public static final int spoofWarning=0x7f08005f; + public static final int spoofstatus=0x7f08005c; + public static final int squidscripts=0x7f080007; + public static final int startButton=0x7f080040; + public static final int status=0x7f08003b; + public static final int subnetMask=0x7f08004a; + public static final int subnetMaskText=0x7f08004b; + public static final int tableLayout1=0x7f080012; + public static final int tableRow01=0x7f080013; + public static final int tableRow05=0x7f08001f; + public static final int tableRow1=0x7f080042; + public static final int text=0x7f08003c; + public static final int textFrom1=0x7f080014; + public static final int textFrom2=0x7f080017; + public static final int textFrom3=0x7f08001a; + public static final int textFrom4=0x7f08001d; + public static final int textFrom5=0x7f080020; + public static final int textFrom6=0x7f080023; + public static final int textFrom7=0x7f080026; + public static final int textFrom8=0x7f080029; + public static final int textTo1=0x7f080015; + public static final int textTo2=0x7f080018; + public static final int textTo3=0x7f08001b; + public static final int textTo4=0x7f08001e; + public static final int textTo5=0x7f080021; + public static final int textTo6=0x7f080024; + public static final int textTo7=0x7f080027; + public static final int textTo8=0x7f08002a; + public static final int textView1=0x7f08000a; + public static final int textView2=0x7f08000e; + public static final int textView3=0x7f080010; + public static final int textViewFilename=0x7f080033; + public static final int udternet=0x7f080006; + public static final int useLocalFile=0x7f080067; + public static final int victimExtraText=0x7f080061; + public static final int victimIp=0x7f080060; + public static final int victimList=0x7f080062; + public static final int web=0x7f080066; + public static final int website=0x7f080004; + public static final int wifiSettings=0x7f08004f; + } + public static final class layout { + public static final int about=0x7f030000; + public static final int agreement=0x7f030001; + public static final int changelog=0x7f030002; + public static final int customip=0x7f030003; + public static final int customtextdialog=0x7f030004; + public static final int dl_notification=0x7f030005; + public static final int file_dialog_main=0x7f030006; + public static final int file_dialog_row=0x7f030007; + public static final int iptextfield=0x7f030008; + public static final int listloadingitem=0x7f030009; + public static final int main=0x7f03000a; + public static final int otheripdialog=0x7f03000b; + public static final int routerlistitem=0x7f03000c; + public static final int routerselector=0x7f03000d; + public static final int setupstatus=0x7f03000e; + public static final int spoofitem=0x7f03000f; + public static final int spoofmultiselector=0x7f030010; + public static final int spoofrunning=0x7f030011; + public static final int spoofselector=0x7f030012; + public static final int victimlistitem=0x7f030013; + public static final int victimselector=0x7f030014; + public static final int youtube=0x7f030015; + } + public static final class menu { + public static final int dlscreen=0x7f070000; + public static final int netspoofmenu=0x7f070001; + public static final int youtube=0x7f070002; + } + public static final class raw { + public static final int applyupgrade=0x7f050000; + public static final int busybox=0x7f050001; + public static final int config=0x7f050002; + public static final int mount=0x7f050003; + public static final int start=0x7f050004; + public static final int umount=0x7f050005; + } + public static final class string { + public static final int about=0x7f06004a; + public static final int aboutText1=0x7f06004c; + public static final int aboutText2=0x7f06004d; + public static final int aboutTextRefs=0x7f060063; + public static final int advanced=0x7f060054; + public static final int agreementContents1=0x7f060001; + public static final int agreementContents2=0x7f060002; + public static final int agreementNegative=0x7f060004; + public static final int agreementPositive=0x7f060003; + public static final int agreementTitle=0x7f060000; + public static final int allDevices=0x7f06002d; + public static final int allDevicesDesc=0x7f06002e; + public static final int app_name=0x7f060012; + public static final int autoChooseRouter=0x7f060043; + public static final int autoChooseRouterDesc=0x7f060044; + public static final int autoChooseVictim=0x7f060045; + public static final int autoChooseVictimDesc=0x7f060046; + public static final int automaticOptions=0x7f060042; + public static final int blank=0x7f060025; + public static final int builtinbusybox=0x7f060064; + public static final int builtinbusyboxDesc=0x7f060065; + public static final int cancel=0x7f06000b; + public static final int cant_read_folder=0x7f060007; + public static final int changelog=0x7f060005; + public static final int chooseFile=0x7f060070; + public static final int configuring=0x7f06006a; + public static final int contactdev=0x7f06004f; + public static final int create=0x7f06000c; + public static final int customIpSettings=0x7f060029; + public static final int customText=0x7f060068; + public static final int customTextDesc=0x7f060069; + public static final int customwebsitedesc=0x7f06006c; + public static final int debImgUrl=0x7f060052; + public static final int debImgUrlDesc=0x7f060053; + public static final int debianImage=0x7f06005b; + public static final int debianImageDesc=0x7f06005c; + public static final int debianMount=0x7f060059; + public static final int debianMountDesc=0x7f06005a; + public static final int deviceIf=0x7f060028; + public static final int deviceIp=0x7f060026; + public static final int devsite=0x7f06004e; + public static final int dlCancel=0x7f060020; + public static final int dlStarted=0x7f06001b; + public static final int dlStarting=0x7f06001c; + public static final int dlnotrunning=0x7f06001a; + public static final int downloadUnzipped=0x7f06003c; + public static final int downloadUnzippedDesc=0x7f06003d; + public static final int downloading=0x7f060036; + public static final int downloadingfiles=0x7f060037; + public static final int ellipsis=0x7f06001f; + public static final int enterip=0x7f060032; + public static final int enteriptext=0x7f060033; + public static final int file_name=0x7f06000a; + public static final int gotosite=0x7f06004b; + public static final int gpl=0x7f060051; + public static final int iface=0x7f06005d; + public static final int ifaceDesc=0x7f06005e; + public static final int ipExample=0x7f060071; + public static final int ipScanThreads=0x7f060048; + public static final int ipScanThreadsDesc=0x7f060049; + public static final int loadfailed=0x7f060039; + public static final int loadfailedtitle=0x7f060038; + public static final int loading=0x7f060022; + public static final int location=0x7f060006; + public static final int lookingupSite=0x7f06006b; + public static final int loopDev=0x7f060055; + public static final int loopDevDesc=0x7f060056; + public static final int loopNum=0x7f060057; + public static final int loopNumDesc=0x7f060058; + public static final int nnew=0x7f060008; + public static final int no_data=0x7f06000d; + public static final int otherDevice=0x7f06002f; + public static final int otherDeviceDesc=0x7f060030; + public static final int output=0x7f060035; + public static final int pathToBB=0x7f06003f; + public static final int pathToBBDesc=0x7f060041; + public static final int pathToSu=0x7f06003e; + public static final int pathToSuDesc=0x7f060040; + public static final int performance=0x7f060047; + public static final int preferences=0x7f06003a; + public static final int programPrefs=0x7f06003b; + public static final int redownload=0x7f06001d; + public static final int redownloadnotify=0x7f06001e; + public static final int refresh=0x7f060031; + public static final int reportBug=0x7f060050; + public static final int returntoyt=0x7f060067; + public static final int routerIp=0x7f060027; + public static final int scanning=0x7f06002b; + public static final int select=0x7f060009; + public static final int selectgateway=0x7f060023; + public static final int selecthack=0x7f060021; + public static final int selectvictim=0x7f06002a; + public static final int selectvideo=0x7f060066; + public static final int setup=0x7f060013; + public static final int setupUpgrade=0x7f060018; + public static final int setup_upgrade=0x7f060014; + public static final int setup_upgrade2=0x7f060015; + public static final int setupt1=0x7f060017; + public static final int spoofRunning=0x7f06005f; + public static final int spoofRunningDesc=0x7f060060; + public static final int spoofnotrunning=0x7f06000e; + public static final int spoofstarted=0x7f060010; + public static final int spoofstarting=0x7f06000f; + public static final int spoofstopping=0x7f060011; + public static final int squidscripts=0x7f060062; + public static final int start=0x7f060016; + public static final int startdl=0x7f060019; + public static final int stop=0x7f060034; + public static final int subnet=0x7f06002c; + public static final int udternet=0x7f060061; + public static final int useLocalFile=0x7f06006f; + public static final int warningText=0x7f06006e; + public static final int warningTitle=0x7f06006d; + public static final int wifiSettings=0x7f060024; + } + public static final class xml { + public static final int preferences=0x7f040000; + } +} diff --git a/jni/Android.mk b/jni/Android.mk new file mode 100644 index 0000000..75143dc --- /dev/null +++ b/jni/Android.mk @@ -0,0 +1,8 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := netspooflib +LOCAL_SRC_FILES := uk_digitalsquid_netspoofer_JNI.c + +include $(BUILD_SHARED_LIBRARY) diff --git a/jni/uk_digitalsquid_netspoofer_JNI.c b/jni/uk_digitalsquid_netspoofer_JNI.c new file mode 100644 index 0000000..a75f855 --- /dev/null +++ b/jni/uk_digitalsquid_netspoofer_JNI.c @@ -0,0 +1,15 @@ +#include "uk_digitalsquid_netspoofer_JNI.h" + +#include + +#define EXEC_PERM ((S_IRUSR | S_IWUSR | S_IXUSR) | (S_IRGRP | S_IXGRP) | (S_IROTH | S_IXOTH)) /* 00755 */ + +JNIEXPORT jint JNICALL Java_uk_digitalsquid_netspoofer_JNI_setExecutable(JNIEnv *env, jobject obj, jstring path) { + jboolean iscopy; + const char *mpath = (*env)->GetStringUTFChars(env, path, &iscopy); + + chmod(mpath, EXEC_PERM); + + // Clean up + (*env)->ReleaseStringUTFChars(env, path, mpath); +} diff --git a/jni/uk_digitalsquid_netspoofer_JNI.h b/jni/uk_digitalsquid_netspoofer_JNI.h new file mode 100644 index 0000000..7108bce --- /dev/null +++ b/jni/uk_digitalsquid_netspoofer_JNI.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class uk_digitalsquid_netspoofer_JNI */ + +#ifndef _Included_uk_digitalsquid_netspoofer_JNI +#define _Included_uk_digitalsquid_netspoofer_JNI +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: uk_digitalsquid_netspoofer_JNI + * Method: setExecutable + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_uk_digitalsquid_netspoofer_JNI_setExecutable + (JNIEnv *, jobject, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libs/armeabi/libnetspooflib.so b/libs/armeabi/libnetspooflib.so new file mode 100755 index 0000000..5043a3f Binary files /dev/null and b/libs/armeabi/libnetspooflib.so differ diff --git a/netspoof icon.svg b/netspoof icon.svg new file mode 100644 index 0000000..d2425ac --- /dev/null +++ b/netspoof icon.svg @@ -0,0 +1,1125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/netspoof logo.svg b/netspoof logo.svg new file mode 100644 index 0000000..a8ef288 --- /dev/null +++ b/netspoof logo.svg @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proguard.cfg b/proguard.cfg new file mode 100644 index 0000000..4dc32b1 --- /dev/null +++ b/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembers class * { + native ; +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/project.properties b/project.properties new file mode 100644 index 0000000..ea89160 --- /dev/null +++ b/project.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "ant.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-8 diff --git a/res/drawable-hdpi-v9/status.png b/res/drawable-hdpi-v9/status.png new file mode 100644 index 0000000..ed9bfd0 Binary files /dev/null and b/res/drawable-hdpi-v9/status.png differ diff --git a/res/drawable-hdpi/bg.9.png b/res/drawable-hdpi/bg.9.png new file mode 100644 index 0000000..cfb8058 Binary files /dev/null and b/res/drawable-hdpi/bg.9.png differ diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png new file mode 100644 index 0000000..a2e6d71 Binary files /dev/null and b/res/drawable-hdpi/icon.png differ diff --git a/res/drawable-hdpi/status.png b/res/drawable-hdpi/status.png new file mode 100644 index 0000000..5188311 Binary files /dev/null and b/res/drawable-hdpi/status.png differ diff --git a/res/drawable-ldpi-v9/status.png b/res/drawable-ldpi-v9/status.png new file mode 100644 index 0000000..99a6b78 Binary files /dev/null and b/res/drawable-ldpi-v9/status.png differ diff --git a/res/drawable-ldpi/bg.9.png b/res/drawable-ldpi/bg.9.png new file mode 100644 index 0000000..397473c Binary files /dev/null and b/res/drawable-ldpi/bg.9.png differ diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png new file mode 100644 index 0000000..4ce8e3d Binary files /dev/null and b/res/drawable-ldpi/icon.png differ diff --git a/res/drawable-ldpi/status.png b/res/drawable-ldpi/status.png new file mode 100644 index 0000000..614e22f Binary files /dev/null and b/res/drawable-ldpi/status.png differ diff --git a/res/drawable-mdpi-v9/status.png b/res/drawable-mdpi-v9/status.png new file mode 100644 index 0000000..99bf3d7 Binary files /dev/null and b/res/drawable-mdpi-v9/status.png differ diff --git a/res/drawable-mdpi/bg.9.png b/res/drawable-mdpi/bg.9.png new file mode 100644 index 0000000..32bce3d Binary files /dev/null and b/res/drawable-mdpi/bg.9.png differ diff --git a/res/drawable-mdpi/icon.png b/res/drawable-mdpi/icon.png new file mode 100644 index 0000000..90cafdc Binary files /dev/null and b/res/drawable-mdpi/icon.png differ diff --git a/res/drawable-mdpi/status.png b/res/drawable-mdpi/status.png new file mode 100644 index 0000000..78f4e0a Binary files /dev/null and b/res/drawable-mdpi/status.png differ diff --git a/res/drawable-xhdpi/bg.9.png b/res/drawable-xhdpi/bg.9.png new file mode 100644 index 0000000..fddbcee Binary files /dev/null and b/res/drawable-xhdpi/bg.9.png differ diff --git a/res/drawable-xhdpi/icon.png b/res/drawable-xhdpi/icon.png new file mode 100644 index 0000000..d0bb99e Binary files /dev/null and b/res/drawable-xhdpi/icon.png differ diff --git a/res/drawable/file.png b/res/drawable/file.png new file mode 100644 index 0000000..fa45699 Binary files /dev/null and b/res/drawable/file.png differ diff --git a/res/drawable/folder.png b/res/drawable/folder.png new file mode 100644 index 0000000..0108ed9 Binary files /dev/null and b/res/drawable/folder.png differ diff --git a/res/layout/about.xml b/res/layout/about.xml new file mode 100644 index 0000000..9a615a9 --- /dev/null +++ b/res/layout/about.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/agreement.xml b/res/layout/agreement.xml new file mode 100644 index 0000000..f399f1c --- /dev/null +++ b/res/layout/agreement.xml @@ -0,0 +1,21 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/layout/changelog.xml b/res/layout/changelog.xml new file mode 100644 index 0000000..a3fde78 --- /dev/null +++ b/res/layout/changelog.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/customip.xml b/res/layout/customip.xml new file mode 100644 index 0000000..abb4b75 --- /dev/null +++ b/res/layout/customip.xml @@ -0,0 +1,37 @@ + + + + + + + + + diff --git a/res/layout/customtextdialog.xml b/res/layout/customtextdialog.xml new file mode 100644 index 0000000..ae3559b --- /dev/null +++ b/res/layout/customtextdialog.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/dl_notification.xml b/res/layout/dl_notification.xml new file mode 100644 index 0000000..002f5b1 --- /dev/null +++ b/res/layout/dl_notification.xml @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/res/layout/file_dialog_main.xml b/res/layout/file_dialog_main.xml new file mode 100644 index 0000000..c803522 --- /dev/null +++ b/res/layout/file_dialog_main.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/file_dialog_row.xml b/res/layout/file_dialog_row.xml new file mode 100644 index 0000000..18c8c62 --- /dev/null +++ b/res/layout/file_dialog_row.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/res/layout/iptextfield.xml b/res/layout/iptextfield.xml new file mode 100644 index 0000000..d5d3afe --- /dev/null +++ b/res/layout/iptextfield.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/res/layout/listloadingitem.xml b/res/layout/listloadingitem.xml new file mode 100644 index 0000000..f541f97 --- /dev/null +++ b/res/layout/listloadingitem.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/res/layout/main.xml b/res/layout/main.xml new file mode 100644 index 0000000..90e694a --- /dev/null +++ b/res/layout/main.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/otheripdialog.xml b/res/layout/otheripdialog.xml new file mode 100644 index 0000000..4dfb601 --- /dev/null +++ b/res/layout/otheripdialog.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/routerlistitem.xml b/res/layout/routerlistitem.xml new file mode 100644 index 0000000..da9ffa6 --- /dev/null +++ b/res/layout/routerlistitem.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/res/layout/routerselector.xml b/res/layout/routerselector.xml new file mode 100644 index 0000000..d358558 --- /dev/null +++ b/res/layout/routerselector.xml @@ -0,0 +1,30 @@ + + + + + + + + + diff --git a/res/layout/setupstatus.xml b/res/layout/setupstatus.xml new file mode 100644 index 0000000..ab50576 --- /dev/null +++ b/res/layout/setupstatus.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + diff --git a/res/layout/spoofitem.xml b/res/layout/spoofitem.xml new file mode 100644 index 0000000..2f237e3 --- /dev/null +++ b/res/layout/spoofitem.xml @@ -0,0 +1,36 @@ + + + + + + + + + + diff --git a/res/layout/spoofmultiselector.xml b/res/layout/spoofmultiselector.xml new file mode 100644 index 0000000..75b4df4 --- /dev/null +++ b/res/layout/spoofmultiselector.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/res/layout/spoofrunning.xml b/res/layout/spoofrunning.xml new file mode 100644 index 0000000..c1d43a4 --- /dev/null +++ b/res/layout/spoofrunning.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/spoofselector.xml b/res/layout/spoofselector.xml new file mode 100644 index 0000000..72de139 --- /dev/null +++ b/res/layout/spoofselector.xml @@ -0,0 +1,27 @@ + + + + + + diff --git a/res/layout/victimlistitem.xml b/res/layout/victimlistitem.xml new file mode 100644 index 0000000..e048d6c --- /dev/null +++ b/res/layout/victimlistitem.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/res/layout/victimselector.xml b/res/layout/victimselector.xml new file mode 100644 index 0000000..21b50a2 --- /dev/null +++ b/res/layout/victimselector.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + diff --git a/res/layout/youtube.xml b/res/layout/youtube.xml new file mode 100644 index 0000000..82c3783 --- /dev/null +++ b/res/layout/youtube.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/res/menu/dlscreen.xml b/res/menu/dlscreen.xml new file mode 100644 index 0000000..fcd580f --- /dev/null +++ b/res/menu/dlscreen.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/res/menu/netspoofmenu.xml b/res/menu/netspoofmenu.xml new file mode 100644 index 0000000..8367957 --- /dev/null +++ b/res/menu/netspoofmenu.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/res/menu/youtube.xml b/res/menu/youtube.xml new file mode 100644 index 0000000..8e93ef0 --- /dev/null +++ b/res/menu/youtube.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/res/raw/applyupgrade b/res/raw/applyupgrade new file mode 100644 index 0000000..fb3e1e8 --- /dev/null +++ b/res/raw/applyupgrade @@ -0,0 +1,39 @@ +#!/system/bin/sh +# This file is part of Network Spoofer for Android. +# Network Spoofer - change and mess with webpages and the internet on +# other people's computers +# Copyright (C) 2011 Will Shackleton +# +# Network Spoofer is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Network Spoofer is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Network Spoofer, in the file COPYING. +# If not, see . + +# First arg is always path to config file. +. $1 + +SRCDIR=$2 +DESTDIR=$3 + +# Copy all files into image +$BB cp -R $SRCDIR/* $DESTDIR + +SCRIPT="$DESTDIR/upgrade.sh" +if $BB [ -f $SCRIPT ] +then + echo "Upgrade script found, running" + $BB chmod a+x $SCRIPT + $BB chroot $DEB "/upgrade.sh" + $BB rm $SCRIPT +fi + +exit 0 \ No newline at end of file diff --git a/res/raw/busybox b/res/raw/busybox new file mode 100755 index 0000000..2405887 Binary files /dev/null and b/res/raw/busybox differ diff --git a/res/raw/config b/res/raw/config new file mode 100644 index 0000000..ef4585e --- /dev/null +++ b/res/raw/config @@ -0,0 +1 @@ +# Dummy config file \ No newline at end of file diff --git a/res/raw/mount b/res/raw/mount new file mode 100644 index 0000000..8a94e78 --- /dev/null +++ b/res/raw/mount @@ -0,0 +1,69 @@ +#!/system/bin/sh +# This file is part of Network Spoofer for Android. +# Network Spoofer - change and mess with webpages and the internet on +# other people's computers +# Copyright (C) 2011 Will Shackleton +# +# Network Spoofer is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Network Spoofer is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Network Spoofer, in the file COPYING. +# If not, see . + +# First arg is always path to config file. +. $1 + +set -x + +echo "Starting..." +echo "Busybox: $BB" +echo "Env:" +env + +echo 1 > /proc/sys/net/ipv4/ip_forward + +echo "INFO: Mount data" +$BB mount +# Create folder +# If no BB, then this will use builtins. +$BB mkdir -p $DEB || +( + # Can't create dir, remount rw then try again + echo "Couldn't create mount directory, trying to remount filesystems RW" + + # Try everything + $BB mount -o remount,rw /data/local + $BB mount -o remount,rw /data + $BB mount -o remount,rw / + + echo "INFO: New mount data" + $BB mount + + # Try again + $BB mkdir -p $DEB +) + +$BB ls -la $DEB + +echo "Loading FS from file $DEBIMG to loop $LOOPDEV ($LOOPNUM) at mountpoint $DEB" + +$BB mknod $LOOPDEV b 7 $LOOPNUM +$BB losetup $LOOPDEV $DEBIMG +$BB mount -o loop $LOOPDEV $DEB + +$BB mount -t devpts devpts $DEB/dev/pts +$BB mount -t proc proc $DEB/proc +$BB mount -t sysfs sysfs $DEB/sys + +# Debug +$BB ls -la $DEB +echo "Loop device:" +$BB ls -l $LOOPDEV diff --git a/res/raw/start b/res/raw/start new file mode 100644 index 0000000..33dfaa7 --- /dev/null +++ b/res/raw/start @@ -0,0 +1,32 @@ +#!/system/bin/sh +# This file is part of Network Spoofer for Android. +# Network Spoofer - change and mess with webpages and the internet on +# other people's computers +# Copyright (C) 2011 Will Shackleton +# +# Network Spoofer is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Network Spoofer is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Network Spoofer, in the file COPYING. +# If not, see . + +# First arg is always path to config file. +. $1 + +set -x +echo 1 > /proc/sys/net/ipv4/ip_forward + +# Get all args but first +shift + +echo "Starting spoof" +$BB chroot $DEB $@ +echo "Spoof done." diff --git a/res/raw/umount b/res/raw/umount new file mode 100644 index 0000000..b0a9096 --- /dev/null +++ b/res/raw/umount @@ -0,0 +1,39 @@ +#!/system/bin/sh +# This file is part of Network Spoofer for Android. +# Network Spoofer - change and mess with webpages and the internet on +# other people's computers +# Copyright (C) 2011 Will Shackleton +# +# Network Spoofer is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Network Spoofer is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Network Spoofer, in the file COPYING. +# If not, see . + +# First arg is always path to config file. +. $1 + +set -x + +echo "Closing environment" +# Debug +$BB ls -la $DEB + +$BB umount $DEB/dev/pts +$BB umount $DEB/proc +$BB umount $DEB/sys + +$BB umount $LOOPDEV +$BB losetup -d $LOOPDEV +$BB rm $LOOPDEV + +$BB ls -la $DEB +echo "Done." \ No newline at end of file diff --git a/res/values/dialogs.xml b/res/values/dialogs.xml new file mode 100644 index 0000000..21fd7aa --- /dev/null +++ b/res/values/dialogs.xml @@ -0,0 +1,21 @@ + + + Network Spoofer + I agree to only use Network Spoofer on residential and personal networks with the permission of the network owner. + + There is no intention for Network Spoofer to include any malicious features. + This application is a fun demonstration of how vulnerable home networks are to simple attacks, + with permission of the network owner - DO NOT attempt to use Network Spoofer on any corporate + or other non-residential networks (eg. at school, university). It becomes very obvious when + Network Spoofer is being used on a Network, and use of Network Spoofer will be considered + malicious hacking by network administrators. + + Agree + Exit + New in this release:\n + * Added installing of data from SD card\n + * Added much smaller upgrades (upgrading is now usually now a 0.1MB download)\n + * Added new spoof - Adblock + + + \ No newline at end of file diff --git a/res/values/filedialog.xml b/res/values/filedialog.xml new file mode 100644 index 0000000..817bd00 --- /dev/null +++ b/res/values/filedialog.xml @@ -0,0 +1,11 @@ + + + Location + folder can\'t be read! + New + Select + File name: + Cancel + Save + No Data + diff --git a/res/values/spoofrunning.xml b/res/values/spoofrunning.xml new file mode 100644 index 0000000..d87b534 --- /dev/null +++ b/res/values/spoofrunning.xml @@ -0,0 +1,28 @@ + + + + + Spoof not running + Starting… + Spoof running. Hide your phone to not look suspicious! + Stopping… This may take a while. + diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..d198dce --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,129 @@ + + + + + Network Spoofer + Setup & Install + Update available + Update available\nReinstall required + Start + Please press Start to begin downloading necessary files. This is quite a big download, so you may want to connect to Wifi first. + Press start to download the upgrade. This is a very small download and should only take a few seconds. + Start Download + Download currently not running. + Download Started + Download Starting + Redownload + The latest version is already installed. Are you sure you wish to redownload? + + Cancel download + Select Hack to use + Loading… + Select gateway + Change Wifi Settings + + My IP Address: + Router IP Address: + Wifi interface name:\n(usually eth0) + Custom IP Settings + Select Victim + Scanning for devices… + Subnet Mask: + All Devices + Run spoof on everything on the network. May slow down the phone a lot and cause the battery to melt. + Other + Enter an IP address of someone to spoof not seen in this list. + Refresh + Enter IP Address + Please enter a custom IP address / hostname of victim to attack. + Stop + Output: + Downloading Installation files… + Downloading files needed to run… + Oops! + Something went wrong whilst trying to load. Perhaps the SD card isn\'t plugged in, or you didn\'t accept the superuser command?\n\nCheck the log for more details. + Preferences + Programs + Download uncompressed installation files + Download the setup files uncompressed (larger download). Use if you are having problems with the extraction process. + Custom path to \'su\' command + Custom path to \'busybox\' command + Set a custom path to the superuser binary. Normally this is automatically detected. + Set a custom path to the busybox binary. Normally this is automatically detected. + Automatic choices + Choose router automatically + Automatically choose the default detected router, allowing you to skip one of the steps. + Choose victim automatically + Automatically chooses to run attack for everyone on the network. + Performance + IP scanners + The number of simultaneous threads for scanning the local network - can make the process faster + About + Go to website + Network Spoofer lets you change websites on other people’s computers from an Android phone. + DISCLAIMER: This application is not to be used for any purposes other than to demonstrate its functions, and must only be used on networks for which you have permission to do so. Any other use is not the responsibility of the developer.\nIn other words, don\'t be stupid, and don\'t direct angry people towards me. + Developer\'s site + Contact Developer + Report Bug + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + \nThis program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + \nYou should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + Custom URL for environment + Rather than download from SourceForge (recommended), use this URL to download the environment. + Advanced + Linux loop device + The loop device on which to mount the debian image. If the user has a lot of apps installed on the SD card, this may need changing. + Linux loop device number + The loop device number with which to create the loop device. If the user has a lot of apps installed on the SD card, this may need changing (higher is better). + Image mount location + A location on the phone\'s file system to mount the required image. + Debian image + Path to the debian image. Note that setting this to a non-blank value will require you to download the images manually. + Wifi interface + The Linux interface name of the adapter through which you will be running these spoofs. + Spoofer running + Network Spoofer is running. + Upside-down-ternet + Squid - \'playing with traffic\' + Many thanks to the developer of the \'upside-down-ternet\' (see above link) and the writer of \'playing with traffic\' (also above) for the inspiration for this project. + Use builtin Busybox + Use the version of Busybox distributed with Network Spoofer. Uncheck to use the phone\'s version. + Please Select a Youtube Video + Return to Youtube + Change page text + Enter custom text values to change. Blank fields are ignored. + Configuring… + Finding website… + Please enter a website to redirect to, not including http:// (eg. kittenwar.com). + Don\'t be evil! + Remember, only run Network Spoofer when you have permission to do so. Don\'t run at work, university, school etc. without the permission of your network administrators. + Use Local File + Select downloaded file + eg. 192.168.1.42 + diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml new file mode 100644 index 0000000..0cc0e09 --- /dev/null +++ b/res/xml/preferences.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/lamerman/FileDialog.java b/src/com/lamerman/FileDialog.java new file mode 100644 index 0000000..b527214 --- /dev/null +++ b/src/com/lamerman/FileDialog.java @@ -0,0 +1,298 @@ +package com.lamerman; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.TreeMap; + +import uk.digitalsquid.netspoofer.R; +import android.app.AlertDialog; +import android.app.ListActivity; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.TextView; + +/** + * See http://code.google.com/p/android-file-dialog/ for info about this library. + * @author william + * + */ +public class FileDialog extends ListActivity { + + private static final String ITEM_KEY = "key"; + private static final String ITEM_IMAGE = "image"; + private static final String ROOT = "/"; + + public static final String START_PATH = "START_PATH"; + public static final String RESULT_PATH = "RESULT_PATH"; + public static final String SELECTION_MODE = "SELECTION_MODE"; + + private List path = null; + private TextView myPath; + private EditText mFileName; + private ArrayList> mList; + + private Button selectButton; + + private LinearLayout layoutSelect; + private LinearLayout layoutCreate; + private InputMethodManager inputManager; + private String parentPath; + private String currentPath = ROOT; + + private int selectionMode = SelectionMode.MODE_CREATE; + + private File selectedFile; + private HashMap lastPositions = new HashMap(); + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setResult(RESULT_CANCELED, getIntent()); + + setContentView(R.layout.file_dialog_main); + myPath = (TextView) findViewById(R.id.path); + mFileName = (EditText) findViewById(R.id.fdEditTextFile); + + inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + + selectButton = (Button) findViewById(R.id.fdButtonSelect); + selectButton.setEnabled(false); + selectButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (selectedFile != null) { + getIntent().putExtra(RESULT_PATH, selectedFile.getPath()); + setResult(RESULT_OK, getIntent()); + finish(); + } + } + }); + + final Button newButton = (Button) findViewById(R.id.fdButtonNew); + newButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + setCreateVisible(v); + + mFileName.setText(""); + mFileName.requestFocus(); + } + }); + + selectionMode = getIntent().getIntExtra(SELECTION_MODE, + SelectionMode.MODE_CREATE); + if (selectionMode == SelectionMode.MODE_OPEN) { + newButton.setEnabled(false); + } + + layoutSelect = (LinearLayout) findViewById(R.id.fdLinearLayoutSelect); + layoutCreate = (LinearLayout) findViewById(R.id.fdLinearLayoutCreate); + layoutCreate.setVisibility(View.GONE); + + final Button cancelButton = (Button) findViewById(R.id.fdButtonCancel); + cancelButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + setSelectVisible(v); + } + + }); + final Button createButton = (Button) findViewById(R.id.fdButtonCreate); + createButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (mFileName.getText().length() > 0) { + getIntent().putExtra(RESULT_PATH, + currentPath + "/" + mFileName.getText()); + setResult(RESULT_OK, getIntent()); + finish(); + } + } + }); + + String startPath = getIntent().getStringExtra(START_PATH); + if (startPath != null) { + getDir(startPath); + } else { + getDir(ROOT); + } + } + + private void getDir(String dirPath) { + + boolean useAutoSelection = dirPath.length() < currentPath.length(); + + Integer position = lastPositions.get(parentPath); + + getDirImpl(dirPath); + + if (position != null && useAutoSelection) { + getListView().setSelection(position); + } + + } + + private void getDirImpl(final String dirPath) { + + currentPath = dirPath; + + final List item = new ArrayList(); + path = new ArrayList(); + mList = new ArrayList>(); + + File f = new File(currentPath); + File[] files = f.listFiles(); + if (files == null) { + currentPath = ROOT; + f = new File(currentPath); + files = f.listFiles(); + } + myPath.setText(getText(R.string.location) + ": " + currentPath); + + if (!currentPath.equals(ROOT)) { + + item.add(ROOT); + addItem(ROOT, R.drawable.folder); + path.add(ROOT); + + item.add("../"); + addItem("../", R.drawable.folder); + path.add(f.getParent()); + parentPath = f.getParent(); + + } + + TreeMap dirsMap = new TreeMap(); + TreeMap dirsPathMap = new TreeMap(); + TreeMap filesMap = new TreeMap(); + TreeMap filesPathMap = new TreeMap(); + for (File file : files) { + if (file.isDirectory()) { + String dirName = file.getName(); + dirsMap.put(dirName, dirName); + dirsPathMap.put(dirName, file.getPath()); + } else { + filesMap.put(file.getName(), file.getName()); + filesPathMap.put(file.getName(), file.getPath()); + } + } + item.addAll(dirsMap.tailMap("").values()); + item.addAll(filesMap.tailMap("").values()); + path.addAll(dirsPathMap.tailMap("").values()); + path.addAll(filesPathMap.tailMap("").values()); + + SimpleAdapter fileList = new SimpleAdapter(this, mList, + R.layout.file_dialog_row, + new String[] { ITEM_KEY, ITEM_IMAGE }, new int[] { + R.id.fdrowtext, R.id.fdrowimage }); + + for (String dir : dirsMap.tailMap("").values()) { + addItem(dir, R.drawable.folder); + } + + for (String file : filesMap.tailMap("").values()) { + addItem(file, R.drawable.file); + } + + fileList.notifyDataSetChanged(); + + setListAdapter(fileList); + + } + + private void addItem(String fileName, int imageId) { + HashMap item = new HashMap(); + item.put(ITEM_KEY, fileName); + item.put(ITEM_IMAGE, imageId); + mList.add(item); + } + + @Override + protected void onListItemClick(ListView l, View v, int position, long id) { + + File file = new File(path.get(position)); + + setSelectVisible(v); + + if (file.isDirectory()) { + selectButton.setEnabled(false); + if (file.canRead()) { + lastPositions.put(currentPath, position); + getDir(path.get(position)); + } else { + new AlertDialog.Builder(this) + .setIcon(R.drawable.icon) + .setTitle( + "[" + file.getName() + "] " + + getText(R.string.cant_read_folder)) + .setPositiveButton("OK", + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, + int which) { + + } + }).show(); + } + } else { + selectedFile = file; + v.setSelected(true); + selectButton.setEnabled(true); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if ((keyCode == KeyEvent.KEYCODE_BACK)) { + selectButton.setEnabled(false); + + if (layoutCreate.getVisibility() == View.VISIBLE) { + layoutCreate.setVisibility(View.GONE); + layoutSelect.setVisibility(View.VISIBLE); + } else { + if (!currentPath.equals(ROOT)) { + getDir(parentPath); + } else { + return super.onKeyDown(keyCode, event); + } + } + + return true; + } else { + return super.onKeyDown(keyCode, event); + } + } + + private void setCreateVisible(View v) { + layoutCreate.setVisibility(View.VISIBLE); + layoutSelect.setVisibility(View.GONE); + + inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); + selectButton.setEnabled(false); + } + + private void setSelectVisible(View v) { + layoutCreate.setVisibility(View.GONE); + layoutSelect.setVisibility(View.VISIBLE); + + inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); + selectButton.setEnabled(false); + } +} \ No newline at end of file diff --git a/src/com/lamerman/SelectionMode.java b/src/com/lamerman/SelectionMode.java new file mode 100644 index 0000000..3c05dfa --- /dev/null +++ b/src/com/lamerman/SelectionMode.java @@ -0,0 +1,7 @@ +package com.lamerman; + +public class SelectionMode { + public static final int MODE_CREATE = 0; + + public static final int MODE_OPEN = 1; +} diff --git a/src/uk/digitalsquid/netspoofer/About.java b/src/uk/digitalsquid/netspoofer/About.java new file mode 100644 index 0000000..ebe69ac --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/About.java @@ -0,0 +1,75 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; + +public class About extends Activity implements OnClickListener { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.about); + + findViewById(R.id.website).setOnClickListener(this); + findViewById(R.id.devsite).setOnClickListener(this); + findViewById(R.id.contactDev).setOnClickListener(this); + findViewById(R.id.reportBug).setOnClickListener(this); + findViewById(R.id.udternet).setOnClickListener(this); + findViewById(R.id.squidscripts).setOnClickListener(this); + } + + @Override + public void onClick(View v) { + Intent intent; + switch(v.getId()) { + case R.id.website: + intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://digitalsquid.co.uk/netspoof")); + startActivity(intent); + break; + case R.id.devsite: + intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://digitalsquid.co.uk/")); + startActivity(intent); + break; + case R.id.contactDev: + intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://digitalsquid.co.uk/contact")); + startActivity(intent); + break; + case R.id.reportBug: + intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://bugs.launchpad.net/android-netspoof")); + startActivity(intent); + break; + case R.id.udternet: + intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.ex-parrot.com/pete/upside-down-ternet.html")); + startActivity(intent); + break; + case R.id.squidscripts: + intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://g0tmi1k.blogspot.com/2011/04/video-playing-with-traffic-squid.html")); + startActivity(intent); + break; + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/InstallService.java b/src/uk/digitalsquid/netspoofer/InstallService.java new file mode 100644 index 0000000..1194500 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/InstallService.java @@ -0,0 +1,521 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.concurrent.CancellationException; +import java.util.zip.GZIPInputStream; + +import uk.digitalsquid.netspoofer.config.Config; +import uk.digitalsquid.netspoofer.config.ConfigChecker; +import uk.digitalsquid.netspoofer.config.IOHelpers; +import uk.digitalsquid.netspoofer.config.UpgradeInstaller; +import uk.digitalsquid.netspoofer.misc.AsyncTaskHelper; +import uk.digitalsquid.netspoofer.misc.UnZip; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.IBinder; +import android.util.Log; +import android.widget.RemoteViews; + +public class InstallService extends Service implements Config { + public static final String INTENT_EXTRA_STATUS = "uk.digitalsquid.netspoofer.InstallService.status"; + public static final String INTENT_EXTRA_DLPROGRESS = "uk.digitalsquid.netspoofer.InstallService.dlprogress"; + public static final String INTENT_EXTRA_DLSTATE = "uk.digitalsquid.netspoofer.InstallService.dlprogress"; + public static final String INTENT_STATUSUPDATE = "uk.digitalsquid.netspoofer.config.ConfigChecker.StatusUpdate"; + public static final String INTENT_START_URL = "uk.digitalsquid.netspoofer.config.InstallStatus.URL"; + /** + * When a file is given as the URL, pass true to this extra. + */ + public static final String INTENT_START_FILE = "uk.digitalsquid.netspoofer.config.InstallStatus.isFile"; + public static final String INTENT_START_URL_UNZIPPED = "uk.digitalsquid.netspoofer.config.InstallStatus.URLUnzipped"; + public static final String INTENT_START_URL_UPGRADE = "uk.digitalsquid.netspoofer.config.InstallStatus.isUpgrade"; + public static final int STATUS_STARTED = 0; + public static final int STATUS_DOWNLOADING = 1; + public static final int STATUS_FINISHED = 2; + + public static final int STATUS_DL_SUCCESS = 0; + public static final int STATUS_DL_FAIL_MALFORMED_FILE = 1; + public static final int STATUS_DL_FAIL_IOERROR = 2; + public static final int STATUS_DL_FAIL_SDERROR = 3; + public static final int STATUS_DL_FAIL_DLERROR = 4; + public static final int STATUS_UPGRADE_ERROR = 5; + public static final int STATUS_DL_CANCEL = 6; + + private static final int DL_NOTIFY = 1; + + private int status = STATUS_STARTED; + private int dlstatus = STATUS_DL_SUCCESS; + + private NotificationManager notificationManager; + private Notification notification; + + boolean started = false; + + @Override + public IBinder onBind(Intent intent) { + return null; + } + @Override + public void onStart(Intent intent, int startId) { + if(!started) start(intent); + broadcastStatus(); + } + + @Override + public int onStartCommand (Intent intent, int flags, int startId) { + if(!started) start(intent); + broadcastStatus(); + return START_REDELIVER_INTENT; + } + + private void start(Intent intent) { + notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + + notification = new Notification(R.drawable.status, getString(R.string.downloading), System.currentTimeMillis()); + RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.dl_notification); + notification.contentView = contentView; + notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT; + + Intent notificationIntent = new Intent(this, InstallService.class); + PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); + notification.contentIntent = contentIntent; + + notificationManager.notify(DL_NOTIFY, notification); + + started = true; + // SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + // String downloadUrl = prefs.getString("debImgUrl", DEB_IMG_URL); + String downloadUrl = intent.getStringExtra(INTENT_START_URL); + boolean downloadUnzipped = intent.getBooleanExtra(INTENT_START_URL_UNZIPPED, false); + boolean isUpgrade = intent.getBooleanExtra(INTENT_START_URL_UPGRADE, false); + boolean useLocalFile = intent.getBooleanExtra(INTENT_START_FILE, false); + if(downloadUrl == null) throw new IllegalArgumentException("Start URL was null"); + Log.v(TAG, "Downloading file " + downloadUrl); + // if(downloadUrl.equals("")) downloadUrl = DEB_IMG_URL; + AsyncTaskHelper.execute(downloadTask, new DlStartData(downloadUrl, downloadUnzipped, isUpgrade, useLocalFile)); + } + + /** + * Information about the download to start + * @author william + * + */ + private static class DlStartData implements Serializable { + private static final long serialVersionUID = 6287320665354658386L; + public final String url; + public final boolean unzipped; + /** + * When true, indicates an incremental upgrade (ie. a patch). + */ + public final boolean upgrade; + public final boolean useLocalFile; + + + public DlStartData(String url, boolean unzipped, boolean isUpgrade, boolean useLocal) { + this.url = url; + this.unzipped = unzipped; + this.upgrade = isUpgrade; + useLocalFile = useLocal; + } + } + + private DLProgress dlProgress = new DLProgress(0, 1024); + + private void broadcastStatus() { + Intent intent = new Intent(INTENT_STATUSUPDATE); + intent.putExtra(INTENT_EXTRA_STATUS, status); + switch(status) { + case STATUS_STARTED: + break; + case STATUS_DOWNLOADING: + intent.putExtra(INTENT_EXTRA_DLPROGRESS, dlProgress); + break; + case STATUS_FINISHED: + intent.putExtra(INTENT_EXTRA_DLSTATE, dlstatus); + break; + } + sendBroadcast(intent); + } + + @Override + public void onDestroy() { + notificationManager.cancel(DL_NOTIFY); + downloadTask.cancel(false); + } + + public static final class DLProgress implements Serializable { + private static final long serialVersionUID = -5366348392979726959L; + + public static final int STATUS_DOWNLOADING = 1; + public static final int STATUS_EXTRACTING = 2; + public static final int STATUS_PATCHING = 3; + public static final int STATUS_RECOVERING = 4; + + private final int status; + + public DLProgress(int bytesDone, int bytesTotal) { + this.bytesDone = bytesDone; + this.bytesTotal = bytesTotal; + status = STATUS_DOWNLOADING; + } + public DLProgress(int status, int bytesDone, int bytesTotal) { + this.bytesDone = bytesDone; + this.bytesTotal = bytesTotal; + this.status = status; + } + + public int getBytesDone() { + return bytesDone; + } + public int getBytesTotal() { + return bytesTotal; + } + public void setBytesDone(int bytes) { + bytesDone = bytes; + } + public void setBytesTotal(int bytes) { + bytesTotal = bytes; + } + public int getKBytesDone() { + return bytesDone / 1024; + } + public int getKBytesTotal() { + return bytesTotal / 1024; + } + public int getStatus() { + return status; + } + private int bytesDone, bytesTotal; + } + + public static interface DLProgressPublisher { + public void publishDLProgress(DLProgress progress); + } + + public final DownloadTask downloadTask = new DownloadTask(); + + /** + * Task to download and extract data. This should be split up into more modular sections at some point. + */ + private final class DownloadTask extends AsyncTask implements DLProgressPublisher { + private InputStream response; + private URLConnection connection; + + private File sd; + /** + * This is the destination to download to. In the case of an upgrade, it is the upgrade file. + */ + private File dlDestination; + + private URL downloadURL; + private FileOutputStream dlWriter; + + public void publishDLProgress(DLProgress progress) { + publishProgress(progress); + } + + @Override + protected Integer doInBackground(DlStartData... params) { + if(params.length != 1) throw new IllegalArgumentException("Please specify 1 parameter"); + boolean downloadUnzipped = params[0].unzipped; + boolean useLocalFile = params[0].useLocalFile; + final boolean upgrade = params[0].upgrade; + boolean writeOldVersion = false; + if(upgrade) { // Never use local file when upgrading, and don't extract + useLocalFile = false; + downloadUnzipped = true; + } + sd = getExternalFilesDir(null); + + if(upgrade) { + dlDestination = new File(getFilesDir() + "/" + "upgrade.zip"); + } else if(downloadUnzipped) { + dlDestination = new File(sd.getAbsolutePath() + "/" + DEB_IMG); // Save directly to new location + } else { + dlDestination = new File(sd.getAbsolutePath() + "/" + DEB_IMG_GZ); + } + try { + dlDestination.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + return STATUS_DL_FAIL_SDERROR; + } + + // Delete version file + final int oldVersionNumber = ConfigChecker.getVersionNumber(getBaseContext()); + File oldversion = new File(sd.getAbsolutePath() + "/" + DEB_VERSION_FILE); + oldversion.delete(); + + boolean done = true; + if(!useLocalFile) { + try { + dlWriter = new FileOutputStream(dlDestination); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + try { + downloadURL = new URL(params[0].url); + } catch (MalformedURLException e) { + e.printStackTrace(); + return STATUS_DL_FAIL_MALFORMED_FILE; + } + + int fileSize = 0; + try { + HttpURLConnection.setFollowRedirects(true); + connection = downloadURL.openConnection(); + connection.connect(); + fileSize = connection.getContentLength(); + Log.i(TAG, String.format("Downloading %d bytes of %s from %s", fileSize, connection.getContentType(), downloadURL)); + } catch (IOException e1) { + e1.printStackTrace(); + } + + int downloaded = 0; + + while(downloaded < fileSize) { + if(isCancelled()) { + done = false; + break; + } + try { + downloaded += tryDownload(downloaded, fileSize); + } catch (CancellationException e) { + done = false; + break; + } catch (IOException e) { + e.printStackTrace(); + Log.w(TAG, "Download failed, trying to continue..."); + try { Thread.sleep(300); } catch (InterruptedException e1) { } + } + } + + try { + dlWriter.close(); + if(response != null) response.close(); // Could be nothing that was downloaded + } catch (IOException e) { + } + } else { // Use local + File localFile = new File(params[0].url); + if(!localFile.exists()) return STATUS_DL_FAIL_IOERROR; + if(!localFile.renameTo(dlDestination)) return STATUS_DL_FAIL_SDERROR; + } + + if(!downloadUnzipped) { // Don't bother extracting + try { + unzip(dlDestination); + } catch (IOException e1) { + e1.printStackTrace(); + done = false; + } + } + + if(upgrade) { // Perform zip based upgrade + File destDir = new File(sd, "upgrade"); + if(destDir.exists()) IOHelpers.deleteFolder(destDir); + DLProgress progress = new DLProgress(DLProgress.STATUS_EXTRACTING, 0, 1); + publishProgress(progress); + destDir.mkdir(); + try { + if(!UnZip.unzipArchive(dlDestination, destDir)) + throw new IOException("Failed to extract"); + UpgradeInstaller.copyUpgrade(getBaseContext(), this, destDir); + } catch (IOException e) { + e.printStackTrace(); + done = false; + writeOldVersion = true; + } + } + + if(done) { + File version = new File(sd.getAbsolutePath() + "/" + DEB_VERSION_FILE); + try { + version.createNewFile(); // Make sure exists + } catch (IOException e) { + e.printStackTrace(); + } + try { + FileOutputStream versionWriter = new FileOutputStream(version); + versionWriter.write(("" + Config.DEB_IMG_URL_VERSION).getBytes()); + versionWriter.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + Log.e(TAG, "Couldn't write version file"); + } + } + if(writeOldVersion) { + File version = new File(sd.getAbsolutePath() + "/" + DEB_VERSION_FILE); + try { + version.createNewFile(); // Make sure exists + } catch (IOException e) { + e.printStackTrace(); + } + try { + FileOutputStream versionWriter = new FileOutputStream(version); + versionWriter.write(("" + oldVersionNumber).getBytes()); + versionWriter.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + Log.e(TAG, "Couldn't write version file"); + } + } + + Log.i(TAG, "Finished download"); + if(done) return STATUS_DL_SUCCESS; + if(upgrade) return STATUS_UPGRADE_ERROR; + return STATUS_DL_FAIL_IOERROR; + } + + /** + * Tries to download part of the file + * @return the number of bytes downloaded + */ + private int tryDownload(final int bytesSoFar, final int totalBytes) throws IOException, CancellationException { + connection = downloadURL.openConnection(); + connection.setRequestProperty("Range", "bytes=" + bytesSoFar + "-"); + connection.connect(); + response = new BufferedInputStream(connection.getInputStream()); + + byte[] dlData = new byte[0x8000]; + int bytesRead = 0; + int bytesDone = 0; + DLProgress progress = new DLProgress(bytesSoFar, totalBytes); + + int i = 0; + try { + while((bytesRead = response.read(dlData)) != -1) { + bytesDone += bytesRead; + dlWriter.write(dlData, 0, bytesRead); + if(i++ > 6) { + i = 0; + progress.setBytesDone(bytesDone + bytesSoFar); + publishProgress(progress); + } + + if(isCancelled()) { + response.close(); + dlWriter.close(); + // Remove old files + File delversion = new File(sd.getAbsolutePath() + "/" + DEB_VERSION_FILE); + delversion.delete(); + File deldebian = new File(sd.getAbsolutePath() + "/" + DEB_IMG_GZ); + deldebian.delete(); + throw new CancellationException(); + } + } + } catch (IOException e) { + e.printStackTrace(); + try { + response.close(); // Simply close, return number written. + } catch (IOException e1) { + e1.printStackTrace(); + } + } + return bytesDone; + } + + private String unzip(File inFile) throws IOException + { + InputStream gzipInputStream = new BufferedInputStream(new GZIPInputStream(new FileInputStream(inFile))); + + DLProgress progress = new DLProgress(DLProgress.STATUS_EXTRACTING, 0, Config.DEB_IMG_URL_SIZE); + + String outFilePath = inFile.getAbsolutePath().replace(".gz", ""); + OutputStream out = new FileOutputStream(outFilePath); + + byte[] buf = new byte[0x8000]; + int len, total = 0; + int i = 0; + while ((len = gzipInputStream.read(buf)) > 0) { + total += len; + out.write(buf, 0, len); + if(i++ > 60) { + i = 0; + progress.setBytesDone(total); + publishProgress(progress); + } + } + + gzipInputStream.close(); + out.close(); + + inFile.delete(); + + return outFilePath; + } + + int statusUpdate = 0; + protected void onProgressUpdate(DLProgress... progress) { + status = STATUS_DOWNLOADING; + dlProgress = progress[0]; + if(statusUpdate++ > 71) { + statusUpdate = 0; + notification.contentView.setProgressBar(R.id.dlProgressBar, dlProgress.bytesTotal, dlProgress.bytesDone, false); + notificationManager.notify(DL_NOTIFY, notification); + } + broadcastStatus(); + } + protected void onPostExecute(Integer result) { + status = STATUS_FINISHED; + dlstatus = result; + broadcastStatus(); + onFinish(); + } + + @Override + protected void onCancelled() { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + } + }; + + void onFinish() { + stopSelf(); + } +} diff --git a/src/uk/digitalsquid/netspoofer/InstallStatus.java b/src/uk/digitalsquid/netspoofer/InstallStatus.java new file mode 100644 index 0000000..542d581 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/InstallStatus.java @@ -0,0 +1,355 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.util.LinkedList; +import java.util.List; + +import uk.digitalsquid.netspoofer.InstallService.DLProgress; +import uk.digitalsquid.netspoofer.NetSpoof.LoadResult; +import uk.digitalsquid.netspoofer.config.Config; +import uk.digitalsquid.netspoofer.config.ConfigChecker; +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.Environment; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.Button; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.lamerman.FileDialog; + +public class InstallStatus extends Activity implements OnClickListener, Config { + private Button dlButton; + + public static final String EXTRA_DL_INFO = "uk.digitalsquid.netspoofer.InstallStatus.DlInfo"; + + /** + * When true, this is put in upgrade mode, ie. downloading a patch, not reinstalling + */ + boolean upgrading; + LoadResult loadResult; + + private ProgressBar dlProgress; + + private WebView webView; + + TextView status, dlProgressText, description; + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.setupstatus); + + statusFilter = new IntentFilter(); + statusFilter.addAction(InstallService.INTENT_STATUSUPDATE); + + LoadResult loadResult = (LoadResult) getIntent().getSerializableExtra(EXTRA_DL_INFO); + this.loadResult = loadResult; + upgrading = loadResult == null ? false : loadResult.doUpgrade; + + webView = (WebView)findViewById(R.id.sfWebView); + + status = (TextView) findViewById(R.id.dlStatus); + description = (TextView) findViewById(R.id.description); + if(upgrading) description.setText(R.string.setupUpgrade); + dlProgressText = (TextView) findViewById(R.id.dlprogresstext); + dlProgress = (ProgressBar) findViewById(R.id.dlprogress); + dlButton = (Button) findViewById(R.id.dlButton); + dlButton.setOnClickListener(this); + if(ConfigChecker.isInstallServiceRunning(getApplicationContext())) { + setWinStatus(true); + } else { // Things for not running + if(ConfigChecker.checkInstalledLatest(getApplicationContext())) { + findViewById(R.id.redlconfirm).setVisibility(View.VISIBLE); + dlButton.setText(R.string.redownload); + } + } + } + + private final List possibleSfURLs = new LinkedList(); + + /** + * Ativates the WebView with the default download URL + */ + private void activateSFWV() { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + // If user wants to download larger file + downloadUnzipped = prefs.getBoolean("downloadUnzipped", false); + if(downloadUnzipped) + activateSFWV(SF_DEB_IMG_URL_NOZIP); + else + activateSFWV(SF_DEB_IMG_URL); + } + + /** + * Activates the WebView used to get the DL url from sourceforge, if needed. + */ + private void activateSFWV(String url) { + final WebViewClient wvc = new WebViewClient() { + @Override + public void onLoadResource(WebView view, String url) { + // Note to self: check this every now and then, as SF may change a bit once in a while. + if(url.startsWith("http://downloads.sourceforge.net/project/netspoof/debian-images/debian") || + url.startsWith("http://downloads.sourceforge.net/project/netspoof/update")) { + Log.i(TAG, "Found SF DL URL: " + url); + if(!ConfigChecker.isInstallServiceRunning(getApplicationContext())) { + startServiceForUrl(loadResult.doUpgrade, url); + } + else possibleSfURLs.add(url); + } + } + }; + webView.setVisibility(View.VISIBLE); + findViewById(R.id.refreshWeb).setVisibility(View.VISIBLE); + findViewById(R.id.refreshWeb).setOnClickListener(this); + webView.setWebViewClient(wvc); + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setBuiltInZoomControls(true); + + webView.loadUrl(url); + } + + private boolean downloadUnzipped; + + private void startServiceForUrl(boolean upgrade, String url) { + Intent intent = new Intent(getApplicationContext(), InstallService.class); + intent.putExtra(InstallService.INTENT_START_URL, url); + intent.putExtra(InstallService.INTENT_START_URL_UNZIPPED, downloadUnzipped); + intent.putExtra(InstallService.INTENT_START_URL_UPGRADE, upgrade); + startService(intent); + status.setText(R.string.dlStarting); + dlButton.setText(R.string.dlCancel); + } + + @Override + public void onClick(View v) { + switch(v.getId()) { + case R.id.dlButton: + if(!ConfigChecker.isInstallServiceRunning(getApplicationContext())) { + if(!upgrading) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + String downloadUrl = prefs.getString("debImgUrl", ""); + if(!downloadUrl.equals("")) { + startServiceForUrl(false, downloadUrl); + } else activateSFWV(); + } else { + if(isSourceforgeUrl(loadResult.upgradeUrl)) + activateSFWV(loadResult.upgradeUrl); + else + startServiceForUrl(true, loadResult.upgradeUrl); + } + } else { + stopService(new Intent(getApplicationContext(), InstallService.class)); + findViewById(R.id.sfWebView).setVisibility(View.GONE); + setWinStatus(false); + } + break; + case R.id.refreshWeb: + webView.reload(); + break; + } + } + + /** + * Determines if a URL is a sourceforge one. + * @param url + * @return + */ + private boolean isSourceforgeUrl(String url) { + return url.toLowerCase().contains("sourceforge"); + } + + private IntentFilter statusFilter; + private final BroadcastReceiver statusReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + switch(intent.getIntExtra(InstallService.INTENT_EXTRA_STATUS, InstallService.STATUS_FINISHED)) { + case InstallService.STATUS_STARTED: + setWinStatus(true); + break; + case InstallService.STATUS_DOWNLOADING: + DLProgress progress = (DLProgress) intent.getSerializableExtra(InstallService.INTENT_EXTRA_DLPROGRESS); + if(progress == null) + Log.w(TAG, "Error in receiving download status"); + else { + dlProgress.setMax(progress.getKBytesTotal()); + dlProgress.setProgress(progress.getKBytesDone()); + float mbDone = (float)progress.getKBytesDone() / 1024; + float mbTotal = (float)progress.getKBytesTotal() / 1024; + switch(progress.getStatus()) { + case DLProgress.STATUS_DOWNLOADING: + dlProgressText.setText(String.format("%.1f / %.0fMB\nDownloading", mbDone, mbTotal)); + break; + case DLProgress.STATUS_EXTRACTING: + dlProgressText.setText(String.format("%.1f / %.0fMB\nExtracting", mbDone, mbTotal)); + break; + case DLProgress.STATUS_PATCHING: + if(mbTotal != 0) dlProgressText.setText(String.format("%.1f / %.0fMB\nUpgrading", mbDone, mbTotal)); + else dlProgressText.setText("Upgrading"); + break; + case DLProgress.STATUS_RECOVERING: + dlProgressText.setText(String.format("%.1f / %.0fMB\nRecovering from failed upgrade", mbDone, mbTotal)); + break; + } + } + break; + case InstallService.STATUS_FINISHED: + switch(intent.getIntExtra(InstallService.INTENT_EXTRA_DLSTATE, InstallService.STATUS_DL_FAIL_DLERROR)) { + case InstallService.STATUS_DL_FAIL_DLERROR: + Toast.makeText( + InstallStatus.this, + "An error ocurred whilst downloading the file. Please try again", + Toast.LENGTH_LONG).show(); + break; + case InstallService.STATUS_DL_FAIL_IOERROR: + Toast.makeText( + InstallStatus.this, + "Couldn't download file. Are you connected to the internet?", + Toast.LENGTH_LONG).show(); + break; + case InstallService.STATUS_DL_FAIL_MALFORMED_FILE: + Toast.makeText( + InstallStatus.this, + "Couldn't locate download file. Please check download URL, or please report this as a bug.", + Toast.LENGTH_LONG).show(); + break; + case InstallService.STATUS_DL_FAIL_SDERROR: + Toast.makeText( + InstallStatus.this, + "Couldn't open file for writing on SD card", + Toast.LENGTH_LONG).show(); + break; + case InstallService.STATUS_UPGRADE_ERROR: + Toast.makeText( + InstallStatus.this, + "An error occured while upgrading.", + Toast.LENGTH_LONG).show(); + break; + case InstallService.STATUS_DL_SUCCESS: + finish(); + break; + case InstallService.STATUS_DL_CANCEL: + Toast.makeText( + InstallStatus.this, + "Cancelled", + Toast.LENGTH_LONG).show(); + break; + } + if(possibleSfURLs.isEmpty()) { // Don't do anything + findViewById(R.id.sfWebView).setVisibility(View.GONE); + setWinStatus(false); + } + break; + } + } + }; + + @Override + protected void onResume() { + registerReceiver(statusReceiver, statusFilter); + super.onResume(); + } + + @Override + protected void onPause() { + unregisterReceiver(statusReceiver); + super.onPause(); + } + + private void setWinStatus(boolean running) { + if(running) { + dlButton.setText(R.string.dlCancel); + status.setText(R.string.dlStarted); + dlProgress.setVisibility(View.VISIBLE); + dlProgressText.setVisibility(View.VISIBLE); + dlButton.setEnabled(true); + } else { + dlButton.setText(R.string.startdl); + status.setText(R.string.dlnotrunning); + dlProgress.setVisibility(View.GONE); + dlProgressText.setVisibility(View.GONE); + dlButton.setEnabled(true); + if(ConfigChecker.checkInstalledLatest(getApplicationContext())) { + dlButton.setText(R.string.redownload); + } else { + dlButton.setText(R.string.startdl); + } + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.dlscreen, menu); + return true; + } + + static final int REQUEST_GETFILE = 1; + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.useLocalFile: + Intent intent = new Intent(this, FileDialog.class); + intent.putExtra(FileDialog.START_PATH, Environment.getExternalStorageDirectory().getPath()); + startActivityForResult(intent, REQUEST_GETFILE); + return true; + } + return false; + } + + public void onActivityResult(final int requestCode, + int resultCode, final Intent data) { + switch(requestCode) { + case REQUEST_GETFILE: + switch(resultCode) { + case RESULT_OK: + String filePath = data.getStringExtra(FileDialog.RESULT_PATH); + Intent intent = new Intent(getApplicationContext(), InstallService.class); + intent.putExtra(InstallService.INTENT_START_URL, filePath); + intent.putExtra(InstallService.INTENT_START_FILE, true); + // Decompress .gz files + intent.putExtra(InstallService.INTENT_START_URL_UNZIPPED, !filePath.endsWith(".gz")); + startService(intent); + break; + case RESULT_CANCELED: + Toast.makeText(this, "No file selected", Toast.LENGTH_SHORT).show(); + break; + } + break; + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/JNI.java b/src/uk/digitalsquid/netspoofer/JNI.java new file mode 100644 index 0000000..b96e447 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/JNI.java @@ -0,0 +1,26 @@ +package uk.digitalsquid.netspoofer; + +/** + *

+ * Application JNI interfaces. Not used at the moment for any purpose, but could be in the future. + *

+ *

+ * Also used to force Android Market to filter by CPUs that this application actually supports, currently armel. + *

+ * + * @author william + * + */ +public class JNI { + static { + System.loadLibrary("netspooflib"); + } + + /** + * Chmod glibc function setting a file to 0755 + * @param filename + * @param permissions + * @return + */ + public static native int setExecutable(String filename); +} diff --git a/src/uk/digitalsquid/netspoofer/MultiSpoofDialogRunner.java b/src/uk/digitalsquid/netspoofer/MultiSpoofDialogRunner.java new file mode 100644 index 0000000..ea8b47d --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/MultiSpoofDialogRunner.java @@ -0,0 +1,135 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.util.ArrayList; +import java.util.Iterator; + +import uk.digitalsquid.netspoofer.spoofs.Spoof.OnExtraDialogDoneListener; +import uk.digitalsquid.netspoofer.spoofs.SquidScriptSpoof; +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.os.Bundle; + +public class MultiSpoofDialogRunner extends Activity implements OnExtraDialogDoneListener { + public static final String SPOOF_LIST = "uk.digitalsquid.netspoofer.MultiSpoofDialogRunner.list"; + + ArrayList spoofs; + Iterator currentSpoof; + SquidScriptSpoof spoof; + + Dialog currentDialog; + + @SuppressWarnings("unchecked") + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + spoofs = (ArrayList) getIntent().getSerializableExtra(SPOOF_LIST); + currentSpoof = spoofs.iterator(); + + processNextSpoof(false); + } + + private static final int ITERATED_ACTIVITY_ID = 1; + + private int dialogId = 0; + + /** + * Processes the next spoof in the iterator. + * @param processActivities If true, does activities. Otherwise, does dialogs. + */ + void processNextSpoof(boolean processActivities) { + if(!processActivities) { + if(currentSpoof.hasNext()) { + spoof = currentSpoof.next(); + Dialog d = spoof.displayExtraDialog(this, this); + if(d != null) { + currentDialog = d; + showDialog(dialogId++); + } else { + processNextSpoof(false); // Too much Haskell programming = using recursion too much... + } + } else { + currentSpoof = spoofs.iterator(); + processNextSpoof(true); + } + } else { // ACTIVITY processing + if(currentSpoof.hasNext()) { + spoof = currentSpoof.next(); + Intent i = spoof.activityForResult(getBaseContext()); + if(i != null) { + startActivityForResult(i, ITERATED_ACTIVITY_ID); + } else { + processNextSpoof(true); + } + } else { + completeProcess(); + } + } + } + + @Override + public void onDone() { + processNextSpoof(false); + } + + // Using this as it allows any form of dialog + @Override + public Dialog onCreateDialog(int id, Bundle args) { + return currentDialog; + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + switch(requestCode) { + case ITERATED_ACTIVITY_ID: + switch(resultCode) { + case RESULT_OK: + spoof.activityFinished(getBaseContext(), intent); + processNextSpoof(true); + break; + default: + cancelProcess(); + } + break; + } + } + + /** + * Cancels the config + */ + void cancelProcess() { + setResult(RESULT_CANCELED); + finish(); + } + + /** + * Completes the config + */ + void completeProcess() { + Intent i = new Intent(); + i.putExtra(SPOOF_LIST, spoofs); // Send list back under same name. + setResult(RESULT_OK, i); + finish(); + } +} diff --git a/src/uk/digitalsquid/netspoofer/NetSpoof.java b/src/uk/digitalsquid/netspoofer/NetSpoof.java new file mode 100644 index 0000000..2dbf47f --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/NetSpoof.java @@ -0,0 +1,438 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Serializable; + +import uk.digitalsquid.netspoofer.config.Config; +import uk.digitalsquid.netspoofer.config.ConfigChecker; +import uk.digitalsquid.netspoofer.config.FileFinder; +import uk.digitalsquid.netspoofer.config.FileInstaller; +import uk.digitalsquid.netspoofer.config.LogConf; +import uk.digitalsquid.netspoofer.config.NetHelpers; +import uk.digitalsquid.netspoofer.misc.AsyncTaskHelper; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources.NotFoundException; +import android.graphics.Typeface; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.WindowManager.BadTokenException; +import android.widget.Button; +import android.widget.Toast; + +public class NetSpoof extends Activity implements OnClickListener, LogConf { + /** + * A dialog to tell the user to mount their SD card. + */ + static final int DIALOG_R_SD = 1; + /** + * A dialog to tell the user to mount their SD card rw. + */ + static final int DIALOG_W_SD = 2; + static final int DIALOG_ROOT = 3; + static final int DIALOG_BB = 4; + /** + * BB found, no chroot. + */ + static final int DIALOG_BB_2 = 6; + static final int DIALOG_ABOUT = 5; + static final int DIALOG_AGREEMENT = 7; + static final int DIALOG_CHANGELOG = 8; + + private Button startButton, setupButton; + + private LoadResult loadResult; + + private boolean showChangelog = false; + + private SharedPreferences prefs; + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + startButton = (Button) findViewById(R.id.startButton); + startButton.setOnClickListener(this); + setupButton = (Button) findViewById(R.id.setupButton); + setupButton.setOnClickListener(this); + + if(!ConfigChecker.checkInstalledLatest(getApplicationContext())) { + setupButton.setTypeface(setupButton.getTypeface(), Typeface.BOLD); + if(ConfigChecker.checkInstalled(getApplicationContext())) { // Installed, but not latest version. + Toast.makeText(this, "New version of setup files, please download", Toast.LENGTH_LONG).show(); + } + } else { + setupButton.setTypeface(setupButton.getTypeface(), Typeface.NORMAL); + } + + AsyncTaskHelper.execute(loadTask); + + statusFilter = new IntentFilter(); + statusFilter.addAction(InstallService.INTENT_STATUSUPDATE); + + registerReceiver(statusReceiver, statusFilter); + + // Changelog dialog + int versionCode = -1; + try { + versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + int oldVersionCode = prefs.getInt("oldVersion", -1); + Log.v(TAG, "Old version is " + oldVersionCode + ", new version is " + versionCode); + if(versionCode != -1 && versionCode > oldVersionCode) { + Log.i(TAG, "Displaying changelog"); + prefs.edit().putInt("oldVersion", versionCode).commit(); + showChangelog = true; + } + + if(prefs.getBoolean("firstTime", true)) { // First time, show license thing + showDialog(DIALOG_AGREEMENT); + } else postInit(); // This isn't called on first time, as new users don't need to see changelog + } + + @Override + public void onDestroy() { + super.onDestroy(); + unregisterReceiver(statusReceiver); + } + + /** + * Non-important tasks after initialisation & agreement + */ + public void postInit() { + if(showChangelog) + showDialog(DIALOG_CHANGELOG); + } + + @Override + public void onClick(View v) { + switch(v.getId()) { + case R.id.setupButton: + Intent intent = new Intent(this, InstallStatus.class); + intent.putExtra(InstallStatus.EXTRA_DL_INFO, loadResult); + startActivity(intent); + break; + case R.id.startButton: + startActivity(new Intent(this, SpoofSelector.class)); + break; + } + } + + protected Dialog onCreateDialog(int id) { + Dialog dialog = null; + AlertDialog.Builder builder; + View view; + switch(id) { + case DIALOG_R_SD: + builder = new AlertDialog.Builder(this); + builder.setMessage("Please connect SD card / exit USB mode to continue.") + .setCancelable(false) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + NetSpoof.this.finish(); + } + }); + dialog = builder.create(); + break; + case DIALOG_W_SD: + builder = new AlertDialog.Builder(this); + builder.setMessage("Please set the SD Card to writable. May work without but expect problems.") + .setCancelable(false) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { } + }); + dialog = builder.create(); + break; + case DIALOG_ROOT: + builder = new AlertDialog.Builder(this); + builder.setMessage("Please root your phone before using this application. Search the internet for instructions on how to do this for your phone.\nA custom firmware (such as CyanogenMod) is also recommended.\n" + + "If the 'su' application is somewhere else on your phone, please specify it in the settings.") + .setCancelable(false) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { } + }); + dialog = builder.create(); + break; + case DIALOG_BB: + builder = new AlertDialog.Builder(this); + builder.setMessage("Please install Busybox (either manually or from the Android Market) before using this application. Network Spoofer will try to run, but may be unstable as Busybox is missing.") + .setCancelable(false) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { } + }); + dialog = builder.create(); + case DIALOG_BB_2: + builder = new AlertDialog.Builder(this); + builder.setTitle("So close.."); + builder.setMessage("You have Busybox installed, but it doesn't appear to have a required component '" + missingBBComponent + "'. Please update Busybox or try a different version of Busybox. Network Spoofer will most likely not work until you have updated Busybox") + .setCancelable(false) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { } + }); + dialog = builder.create(); + break; + case DIALOG_AGREEMENT: + builder = new AlertDialog.Builder(this); + view = getLayoutInflater().inflate(R.layout.agreement, null); + builder.setView(view); + builder.setTitle(R.string.agreementTitle); + builder.setCancelable(false); + builder.setPositiveButton(R.string.agreementPositive, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + prefs.edit().putBoolean("firstTime", false).commit(); + postInit(); + } + }); + builder.setNegativeButton(R.string.agreementNegative, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + dialog = builder.create(); + break; + case DIALOG_CHANGELOG: + builder = new AlertDialog.Builder(this); + view = getLayoutInflater().inflate(R.layout.changelog, null); + builder.setView(view); + builder.setTitle(R.string.agreementTitle); + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }); + dialog = builder.create(); + break; + } + return dialog; + } + + private String missingBBComponent = "?"; + + private IntentFilter statusFilter; + private final BroadcastReceiver statusReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + switch(intent.getIntExtra(InstallService.INTENT_EXTRA_STATUS, InstallService.STATUS_FINISHED)) { + case InstallService.STATUS_FINISHED: + switch(intent.getIntExtra(InstallService.INTENT_EXTRA_DLSTATE, InstallService.STATUS_DL_FAIL_DLERROR)) { + case InstallService.STATUS_DL_SUCCESS: + startButton.setEnabled(true); + break; + default: + startButton.setEnabled(false); + break; + } + break; + } + } + }; + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.netspoofmenu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.netSpoofMenuItemPrefs: + startActivity(new Intent(this, Preferences.class)); + return true; + case R.id.netSpoofMenuItemAbout: + startActivity(new Intent(this, About.class)); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + /** + * Results acquired while loading + * @author william + * + */ + public static class LoadResult implements Serializable { + private static final long serialVersionUID = 6559183327061065064L; + + public int versionNumber = -1; + /** + * An upgrade refers to a patch, not a new reinstall. + */ + public boolean doUpgrade = false; + public String upgradeUrl = ""; + + public boolean doReinstall = false; + + public boolean firstTime = false; + } + + private AsyncTask loadTask = new AsyncTask() { + + @Override + protected LoadResult doInBackground(Void... params) { + if(prefs == null) prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + + // Install scripts & BB + installFiles(); + + // Check SD and files on it + if(!ConfigChecker.getSDStatus(false)) { + publishProgress(DIALOG_R_SD); + } else { + if(!ConfigChecker.getSDStatus(true)) { + publishProgress(DIALOG_W_SD); + } + + final File sd = getExternalFilesDir(null); + File imgDir = new File(sd, "img"); + if(!imgDir.exists()) if(!imgDir.mkdir()) Log.e(TAG, "Couldn't create 'img' dir"); + + // Find files etc. + try { + FileFinder.initialise(getApplicationContext()); + } catch (FileNotFoundException e) { + e.printStackTrace(); + if(e.getMessage().equals("su")) { + publishProgress(DIALOG_ROOT); + } else if(e.getMessage().equals("busybox")) { + publishProgress(DIALOG_BB); + } else if(e.getMessage().startsWith("bb:")) { + missingBBComponent = e.getMessage().substring(2); // 2 = end of bb: + publishProgress(DIALOG_BB_2); + } + + } + } + + if(Build.VERSION.SDK_INT >= 18) { // 4.3 + Log.w(TAG, "Running Android 4.3 or above, with known quirks"); + Log.w(TAG, String.format("Env says ext storage is %s, using /sdcard because of root issues", + Environment.getExternalStorageDirectory())); + } + + LoadResult result = new LoadResult(); + + // Get current version and check for upgrade availability. + result.versionNumber = ConfigChecker.getVersionNumber(getApplicationContext()); + if(result.versionNumber >= Config.DEB_IMG_URL_VERSION) { // If current version + return result; + } + + // Check for possible upgrade file. Otherwise just prompt user to redownload whole file. + String url = String.format(Config.UPGRADE_URI_FORMAT, result.versionNumber, Config.DEB_IMG_URL_VERSION); + result.doUpgrade = NetHelpers.checkFileExistsOnWeb(url, Config.UPGRADE_URI_FAIL); + result.upgradeUrl = url; + result.firstTime = !ConfigChecker.checkInstalled(getApplicationContext()); + + // If can't upgrade, reinstall. + if(!result.doUpgrade) result.doReinstall = true; + + return result; + } + + /** + * Shows the dialog with the given ID. + */ + @Override + protected void onProgressUpdate(Integer... values) { + super.onProgressUpdate(values); + try { + showDialog(values[0]); + } catch(BadTokenException e) { + Log.w(TAG, "Activity not visible, tryed to show dialog", e); + } + } + + @Override + protected void onPostExecute(LoadResult result) { + // Set button statuses + if(!ConfigChecker.checkInstalledLatest(getApplicationContext())) { + setupButton.setTypeface(setupButton.getTypeface(), Typeface.BOLD); + } else { + setupButton.setTypeface(setupButton.getTypeface(), Typeface.NORMAL); + } + if(result.doUpgrade) setupButton.setText(R.string.setup_upgrade); + if(result.doReinstall) setupButton.setText(R.string.setup_upgrade2); + if(result.firstTime) setupButton.setText(R.string.setup); + + startButton.setEnabled(ConfigChecker.checkInstalled(getApplicationContext())); + setupButton.setEnabled(true); + + loadResult = result; + + findViewById(R.id.loading).setVisibility(View.INVISIBLE); + } + + /** + * Installs scripts & files into the data folder. + */ + private void installFiles() { + try { + FileInstaller fi = new FileInstaller(getBaseContext()); + + fi.installScript("config", R.raw.config); + fi.installScript("start", R.raw.start); + fi.installScript("mount", R.raw.mount); + fi.installScript("umount", R.raw.umount); + + fi.installScript("busybox", R.raw.busybox); + fi.installScript("applyupgrade", R.raw.applyupgrade); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (NotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + Log.e(TAG, "Failed to install scripts."); + } + } + }; +} diff --git a/src/uk/digitalsquid/netspoofer/NetSpoofService.java b/src/uk/digitalsquid/netspoofer/NetSpoofService.java new file mode 100644 index 0000000..5cddbe2 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/NetSpoofService.java @@ -0,0 +1,451 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import uk.digitalsquid.netspoofer.config.ChrootConfig; +import uk.digitalsquid.netspoofer.config.ChrootManager; +import uk.digitalsquid.netspoofer.config.FileFinder; +import uk.digitalsquid.netspoofer.config.IOHelpers; +import uk.digitalsquid.netspoofer.config.LogConf; +import uk.digitalsquid.netspoofer.misc.AsyncTaskHelper; +import uk.digitalsquid.netspoofer.servicemsg.ImageLoader; +import uk.digitalsquid.netspoofer.servicemsg.ServiceMsg; +import uk.digitalsquid.netspoofer.servicemsg.SpoofStarter; +import uk.digitalsquid.netspoofer.servicestatus.InitialiseStatus; +import uk.digitalsquid.netspoofer.servicestatus.NewLogOutput; +import uk.digitalsquid.netspoofer.servicestatus.Notifyer; +import uk.digitalsquid.netspoofer.servicestatus.ServiceStatus; +import uk.digitalsquid.netspoofer.servicestatus.SpoofList; +import uk.digitalsquid.netspoofer.spoofs.SpoofData; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Bitmap.CompressFormat; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Binder; +import android.os.Handler; +import android.provider.MediaStore; +import android.util.Log; +import android.widget.Toast; + +public class NetSpoofService extends Service implements LogConf { + public static final int STATUS_LOADING = 0; + public static final int STATUS_LOADED = 1; + public static final int STATUS_FINISHED = 2; + public static final int STATUS_STARTING = 3; + public static final int STATUS_STARTED = 4; + public static final int STATUS_STOPPING = 5; + public static final int STATUS_FAILED = 6; + + public static final String INTENT_STATUSUPDATE = "uk.digitalsquid.netspoofer.NetSpoofService.StatusUpdate"; + public static final String INTENT_SPOOFLIST = "uk.digitalsquid.netspoofer.NetSpoofService.SpoofList"; + public static final String INTENT_NEWLOGOUTPUT = "uk.digitalsquid.netspoofer.NetSpoofService.NewLogOutput"; + public static final String INTENT_EXTRA_STATUS = "uk.digitalsquid.netspoofer.NetSpoofService.status"; + public static final String INTENT_EXTRA_SPOOFLIST = "uk.digitalsquid.netspoofer.NetSpoofService.spooflist"; + public static final String INTENT_EXTRA_LOGOUTPUT = "uk.digitalsquid.netspoofer.NetSpoofService.logoutput"; + + private static final int NS_RUNNING = 1; + + private NotificationManager notificationManager; + private Notification notification; + + public class NetSpoofServiceBinder extends Binder { + public NetSpoofService getService() { + return NetSpoofService.this; + } + } + private final NetSpoofServiceBinder binder = new NetSpoofServiceBinder(); + + @Override + public NetSpoofServiceBinder onBind(Intent arg0) { + return binder; + } + + /** + * Used to do things on the UI thread (ie toasts) + */ + Handler uiThreadHandler; + + @Override + public void onCreate() { + super.onCreate(); + uiThreadHandler = new Handler(); + } + + /** + * Shows a toast on the UI thread + * @param text + * @param duration + */ + private void showToast(final String text, final int duration) { + uiThreadHandler.post(new Runnable() { + @Override + public void run() { + Toast.makeText(getBaseContext(), text, duration).show(); + } + }); + } + + private boolean started = false; + + private int status; + private void setStatus(int status) { + this.status = status; + broadcastStatus(); + } + public int getStatus() { + return status; + } + + public void broadcastStatus() { + Intent intent = new Intent(INTENT_STATUSUPDATE); + intent.putExtra(INTENT_EXTRA_STATUS, getStatus()); + sendBroadcast(intent); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + super.onStartCommand(intent, flags, startId); + if(!started) start(); + return START_NOT_STICKY; + } + + private void start() { + Toast.makeText(getApplicationContext(), "Loaded setup", Toast.LENGTH_LONG).show(); + + AsyncTaskHelper.execute(mainLoopManager, new ChrootConfig(getBaseContext())); + setStatus(STATUS_LOADING); + + notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + + started = true; + } + + @Override + public void onDestroy() { + Toast.makeText(getApplicationContext(), "Unloaded setup", Toast.LENGTH_LONG).show(); + mainLoopManager.cancel(false); + tasks.add(new ServiceMsg(ServiceMsg.MESSAGE_STOP)); + super.onDestroy(); + } + + public final void requestSpoofs() { + try { + tasks.add(new ServiceMsg(ServiceMsg.MESSAGE_GETSPOOFS)); + } catch(IllegalStateException e) { + e.printStackTrace(); + } + } + + private void sendSpoofList(SpoofList spoofs) { + Intent intent = new Intent(INTENT_SPOOFLIST); + intent.putExtra(INTENT_EXTRA_SPOOFLIST, spoofs); + sendBroadcast(intent); + } + + public void startSpoof(SpoofData spoof) { + try { + tasks.add(new SpoofStarter(spoof)); + } catch(IllegalStateException e) { + e.printStackTrace(); + } + } + + public void stopSpoof() { + try { + tasks.add(new ServiceMsg(ServiceMsg.MESSAGE_STOPSPOOF)); + } catch(IllegalStateException e) { + e.printStackTrace(); + } + } + + private void sendLogOutput(NewLogOutput logOutput) { + Intent intent = new Intent(INTENT_NEWLOGOUTPUT); + intent.putExtra(INTENT_EXTRA_LOGOUTPUT, logOutput); + sendBroadcast(intent); + } + + public void saveImageToWebserver(Uri image) { + try { + tasks.add(new ImageLoader(image)); + } catch(IllegalStateException e) { + e.printStackTrace(); + } + } + + private final BlockingQueue tasks = new LinkedBlockingQueue(); + + private final AsyncTask mainLoopManager = new AsyncTask() { + + @Override + protected Void doInBackground(ChrootConfig... params) { + Log.i(TAG, "Setting up chroot..."); + final ChrootManager chroot = new ChrootManager(NetSpoofService.this, params[0]); + + Log.i(TAG, "Starting chroot..."); + try { + if(!chroot.start()) { + Log.e(TAG, "Chroot start returned false, not mounted"); + throw new IOException("Mounted chroot not found after start command executed."); + } + } catch (IOException e) { + Log.e(TAG, "Chroot failed to load!"); + publishProgress(new InitialiseStatus(STATUS_FAILED)); + e.printStackTrace(); + try { + chroot.stop(); + } catch (IOException e1) { + e1.printStackTrace(); + } + return null; + } + publishProgress(new InitialiseStatus(STATUS_LOADED)); + if(isCancelled()) { + Log.i(TAG, "Stop initiated, stopping..."); + try { + chroot.stop(); + } catch (IOException e) { + e.printStackTrace(); + } + Log.i(TAG, "Done."); + return null; + } + + // Main point. Process requests from task list. + boolean running = true; + while(running || !isCancelled()) { + try { + ServiceMsg task = tasks.take(); + switch(task.getMessage()) { + case ServiceMsg.MESSAGE_OTHER: + if(task instanceof SpoofStarter) { + SpoofStarter starter = (SpoofStarter) task; + spoofLoop(chroot, starter.getSpoof()); + } else if(task instanceof ImageLoader) { + loadImageToDebian(chroot, ((ImageLoader)task).getUri()); + } + break; + case ServiceMsg.MESSAGE_STOP: + running = false; + break; + case ServiceMsg.MESSAGE_GETSPOOFS: + SpoofList list = new SpoofList(chroot.getSpoofList()); + publishProgress(list); + break; + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + Log.i(TAG, "Stopping chroot..."); + try { + chroot.stop(); + } catch (IOException e) { + e.printStackTrace(); + Log.e(TAG, "Chroot failed to stop."); + publishProgress(new InitialiseStatus(STATUS_FAILED)); + } + Log.i(TAG, "Done."); + return null; + } + + private void spoofLoop(final ChrootManager chroot, SpoofData spoof) { + publishProgress(new InitialiseStatus(STATUS_STARTING)); + try { + chroot.startSpoof(spoof); + } catch (IOException e) { + e.printStackTrace(); + Log.e(TAG, "Failed to start spoof."); + publishProgress(new InitialiseStatus(STATUS_LOADED)); + } + publishProgress(new InitialiseStatus(STATUS_STARTED)); + publishProgress(new Notifyer(NS_RUNNING, Notifyer.STATUS_SHOW)); + + boolean running = true; + while(running) { + ServiceMsg task = tasks.poll(); + if(task != null) { + switch(task.getMessage()) { + case ServiceMsg.MESSAGE_STOPSPOOF: + stopSpoof(chroot, spoof); + running = false; + break; + } + } + + if(isCancelled()) { + stopSpoof(chroot, spoof); + running = false; + break; + } + + if(chroot.checkIfStopped()) { + finishSpoof(chroot, spoof); + running = false; + break; + } + + try { + publishProgress(new NewLogOutput(chroot.getNewSpoofOutput())); // Send log back to anything listening. + } catch (IOException e) { + e.printStackTrace(); + } + + try { Thread.sleep(600); } catch (InterruptedException e) {} + } + } + + private void stopSpoof(ChrootManager chroot, SpoofData spoof) { + publishProgress(new InitialiseStatus(STATUS_STOPPING)); + publishProgress(new Notifyer(NS_RUNNING, Notifyer.STATUS_HIDE)); + try { + chroot.stopSpoof(spoof); + } catch (IOException e) { + e.printStackTrace(); + Log.e(TAG, "Failed to stop spoof."); + publishProgress(new InitialiseStatus(STATUS_STARTED)); + return; + } + } + + private void finishSpoof(ChrootManager chroot, SpoofData spoof) { + try { + publishProgress(new NewLogOutput(chroot.finishStopSpoof())); // Also send final output. + } catch (IOException e) { + e.printStackTrace(); + Log.e(TAG, "Failed to finish spoof."); + return; + } + publishProgress(new InitialiseStatus(STATUS_LOADED)); + } + + /** + * Loads the image then saves it as a jpg to the debian. + * @param imageUri + */ + private void loadImageToDebian(ChrootManager chroot, Uri imageUri) { + + File tmpImage = new File(getFilesDir(), "customimage.jpg"); + Log.i(TAG, "Loading image from media store"); + try { + Bitmap image = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri); + Log.i(TAG, "Writing image"); + FileOutputStream out = openFileOutput("customimage.jpg", MODE_WORLD_READABLE); + image.compress(CompressFormat.JPEG, 80, out); + out.close(); + image.recycle(); + Log.i(TAG, "Written image"); + + // Use BB to copy this as SU (need root to write to debian area) + final String su = FileFinder.SU; + final String bb = FileFinder.BUSYBOX; + final File debianImageFolder = new File(chroot.config.getDebianMount() + "/var/www/images"); + final File debianImage = new File(debianImageFolder, "customimage.jpg"); + + final List mkdirArgs = new LinkedList(); + // su -c busybox mkdir + mkdirArgs.add(su); + mkdirArgs.add("-c"); + mkdirArgs.add(bb + " " + "mkdir" + " " + debianImageFolder.getCanonicalPath()); + Log.v(TAG, "Running " + mkdirArgs); + try { + IOHelpers.runProcess(mkdirArgs); // Is this necessary? + } catch (IOException e) { + Log.e(TAG, "Failed to create image folder."); + } + + final List cpArgs = new LinkedList(); + // su busybox cp tmp.jpg deb.jpg + cpArgs.add(su); + cpArgs.add("-c"); + cpArgs.add(bb + " " + "cp" + " " + tmpImage.getCanonicalPath() + " " + debianImage.getCanonicalPath()); + Log.v(TAG, "Running " + cpArgs); + if(IOHelpers.runProcess(cpArgs) != 0) { + throw new IOException("Couldn't copy image from tmp to debian.\n Used cmdline " + cpArgs.toString()); + } + Log.i(TAG, "Copied image to debian folder."); + } catch (FileNotFoundException e) { + Log.e(TAG, "Couldn't open temporary file to write image", e); + showToast("Couldn't load selected image!", Toast.LENGTH_LONG); + } catch (IOException e) { + Log.e(TAG, "Couldn't write to temporary image", e); + showToast("Couldn't load selected image!", Toast.LENGTH_LONG); + } finally { + try { + tmpImage.delete(); + } catch(Exception e) { } // Don't care if it fails. + } + } + + protected void onProgressUpdate(ServiceStatus... progress) { + ServiceStatus s = progress[0]; + if(s instanceof InitialiseStatus) { + InitialiseStatus is = (InitialiseStatus) s; + setStatus(is.status); + } else if(s instanceof SpoofList) { + sendSpoofList((SpoofList)s); + } else if(s instanceof NewLogOutput) { + sendLogOutput((NewLogOutput) s); + } else if(s instanceof Notifyer) { + Notifyer n = (Notifyer) s; + + switch(n.getStatus()) { + case Notifyer.STATUS_SHOW: + switch(n.getNotificationType()) { + case NS_RUNNING: + notification = new Notification(R.drawable.status, getString(R.string.spoofRunning), System.currentTimeMillis()); + notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT; + + Intent notificationIntent = new Intent(NetSpoofService.this, NetSpoofService.class); + PendingIntent contentIntent = PendingIntent.getActivity(NetSpoofService.this, 0, notificationIntent, 0); + + notification.setLatestEventInfo(NetSpoofService.this, NetSpoofService.this.getString(R.string.spoofRunning), NetSpoofService.this.getString(R.string.spoofRunningDesc), contentIntent); + notificationManager.notify(NS_RUNNING, notification); + break; + } + break; + case Notifyer.STATUS_HIDE: + notificationManager.cancel(NS_RUNNING); + break; + } + } + } + protected void onPostExecute(Void result) { + setStatus(STATUS_FINISHED); + stopSelf(); + } + }; +} diff --git a/src/uk/digitalsquid/netspoofer/Preferences.java b/src/uk/digitalsquid/netspoofer/Preferences.java new file mode 100644 index 0000000..f2da64b --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/Preferences.java @@ -0,0 +1,77 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.io.FileNotFoundException; + +import uk.digitalsquid.netspoofer.config.FileFinder; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.preference.PreferenceManager; +import android.widget.Toast; + +public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener { + + SharedPreferences prefs; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + prefs.registerOnSharedPreferenceChangeListener(this); + + if(prefs.getBoolean("builtinbusybox", true)) { // If builtinBB is true + findPreference("pathToBB").setEnabled(false); + } else { + findPreference("pathToBB").setEnabled(true); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + prefs.unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if(key.equals("builtinbusybox")) { + if(prefs.getBoolean(key, true)) { // If builtinBB is true + findPreference("pathToBB").setEnabled(false); + } else { + findPreference("pathToBB").setEnabled(true); + } + } + + if(key.equals("builtinbusybox") || key.equals("pathToBB")) { + try { + FileFinder.loadPaths(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + Toast.makeText(getBaseContext(), "Failed to find new BusyBox path", Toast.LENGTH_LONG).show(); + } + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/RouterSelector.java b/src/uk/digitalsquid/netspoofer/RouterSelector.java new file mode 100644 index 0000000..37f20a7 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/RouterSelector.java @@ -0,0 +1,332 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.UnknownHostException; + +import uk.digitalsquid.netspoofer.config.LogConf; +import uk.digitalsquid.netspoofer.config.NetHelpers; +import uk.digitalsquid.netspoofer.config.NetHelpers.GatewayData; +import uk.digitalsquid.netspoofer.spoofs.Spoof; +import uk.digitalsquid.netspoofer.spoofs.SpoofData; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.ActivityNotFoundException; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.NetworkInfo.State; +import android.net.wifi.SupplicantState; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiManager.WifiLock; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.BaseAdapter; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +public class RouterSelector extends Activity implements OnClickListener, LogConf { + public static final String EXTRA_SPOOF = "uk.digitalsquid.netspoofer.RouterSelector.SPOOF"; + + private Spoof spoof; + + private WifiManager wm; + private WifiLock wL; + + private NetworkInterface wifiIface; + private InetAddress wifiIP; + private GatewayData wifiGateway; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.routerselector); + + spoof = (Spoof) getIntent().getSerializableExtra(EXTRA_SPOOF); + if(spoof == null) { + Log.e(TAG, "No spoof given in intent, finishing"); + finish(); + } + + gatewayListAdapter = new GatewayListAdapter(); + ListView gatewayList = (ListView) findViewById(R.id.routerList); + gatewayList.setAdapter(gatewayListAdapter); + gatewayList.setOnItemClickListener(gatewayListAdapter); + + findViewById(R.id.wifiSettings).setOnClickListener(this); + + wm = (WifiManager) getSystemService(Context.WIFI_SERVICE); + wL = wm.createWifiLock(WifiManager.WIFI_MODE_FULL, "android-netspoof"); + wL.acquire(); + + if(wm.getConnectionInfo().getSupplicantState() == SupplicantState.COMPLETED) getAndSetWifiInfo(); + + IntentFilter wifiFilter = new IntentFilter(); + wifiFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); + wifiFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + wifiFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + // wifiFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); + // wifiFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); + // wifiFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + registerReceiver(wifiListener, wifiFilter); + } + + @Override + protected void onDestroy() { + unregisterReceiver(wifiListener); + wL.release(); + super.onDestroy(); + } + + BroadcastReceiver wifiListener = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); + if(info.getType() == ConnectivityManager.TYPE_WIFI || info.getType() == ConnectivityManager.TYPE_WIMAX) { // Only wifi + if(info.getState() == State.CONNECTED) { + getAndSetWifiInfo(); + } + else gatewayListAdapter.setWifiGateway(null); + } + } else { // Some sort of wifi thing + switch(wm.getConnectionInfo().getSupplicantState()) { + case COMPLETED: + break; + default: + // gatewayListAdapter.setWifiGateway(null); + break; + } + } + } + }; + + private GatewayListAdapter gatewayListAdapter; + + private class GatewayListAdapter extends BaseAdapter implements OnItemClickListener { + private final LayoutInflater inflater; + public static final int ITEM_DEFAULT = 0; + public static final int ITEM_PASSIVE = 1; + public static final int ITEM_OTHER = 2; + + private boolean wifiReady = false; + private String wifiGateway = ""; + + public void setWifiGateway(String gateway) { + wifiReady = (gateway != null); + wifiGateway = gateway; + notifyDataSetChanged(); + } + + public GatewayListAdapter() { + inflater = LayoutInflater.from(RouterSelector.this); + } + + @Override + public int getCount() { + return 3; + } + + @Override + public Object getItem(int position) { + return position; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = inflater.inflate(R.layout.routerlistitem, null); + } + TextView name = (TextView) convertView.findViewById(R.id.routerName); + TextView description = (TextView) convertView.findViewById(R.id.routerDescription); + + switch(position) { + case ITEM_DEFAULT: + if(wifiReady) { + name.setText("Default gateway (recommended)"); + description.setText("Autodetected " + wifiGateway); + convertView.setEnabled(true); + } else { + name.setText("Waiting for Wifi..."); + description.setText("Please connect to a Wifi network to automatically get the router's address"); + convertView.setEnabled(false); + } + break; + case ITEM_PASSIVE: + name.setText("Run passively"); + description.setText("Run the spoof passively; run the process, but not for anyone. Choose this to test spoofs or if Wifi tethering. Some settings may not completely work like this."); + convertView.setEnabled(true); + break; + case ITEM_OTHER: + name.setText("Other"); + description.setText("Choose custom IP addresses to use as the default gateway, IP and interface"); + convertView.setEnabled(true); + break; + } + return convertView; + } + + @Override + public void onItemClick(AdapterView adapter, View view, int position, long id) { + switch(position) { + case ITEM_DEFAULT: + if(view.isEnabled()) { + goToNextStep(RouterSelector.this.wifiIP.getHostAddress(), RouterSelector.this.wifiGateway.getSubnet(), RouterSelector.this.wifiGateway.getGateway().getHostAddress(), RouterSelector.this.wifiIface.getDisplayName()); + } + break; + case ITEM_PASSIVE: + goToNextStep(true); + break; + case ITEM_OTHER: + showDialog(DIALOG_CUSTOMIP); + break; + } + } + } + + private static final int DIALOG_CUSTOMIP = 0; + + @Override + public Dialog onCreateDialog(int id, Bundle bundle) { + switch(id) { + case DIALOG_CUSTOMIP: + AlertDialog.Builder builder = new AlertDialog.Builder(this); + + LayoutInflater inflater = LayoutInflater.from(this); + LinearLayout view = (LinearLayout)inflater.inflate(R.layout.otheripdialog, null); + + final EditText + myIp = (EditText) view.findViewById(R.id.myIpText), + subnetMask = (EditText) view.findViewById(R.id.subnetMaskText), + routerIp = (EditText) view.findViewById(R.id.routerIpText), + myIf = (EditText) view.findViewById(R.id.myIfText); + + builder.setView(view); + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String sMyIp = myIp.getText().toString(); + String sMyIf = myIf.getText().toString(); + String sRouterIp = routerIp.getText().toString(); + String sSubnetMask = subnetMask.getText().toString(); + + // Check if valid + try { + InetAddress.getByName(sMyIp); + InetAddress.getByName(sRouterIp); + } catch (UnknownHostException e) { + e.printStackTrace(); + Toast.makeText(getBaseContext(), "Invalid IP addresses entered. Please enter valid information.", Toast.LENGTH_LONG).show(); + return; + } + goToNextStep(sMyIp, sSubnetMask, sRouterIp, sMyIf); + } + }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }).setTitle(R.string.customIpSettings); + return builder.create(); + default: + return null; + } + } + + @Override + public void onClick(View v) { + switch(v.getId()) { + case R.id.wifiSettings: + try { + startActivity(new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS)); + } catch(ActivityNotFoundException e) { + Toast.makeText(getBaseContext(), "Couldn't load Wifi settings.", Toast.LENGTH_SHORT).show(); + } + break; + } + } + + private boolean autoNextStepStarted = false; + + private void getAndSetWifiInfo() { + int ip = wm.getConnectionInfo().getIpAddress(); + try { + wifiIP = NetHelpers.inetFromInt(ip); + wifiIface = NetHelpers.getIface(wifiIP); + wifiGateway = NetHelpers.getDefaultGateway(wifiIface); + gatewayListAdapter.setWifiGateway(wifiGateway.getGateway().getHostAddress()); + if(!autoNextStepStarted && PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getBoolean("autoChooseRouter", false)) { + autoNextStepStarted = true; + // Auto start if user specified to. + goToNextStep(RouterSelector.this.wifiIP.getHostAddress(), RouterSelector.this.wifiGateway.getSubnet(), RouterSelector.this.wifiGateway.getGateway().getHostAddress(), RouterSelector.this.wifiIface.getDisplayName()); + } + } catch (UnknownHostException e) { + e.printStackTrace(); + Toast.makeText(getBaseContext(), "Error getting wifi info. Please see log for more info.", Toast.LENGTH_LONG).show(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + Toast.makeText(getBaseContext(), "Error getting wifi info. Please see log for more info.", Toast.LENGTH_LONG).show(); + } + } + + private void goToNextStep(boolean runningPassively) { + Intent intent = new Intent(this, SpoofRunning.class); + intent.putExtra(SpoofRunning.EXTRA_SPOOFDATA, new SpoofData(spoof, true)); + startActivity(intent); + } + + private void goToNextStep(String myIp, String mySubnet, String gatewayIp, String wifiIface) { + Intent intent = new Intent(this, VictimSelector.class); + try { + intent.putExtra(VictimSelector.EXTRA_SPOOFDATA, new SpoofData(spoof, myIp, mySubnet, wifiIface, gatewayIp)); + } catch (UnknownHostException e) { + e.printStackTrace(); + Log.e(TAG, "Couldn't decode IP addresses."); + Toast.makeText(this, "Error decoding IP addresses given. Perhaps you mistyped something or aren't connected to Wifi?", Toast.LENGTH_LONG).show(); + return; + } + startActivity(intent); + } +} diff --git a/src/uk/digitalsquid/netspoofer/SpoofRunning.java b/src/uk/digitalsquid/netspoofer/SpoofRunning.java new file mode 100644 index 0000000..a56755d --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/SpoofRunning.java @@ -0,0 +1,196 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.util.ArrayList; + +import uk.digitalsquid.netspoofer.NetSpoofService.NetSpoofServiceBinder; +import uk.digitalsquid.netspoofer.config.LogConf; +import uk.digitalsquid.netspoofer.servicestatus.NewLogOutput; +import uk.digitalsquid.netspoofer.spoofs.SpoofData; +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.ScrollView; +import android.widget.TextView; +import android.widget.Toast; + +public class SpoofRunning extends Activity implements OnClickListener, LogConf { + public static final String EXTRA_SPOOFDATA = "uk.digitalsquid.netspoofer.SpoofRunning.SPOOFDATA"; + + private SpoofData spoof; + + private Button startButton; + private TextView logOutput, spoofStatus; + private ScrollView logscroller; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.spoofrunning); + startButton = (Button) findViewById(R.id.startButton); + startButton.setOnClickListener(this); + logOutput = (TextView) findViewById(R.id.logoutput); + spoofStatus = (TextView) findViewById(R.id.spoofstatus); + logscroller = (ScrollView) findViewById(R.id.logscroller); + spoof = (SpoofData) getIntent().getSerializableExtra(EXTRA_SPOOFDATA); + if(spoof == null) { + finish(); + } else { + bindService(new Intent(this, NetSpoofService.class), mConnection, Context.BIND_AUTO_CREATE); + } + + } + + @Override + public void onDestroy() { + super.onDestroy(); + // Unbind from the service + if (service != null) { + unbindService(mConnection); + service = null; + } + } + + @Override + protected void onStart() { + super.onStart(); + statusFilter = new IntentFilter(); + statusFilter.addAction(NetSpoofService.INTENT_STATUSUPDATE); + statusFilter.addAction(NetSpoofService.INTENT_NEWLOGOUTPUT); + registerReceiver(statusReceiver, statusFilter); + } + + @Override + protected void onStop() { + unregisterReceiver(statusReceiver); + super.onStop(); + } + + private NetSpoofService service; + + private ServiceConnection mConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + NetSpoofServiceBinder binder = (NetSpoofServiceBinder) service; + SpoofRunning.this.service = binder.getService(); + + updateStatus(SpoofRunning.this.service.getStatus()); + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + service = null; + } + }; + + private ArrayList logList = new ArrayList(); + private static final int LOG_LENGTH = 10; + + private IntentFilter statusFilter; + private final BroadcastReceiver statusReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getAction().equals(NetSpoofService.INTENT_STATUSUPDATE)) { + updateStatus(intent.getIntExtra(NetSpoofService.INTENT_EXTRA_STATUS, NetSpoofService.STATUS_FINISHED)); + } else if(intent.getAction().equals(NetSpoofService.INTENT_NEWLOGOUTPUT)) { + NewLogOutput newLog = (NewLogOutput) intent.getSerializableExtra(NetSpoofService.INTENT_EXTRA_LOGOUTPUT); + assert newLog != null; + logList.addAll(newLog.getLogLines()); + logList.subList(0, logList.size() < LOG_LENGTH ? 0 : (logList.size() - LOG_LENGTH)).clear(); + StringBuilder sb = new StringBuilder(); + for(String entry : logList) { + sb.append(entry); + sb.append("\n"); + } + logOutput.setText(sb); + logscroller.fullScroll(ScrollView.FOCUS_DOWN); + } + } + }; + + private void updateStatus(int status) { + switch(status) { + case NetSpoofService.STATUS_STARTING: + startButton.setEnabled(false); + startButton.setText(R.string.stop); + spoofStatus.setText(R.string.spoofstarting); + stopBackPress = true; + break; + case NetSpoofService.STATUS_STARTED: + startButton.setEnabled(true); + startButton.setText(R.string.stop); + spoofStatus.setText(R.string.spoofstarted); + break; + case NetSpoofService.STATUS_STOPPING: + startButton.setEnabled(false); + startButton.setText(R.string.start); + spoofStatus.setText(R.string.spoofstopping); + break; + case NetSpoofService.STATUS_LOADED: // Stopped + startButton.setEnabled(true); + startButton.setText(R.string.start); + spoofStatus.setText(R.string.spoofnotrunning); + stopBackPress = false; + break; + } + } + + @Override + public void onClick(View v) { + switch(v.getId()) { + case R.id.startButton: + switch(service.getStatus()) { + case NetSpoofService.STATUS_LOADED: + service.startSpoof(spoof); + findViewById(R.id.spoofWarning).setVisibility(View.GONE); + break; + case NetSpoofService.STATUS_STARTED: + service.stopSpoof(); + findViewById(R.id.spoofWarning).setVisibility(View.VISIBLE); + break; + } + break; + } + } + + private boolean stopBackPress = false; + + // Stop accidental back press + @Override + public void onBackPressed() { + if(!stopBackPress) finish(); + else { + Toast.makeText(this, "Spoof is still running, please press back again to confirm that you want to exit.", Toast.LENGTH_LONG).show(); + stopBackPress = false; + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/SpoofSelector.java b/src/uk/digitalsquid/netspoofer/SpoofSelector.java new file mode 100644 index 0000000..396af44 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/SpoofSelector.java @@ -0,0 +1,429 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import uk.digitalsquid.netspoofer.NetSpoofService.NetSpoofServiceBinder; +import uk.digitalsquid.netspoofer.config.LogConf; +import uk.digitalsquid.netspoofer.misc.CheckedLinearLayout; +import uk.digitalsquid.netspoofer.servicestatus.SpoofList; +import uk.digitalsquid.netspoofer.spoofs.Spoof; +import uk.digitalsquid.netspoofer.spoofs.Spoof.OnExtraDialogDoneListener; +import uk.digitalsquid.netspoofer.spoofs.SquidScriptSpoof; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.AlertDialog.Builder; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.util.Log; +import android.util.SparseBooleanArray; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.BaseAdapter; +import android.widget.Checkable; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +/** + * Shows a list of possible spoofs, either a single one or a multi choice. + * @author william + * + */ +public class SpoofSelector extends Activity implements OnClickListener, OnItemClickListener, LogConf { + ProgressDialog startingProgress; + + private ListView spoofList; + + boolean haveSpoofList = false; + boolean gettingSpoofList = false; + + boolean multiChoice = false; + List multiSpoofList; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if(Intent.ACTION_PICK.equals(getIntent().getAction())) { // activity for result + multiChoice = true; + setContentView(R.layout.spoofmultiselector); + findViewById(R.id.ok).setOnClickListener(this); + findViewById(R.id.cancel).setOnClickListener(this); + } else { + setContentView(R.layout.spoofselector); + } + if(!multiChoice) startService(new Intent(this, NetSpoofService.class)); + + spoofListAdapter = new SpoofListAdapter(); + spoofList = (ListView) findViewById(R.id.spoofList); + if(!multiChoice) { + spoofList.setAdapter(spoofListAdapter); + spoofList.setOnItemClickListener(this); + } else { + spoofList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + spoofList.setItemsCanFocus(false); + } + + statusFilter = new IntentFilter(); + statusFilter.addAction(NetSpoofService.INTENT_STATUSUPDATE); + statusFilter.addAction(NetSpoofService.INTENT_SPOOFLIST); + registerReceiver(statusReceiver, statusFilter); + } + @Override + public void onDestroy() { + super.onDestroy(); + if(!multiChoice) stopService(new Intent(this, NetSpoofService.class)); + unregisterReceiver(statusReceiver); + } + + @Override + protected void onStart() { + super.onStart(); + // Bind to LocalService + bindService(new Intent(this, NetSpoofService.class), mConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + // Unbind from the service + if (service != null) { + unbindService(mConnection); + service = null; + } + } + + private NetSpoofService service; + + private ServiceConnection mConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + NetSpoofServiceBinder binder = (NetSpoofServiceBinder) service; + SpoofSelector.this.service = binder.getService(); + + switch(SpoofSelector.this.service.getStatus()) { + case NetSpoofService.STATUS_LOADING: + showStartingDialog(); + break; + case NetSpoofService.STATUS_LOADED: + if(!gettingSpoofList) { + gettingSpoofList = true; + SpoofSelector.this.service.requestSpoofs(); + } + break; + } + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + service = null; + } + }; + + private IntentFilter statusFilter; + private final BroadcastReceiver statusReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getAction().equals(NetSpoofService.INTENT_STATUSUPDATE)) { + switch(intent.getIntExtra(NetSpoofService.INTENT_EXTRA_STATUS, NetSpoofService.STATUS_FINISHED)) { + case NetSpoofService.STATUS_LOADING: + showStartingDialog(); + break; + case NetSpoofService.STATUS_LOADED: + if(startingDialog != null) startingDialog.cancel(); + if(!gettingSpoofList) { + gettingSpoofList = true; + if(SpoofSelector.this.service != null) SpoofSelector.this.service.requestSpoofs(); + } + break; + case NetSpoofService.STATUS_FAILED: + try { + if(startingDialog != null) startingDialog.cancel(); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Couldn't close dialog, ignoring..."); + } + showDialog(DIALOG_FAIL_LOAD); + break; + } + } else if(intent.getAction().equals(NetSpoofService.INTENT_SPOOFLIST)) { + SpoofList spoofs = (SpoofList) intent.getSerializableExtra(NetSpoofService.INTENT_EXTRA_SPOOFLIST); + if(multiChoice) { + multiSpoofList = new ArrayList(); + for(Spoof s : spoofs.getSpoofs()) { + if(s instanceof SquidScriptSpoof) { + multiSpoofList.add(s); + } + } + Collections.sort(multiSpoofList); + spoofList.setAdapter(new ArrayAdapter(SpoofSelector.this, android.R.layout.simple_list_item_multiple_choice, multiSpoofList)); + } else { + spoofListAdapter.setSpoofs(spoofs.getSpoofs()); + } + } + } + }; + + private ProgressDialog startingDialog; + + private void showStartingDialog() { + if(startingDialog != null) if(startingDialog.isShowing()) return; + startingDialog = new ProgressDialog(this); + startingDialog.setTitle(R.string.loading); + startingDialog.setMessage("Starting environment... This should take a few seconds"); + startingDialog.setCancelable(false); + startingDialog.setOnKeyListener(new DialogInterface.OnKeyListener() { + @Override + public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_SEARCH && event.getRepeatCount() == 0) { + return true; + } + return false; + } + }); + startingDialog.show(); + } + + private SpoofListAdapter spoofListAdapter; + + private class SpoofListAdapter extends BaseAdapter { + private final LayoutInflater inflater; + + private List spoofs; + + public SpoofListAdapter() { + inflater = LayoutInflater.from(SpoofSelector.this); + } + + @SuppressLint("WrongViewCast") + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if(spoofs == null) { + if (convertView == null) { + convertView = inflater.inflate(R.layout.listloadingitem, null); + convertView.setEnabled(false); + } + } else { + if (convertView != null) { + if(convertView.findViewById(R.id.spoofTitle) == null) // Must be other view + convertView = inflater.inflate(R.layout.spoofitem, null); + } else { + convertView = inflater.inflate(R.layout.spoofitem, null); + } + // NOTE: Not used, currently using ArrayAdapter. + if(multiChoice) { + convertView.findViewById(R.id.checkbox).setVisibility(View.VISIBLE); + ((CheckedLinearLayout)convertView).setCheckable((Checkable) convertView.findViewById(R.id.checkbox)); + } else { + convertView.findViewById(R.id.checkbox).setVisibility(View.GONE); + } + TextView title = (TextView) convertView.findViewById(R.id.spoofTitle); + TextView description = (TextView) convertView.findViewById(R.id.spoofDescription); + + title.setText(spoofs.get(position).getTitle()); + description.setText(spoofs.get(position).getDescription()); + } + + return convertView; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public Spoof getItem(int position) { + if(spoofs == null) return null; + return spoofs.get(position); + } + + @Override + public int getCount() { + if(spoofs == null) return 1; + return spoofs.size(); + } + + public void setSpoofs(List spoofs) { + if(!multiChoice) { + this.spoofs = spoofs; + } else { + // Remove non squid spoofs + this.spoofs = new LinkedList(); + for(Spoof spoof : spoofs) { + if(spoof instanceof SquidScriptSpoof) { + this.spoofs.add(spoof); + } + } + } + notifyDataSetChanged(); + } + } + + @Override + public void onItemClick(AdapterView arg0, View view, int position, long id) { + final Spoof spoof = spoofListAdapter.getItem(position); + if(spoof == null) return; + + // Start processing spoof etc. + final OnExtraDialogDoneListener onDone = new OnExtraDialogDoneListener() { + @Override + public void onDone() { + Log.d(TAG, "Dialog done, continuing"); + Intent intent = new Intent(SpoofSelector.this, RouterSelector.class); + intent.putExtra(RouterSelector.EXTRA_SPOOF, spoof); + startActivity(intent); + } + }; + Dialog optDialog = spoof.displayExtraDialog(this, onDone); + if(optDialog == null) { + // Only execute activity if no dialog. TODO: Make this logic better? + Intent resultIntent = spoof.activityForResult(this); + if(resultIntent != null) { + activityResultSpoof = spoof; + startActivityForResult(resultIntent, ACTIVITY_REQUEST_CUSTOM); + } + else onDone.onDone(); // Nothing to do + } else { // Let dialog do so. + optDialog.show(); + } + } + + private static final int DIALOG_FAIL_LOAD = 1; + + /** + * The ID used for result intents returned by custom spoofs. + */ + private static final int ACTIVITY_REQUEST_CUSTOM = 2; + /** + * The ID used for result intents returned by custom spoofs, part 2. + */ + private static final int ACTIVITY_REQUEST_CUSTOM_2 = 3; + + private Spoof activityResultSpoof; + + @Override + public Dialog onCreateDialog(int id, Bundle bundle) { + super.onCreateDialog(id, bundle); + switch(id) { + case DIALOG_FAIL_LOAD: + Builder builder = new Builder(this); + builder.setTitle(R.string.loadfailedtitle); + builder.setMessage(R.string.loadfailed); + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + return builder.create(); + default: return null; + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + switch(requestCode) { + case ACTIVITY_REQUEST_CUSTOM: + if(activityResultSpoof != null) { + if(resultCode == RESULT_OK) { + if(activityResultSpoof.activityFinished(getBaseContext(), data)) { // If true, continue + Log.d(TAG, "Activity done, continuing"); + // NEW: Run 2nd activity if needed. + Intent part2 = activityResultSpoof.activityForResult2(this); + if(part2 != null) { + startActivityForResult(part2, ACTIVITY_REQUEST_CUSTOM_2); + } else { + Intent intent = new Intent(SpoofSelector.this, RouterSelector.class); + intent.putExtra(RouterSelector.EXTRA_SPOOF, activityResultSpoof); + startActivity(intent); + } + } + } + } + break; + case ACTIVITY_REQUEST_CUSTOM_2: + if(activityResultSpoof != null) { + if(resultCode == RESULT_OK) { + if(activityResultSpoof.activityFinished2(getBaseContext(), data)) { // If true, continue + Log.d(TAG, "Activity 2 done, continuing"); + Intent intent = new Intent(SpoofSelector.this, RouterSelector.class); + intent.putExtra(RouterSelector.EXTRA_SPOOF, activityResultSpoof); + startActivity(intent); + } + } + } + break; + } + } + @Override + public void onClick(View v) { + switch(v.getId()) { + case R.id.ok: + // Process selections + SparseBooleanArray arr = spoofList.getCheckedItemPositions(); + LinkedList selected = new LinkedList(); + if(multiSpoofList != null) { + for(int i = 0; i < multiSpoofList.size(); i++) { + if(arr.get(i)) { + selected.add(multiSpoofList.get(i)); + } + } + } + if(selected.size() != 0) { + Intent result = new Intent(); + result.putExtra("uk.digitalsquid.netspoof.SpoofSelector.spoofs", selected); + setResult(RESULT_OK, result); + finish(); + } else { + setResult(RESULT_CANCELED); + Toast.makeText(this, "Please specify some spoofs to use", Toast.LENGTH_LONG).show(); + finish(); + } + break; + case R.id.cancel: + setResult(RESULT_CANCELED); + finish(); + break; + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/VictimSelector.java b/src/uk/digitalsquid/netspoofer/VictimSelector.java new file mode 100644 index 0000000..1cba439 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/VictimSelector.java @@ -0,0 +1,453 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer; + +import java.io.IOException; +import java.io.Serializable; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import uk.digitalsquid.netspoofer.config.LogConf; +import uk.digitalsquid.netspoofer.config.NetHelpers; +import uk.digitalsquid.netspoofer.misc.AsyncTaskHelper; +import uk.digitalsquid.netspoofer.spoofs.SpoofData; +import android.app.Activity; +import android.app.AlertDialog.Builder; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +public class VictimSelector extends Activity implements OnClickListener, LogConf { + public static final String EXTRA_SPOOFDATA = "uk.digitalsquid.netspoofer.VictimSelector.SPOOFDATA"; + + private SpoofData spoof; + + private ProgressBar scanProgressBar; + private TextView scanProgressText; + private Button scanProgressRefresh; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); + + final Intent myStarter = getIntent(); + spoof = (SpoofData) myStarter.getSerializableExtra(EXTRA_SPOOFDATA); + if(spoof == null) { + Log.e(TAG, "Incorrect data given in intent, finishing"); + finish(); + } + + if(PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getBoolean("autoChooseVictim", false)) { + // Auto advance as user requested. + goToNextStep(null); + return; + } + + setContentView(R.layout.victimselector); + + victimListAdapter = new VictimListAdapter(); + final ListView victimList = (ListView) findViewById(R.id.victimList); + victimList.setAdapter(victimListAdapter); + victimList.setOnItemClickListener(victimListAdapter); + + scanProgressBar = (ProgressBar) findViewById(R.id.scanProgressBar); + scanProgressText = (TextView) findViewById(R.id.scanProgressText); + scanProgressRefresh = (Button) findViewById(R.id.scanProgressRefresh); + scanProgressRefresh.setOnClickListener(this); + + startScanners(); + AsyncTaskHelper.execute(hostnameFinder); + } + + @Override + public void onDestroy() { + super.onDestroy(); + Log.v(TAG, "VictimSelector stopping"); + hostnameFinder.cancel(false); + } + + private VictimListAdapter victimListAdapter; + + public static class Victim implements Comparable, Serializable { + private static final long serialVersionUID = -8815727249378333391L; + private final InetAddress ip; + private String name; + + public Victim(InetAddress ip) { + this.ip = ip; + } + + public InetAddress getIp() { + return ip; + } + + public String getIpString() { + return ip.getHostAddress(); + } + + /** + * Gets the predetermined hostname. This will initially be null, but will be filled in later by the lookup thread. + * @return + */ + public String getHostname() { + return name; + } + + public void setHostname(String name) { + this.name = name; + } + + @Override + public int compareTo(Victim another) { + byte[] me = ip.getAddress(); + byte[] other = another.getIp().getAddress(); + for(int i = 0; i < me.length && i < other.length; i++) { + if(me[i] != other[i]) { + return me[i] - other[i]; + } + } + return 0; + } + } + + private class VictimListAdapter extends BaseAdapter implements OnItemClickListener { + private final LayoutInflater inflater; + List victims = new ArrayList(); + + private static final int ITEM_ALL = 0; + private static final int ITEM_OTHER = 1; + + public VictimListAdapter() { + inflater = LayoutInflater.from(VictimSelector.this); + } + + @Override + public int getCount() { + return victims.size() + 2; // 2 for all + other + } + + @Override + public Victim getItem(int position) { + if(position < 2) return null; + return victims.get(position - 2); + } + + @Override + public long getItemId(int position) { + if(position < 2) return position; + return position - 2; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + if (convertView == null) { + convertView = inflater.inflate(R.layout.victimlistitem, null); + + holder = new ViewHolder(); + holder.vIp = (TextView) convertView.findViewById(R.id.victimIp); + holder.vText = (TextView) convertView.findViewById(R.id.victimExtraText); + + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + switch(position) { + case ITEM_ALL: + holder.vIp.setText(R.string.allDevices); + holder.vText.setText(R.string.allDevicesDesc); + convertView.setEnabled(true); + break; + case ITEM_OTHER: + holder.vIp.setText(R.string.otherDevice); + holder.vText.setText(R.string.otherDeviceDesc); + convertView.setEnabled(true); + break; + default: + holder.vIp.setText(getItem(position).ip.getHostAddress()); + holder.vText.setText(getItem(position).getHostname()); + break; + } + return convertView; + } + + private class ViewHolder { + TextView vIp; + TextView vText; + } + + @Override + public void onItemClick(AdapterView adapter, View view, int position, long id) { + Victim victim = getItem(position); + switch(position) { + case ITEM_ALL: + // null means spoof everyone. + goToNextStep(null); + break; + case ITEM_OTHER: + showDialog(DIALOG_GETIP); + break; + default: + goToNextStep(victim); + break; + } + } + + @SuppressWarnings("unused") + public void addDeviceToList(Victim victim) { + victims.add(victim); + Collections.sort(victims); + notifyDataSetChanged(); + } + + public void addDevicesToList(Victim[] victimList) { + for(Victim victim : victimList) { + victims.add(victim); + } + Collections.sort(victims); + notifyDataSetChanged(); + } + + public void clearDeviceList() { + victims.clear(); + notifyDataSetChanged(); + } + } + + private IPScanner[] scanners; + + private class IPScanner extends AsyncTask { + + private final long ipFrom, ipTo; + + private boolean running = true; + + public IPScanner(long ipFrom, long ipTo) { + this.ipFrom = ipFrom; + this.ipTo = ipTo; + } + + @Override + protected Void doInBackground(Void... params) { + Log.d(TAG, String.format("Starting scanning IPs %d to %d.", ipFrom, ipTo)); + for(long ip = ipFrom; ip < ipTo; ip++) { + try { + InetAddress addr = NetHelpers.reverseInetFromInt(ip); + if(addr.isReachable(100)) { + Victim v = new Victim(addr); + hostnameFindQueue.add(v); // Get hostname async-ly + publishProgress(v); + } + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } + + @Override + protected void onProgressUpdate(Victim... victims) { + victimListAdapter.addDevicesToList(victims); + } + + @Override + protected void onPostExecute(Void ret) { + Log.d(TAG, String.format("Finished scanning IPs %d to %d.", ipFrom, ipTo)); + running = false; + onScannerFinish(); + } + + public boolean isRunning() { + return running; + } + } + + private void onScannerFinish() { + boolean allFinished = true; + for(IPScanner scanner : scanners) { + if(scanner.isRunning()) allFinished = false; + } + if(allFinished) { + Log.i(TAG, "All scanners finished"); + scanProgressBar.setVisibility(View.INVISIBLE); + scanProgressText.setText(""); + scanProgressRefresh.setEnabled(true); + + setProgressBarIndeterminateVisibility(false); + } + } + + private void startScanners() { + victimListAdapter.clearDeviceList(); + // Start IP Scanners + long ip = spoof.getMyIpReverseInt(); + long baseIp = ip & spoof.getMySubnetReverseInt(); // Bottom possble IP + long topIp = baseIp | (0xffffffffL >> spoof.getMySubnet()); // Top possible IP + /* + * A little note here. The logical way to store IP addrs in ints (the 'reverse' commands) + * is the opposite to the one used by Android functions (the non reverse ones). The difference + * is the endianness. + */ + + // Create as many scanners as user asked. + int numScanners; + try { + numScanners = Integer.valueOf(PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("ipScanThreads", "4")); + } catch(NumberFormatException e) { + numScanners = 4; + } + if(numScanners < 1) numScanners = 1; + if(numScanners > 40) numScanners = 40; + scanners = new IPScanner[numScanners]; + + long range = (topIp - baseIp) / scanners.length; + for(int i = 0; i < scanners.length - 1; i++) { + scanners[i] = new IPScanner(baseIp + (range * i), baseIp + (range * (i+1))); + } + // Make sure that none are left out. + scanners[scanners.length - 1] = new IPScanner(baseIp + (range * (scanners.length - 1)), topIp + 1); + + // Start + for(IPScanner scanner : scanners) { + AsyncTaskHelper.execute(scanner); + } + + scanProgressBar.setVisibility(View.VISIBLE); + scanProgressText.setText(R.string.scanning); + scanProgressRefresh.setEnabled(false); + + setProgressBarIndeterminateVisibility(true); + } + + @Override + public void onClick(View v) { + switch(v.getId()) { + case R.id.scanProgressRefresh: + startScanners(); + break; + } + } + + private static final int DIALOG_GETIP = 0; + + @Override + public Dialog onCreateDialog(int id, Bundle args) { + super.onCreateDialog(id, args); + switch(id) { + case DIALOG_GETIP: + LayoutInflater inflater = LayoutInflater.from(this); + Builder builder = new Builder(this); + View layout = inflater.inflate(R.layout.customip, null); + builder.setView(layout).setTitle(R.string.enterip); + final EditText ip = (EditText) layout.findViewById(R.id.ipBox); + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + try { + goToNextStep(new Victim(InetAddress.getByName(ip.getText().toString()))); + } catch (UnknownHostException e) { + e.printStackTrace(); + Log.e(TAG, "Incorrect IP given."); + Toast.makeText(VictimSelector.this, "Please enter a valid IP address", Toast.LENGTH_LONG).show(); + } + } + }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { } + }); + + return builder.show(); + default: + return null; + } + } + + /** + * Goes to the next step of the setup process. null means everyone. + * @param victim + */ + private void goToNextStep(Victim victim) { + spoof.setVictim(victim); + Intent intent = new Intent(this, SpoofRunning.class); + intent.putExtra(SpoofRunning.EXTRA_SPOOFDATA, spoof); + startActivity(intent); + } + + LinkedBlockingQueue hostnameFindQueue = new LinkedBlockingQueue(); + + private final AsyncTask hostnameFinder = new AsyncTask() { + @Override + protected Void doInBackground(Void... params) { + Log.i(TAG, "Starting to find hostnames"); + while(!isCancelled()) { + Victim victim = null; + try { + victim = hostnameFindQueue.poll(100, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if(victim != null) { + Log.v(TAG, "Finding hostname for " + victim.getIp().getHostAddress()); + victim.setHostname(victim.getIp().getHostName()); + Log.v(TAG, "IP " + victim.getIp().getHostAddress() + " = " + victim.getHostname()); + publishProgress(victim); + } + } + return null; + } + + @Override + protected void onProgressUpdate(Victim... victim) { + super.onProgressUpdate(victim); + victimListAdapter.notifyDataSetChanged(); + } + }; +} diff --git a/src/uk/digitalsquid/netspoofer/YoutubeSelector.java b/src/uk/digitalsquid/netspoofer/YoutubeSelector.java new file mode 100644 index 0000000..fcf9ca5 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/YoutubeSelector.java @@ -0,0 +1,92 @@ +package uk.digitalsquid.netspoofer; + +import uk.digitalsquid.netspoofer.config.LogConf; +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.Toast; + +/** + *

Selects a Youtube video. Currently uses the mobile site.

+ * + *

Youtube '?v=' code returned in {@link YoutubeSelector.CODE}

+ * @author william + * + */ +public class YoutubeSelector extends Activity implements LogConf { + + /** + * The extra the YT code is returned in. + */ + public static final String CODE = "code"; + + WebView web; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.youtube); + + web = (WebView) findViewById(R.id.web); + + web.setWebViewClient(wvc); + web.getSettings().setJavaScriptEnabled(true); + web.getSettings().setBuiltInZoomControls(true); + web.loadUrl("http://m.youtube.com"); + + } + + WebViewClient wvc = new WebViewClient() { + @Override + public void onLoadResource(WebView view, String url) { + super.onLoadResource(view, url); + if(url.contains("/watch")) { // Probably is a video page + Uri uri = Uri.parse(url); + try { + String videoID = uri.getQueryParameter("v"); // V is the video ID + if(videoID != null) { // Send back result + Intent intent = new Intent(); + intent.putExtra(CODE, videoID); + YoutubeSelector.this.setResult(RESULT_OK, intent); + + Log.i(TAG, "Found video " + videoID + " at " + url); + Toast.makeText(getApplicationContext(), "Got video", Toast.LENGTH_LONG).show(); + + YoutubeSelector.this.finish(); + } + } catch(UnsupportedOperationException e) { } + } + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + view.loadUrl(url); + return true; + } + }; + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.youtube, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.goback: + web.loadUrl("http://m.youtube.com"); + return true; + default: + return super.onOptionsItemSelected(item); + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/config/ChrootConfig.java b/src/uk/digitalsquid/netspoofer/config/ChrootConfig.java new file mode 100644 index 0000000..cef0386 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/ChrootConfig.java @@ -0,0 +1,169 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Build; +import android.preference.PreferenceManager; +import android.util.Log; +import android.widget.Toast; + +/** + * A class to hold the configuration; It is pulled from the shared preferences. + * @author william + * + */ +public final class ChrootConfig implements Config { + static ChrootConfig DEFAULTS = null; + + private String loopdev; + private int loopnum; + + private String debianMount; + private String debianImage; + + private String iface; + + private final Map values = new HashMap(); + + public ChrootConfig(Context context) { + if(DEFAULTS == null) DEFAULTS = new ChrootConfig("/dev/block/loop250", 250, "/data/local/mnt", getDebImgPath(context), "eth0"); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + loopdev = prefs.getString("loopdev", DEFAULTS.loopdev); + if(loopdev.equals("")) loopdev = DEFAULTS.loopdev; + values.put("LOOPDEV", loopdev); + + File folder = context.getExternalFilesDir(null); + Log.i(TAG, "Data folder is " + folder + ", absolute path is " + folder.getAbsolutePath()); + + try { + // loopnum = prefs.getInt("loopnum", DEFAULTS.loopnum); + loopnum = Integer.parseInt(prefs.getString("loopnum", "" + DEFAULTS.loopnum)); + } catch (NumberFormatException e) { + loopnum = DEFAULTS.loopnum; + Toast.makeText(context, "Invalid loop device number, using default", Toast.LENGTH_SHORT).show(); + } catch (ClassCastException e) { + loopnum = DEFAULTS.loopnum; + Toast.makeText(context, "Invalid loop device number, using default", Toast.LENGTH_SHORT).show(); + } + if(prefs.getString("loopnum", "").equals("")) loopnum = DEFAULTS.loopnum; + values.put("LOOPNUM", "" + loopnum); + + debianMount = prefs.getString("debianMount", DEFAULTS.debianMount); + if(debianMount.equals("")) debianMount = DEFAULTS.debianMount; + values.put("DEB", debianMount); + + debianImage = prefs.getString("debianImage", DEFAULTS.debianImage); + if(debianImage.equals("")) debianImage = DEFAULTS.debianImage; + values.put("DEBIMG", debianImage); + + iface = prefs.getString("iface", DEFAULTS.iface); + if(iface.equals("")) iface = DEFAULTS.iface; + // values.put("WLAN", iface); - Set in other places + } + + private static String getDebImgPath(Context context) { + // Android 4.3 goes all ???? with root trying to access the path given + // by SDK + if(Build.VERSION.SDK_INT >= 18) { // 4.3 + // TODO: Find out what exactly /storage/emulated/0 is and what this means + // for the root user + return "/sdcard/Android/data/uk.digitalsquid.netspoofer/files/" + Config.DEB_IMG; + } + return context.getExternalFilesDir(null).getAbsolutePath() + "/" + Config.DEB_IMG; + } + + private ChrootConfig(String loopdev, int loopnum, String debianMount, String debianImage, String iface) { + this.loopdev = loopdev; + this.loopnum = loopnum; + this.debianMount = debianMount; + this.debianImage = debianImage; + this.iface = iface; + values.put("LOOPDEV", loopdev); + values.put("LOOPNUM", "" + loopnum); + values.put("DEB", debianMount); + values.put("DEBIMG", debianImage); + // values.put("WLAN", iface); - Set in other places + } + + /** + * Gets the location of the loop device + * @return + */ + public String getLoopdev() { + return loopdev; + } + + /** + * Gets the loop device number + * @return + */ + public int getLoopNum() { + return loopnum; + } + + /** + * Gets the location where debian is mounted + * @return + */ + public String getDebianMount() { + return debianMount; + } + + /** + * Gets the location of the debian image on the SD card + * @return + */ + public String getDebianImage() { + return debianImage; + } + + /** + * Adds busybox to the values, as found in FileFinder. + */ + private void addBBToValues() { + if(!FileFinder.BUSYBOX.equals("")) // Leave undefined. This will cause the shell scripts to use the system utils instead, with dragons ahead. + values.put("BB", FileFinder.BUSYBOX); + } + + public Map getValues() { + addBBToValues(); + return values; + } + + public String[] getExecValues() { + addBBToValues(); + String[] vals = new String[values.size()]; + + int i = 0; + for(String key : values.keySet()) { + vals[i++] = String.format("%s=%s", key, values.get(key)); + } + + return vals; + } +} diff --git a/src/uk/digitalsquid/netspoofer/config/ChrootManager.java b/src/uk/digitalsquid/netspoofer/config/ChrootManager.java new file mode 100644 index 0000000..0d32a64 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/ChrootManager.java @@ -0,0 +1,291 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import uk.digitalsquid.netspoofer.spoofs.CustomGSearchSpoof; +import uk.digitalsquid.netspoofer.spoofs.CustomGalleryImageChange; +import uk.digitalsquid.netspoofer.spoofs.CustomImageChange; +import uk.digitalsquid.netspoofer.spoofs.CustomTextChange; +import uk.digitalsquid.netspoofer.spoofs.IPRedirectSpoof; +import uk.digitalsquid.netspoofer.spoofs.MultiSpoof; +import uk.digitalsquid.netspoofer.spoofs.SimpleScriptedSpoof; +import uk.digitalsquid.netspoofer.spoofs.Spoof; +import uk.digitalsquid.netspoofer.spoofs.SpoofData; +import uk.digitalsquid.netspoofer.spoofs.SquidScriptSpoof; +import uk.digitalsquid.netspoofer.spoofs.VideoChange; +import android.content.Context; +import android.os.Build; +import android.util.Log; + +public class ChrootManager implements Config { + private final Context context; + public final ChrootConfig config; + + public ChrootManager(Context context, ChrootConfig config) { + this.context = context; + this.config = config; + } + + /** + * Sets up the shell's environment variables, mounts the image, and chroots into debian. + * @return true of mount completed successfully. + * @throws IOException + */ + public synchronized boolean start() throws IOException { + Map env = config.getValues(); + // Setup & mount DEB. + FileFinder.initialise(context.getApplicationContext()); // In case of weird android instancing + ProcessRunner.runProcess(context, env, FileFinder.SU, "-c", FileInstaller.getScriptPath(context, "mount") + " " + FileInstaller.getScriptPath(context, "config")); // Pass config script as arg. + + try { Thread.sleep(700); } catch (InterruptedException e) { e.printStackTrace(); } + return new File(config.getDebianMount() + "/rewriters").exists(); + } + + /** + * Stops the chroot. + * @throws IOException + */ + public synchronized int stop() throws IOException { + Map env = config.getValues(); + FileFinder.initialise(context.getApplicationContext()); // In case of weird android instancing + return ProcessRunner.runProcess(context, env, FileFinder.SU, "-c", FileInstaller.getScriptPath(context, "umount") + " " + FileInstaller.getScriptPath(context, "config")); + } + + public ArrayList getSpoofList() { + Log.i(TAG, "Searching for spoofs to use..."); + final ArrayList spoofs = new ArrayList(); + + // 1. Scan squid rewriters + File rewriteDir = new File(config.getDebianMount() + "/rewriters"); + if(rewriteDir.exists()) { + for(String file : rewriteDir.list(new FilenameFilter() { + @Override + public boolean accept(File dir, String filename) { + return filename.endsWith(".txt"); + } + })) { + Log.v(TAG, "Spoof: " + file); + try { + List lines = IOHelpers.readFileToLines(rewriteDir.getAbsolutePath() + "/" + file); + if(lines.size() < 2) { + Log.e(TAG, "Malformed description file for " + file + "."); + continue; + } + spoofs.add(new SquidScriptSpoof(lines.get(1), lines.get(2), lines.get(0))); + } catch (IOException e) { + e.printStackTrace(); + Log.e(TAG, "Couldn't read info for spoof " + file + "."); + } + } + } + + spoofs.add(new CustomGSearchSpoof()); + spoofs.add(new CustomImageChange()); + spoofs.add(new CustomGalleryImageChange()); + // This breaks IOHelpers.runProcessOutputToLines on Android 4.0 for some reason, so temporarily disabling it. + if(Build.VERSION.SDK_INT < 14) spoofs.add(new VideoChange()); + spoofs.add(new CustomTextChange()); + + // General spoof - only arpspoof. + spoofs.add(new SimpleScriptedSpoof( + "Redirect traffic through phone", + "Don't do anything to the traffic, only redirect other people's traffic through the phone. Useful in combination with 'Shark' app.", + "spoof %s %s 0", "\n")); + + // IP Redirect spoofs. + spoofs.add(new IPRedirectSpoof("All sites -> other website", "Redirect all websites to another website")); + + Collections.sort(spoofs); + spoofs.add(0, new MultiSpoof()); + + return spoofs; + } + + public boolean isSpoofRunning() { + return spoofRunning; + } + + private boolean spoofRunning = false; + private Object spoofLock = new Object(); + + Process su; + BufferedReader cout; + BufferedReader cerr; + OutputStreamWriter cin; + + public void startSpoof(SpoofData spoof) throws IOException { + if(spoofRunning) throw new IllegalStateException("Spoof already running"); + FileFinder.initialise(context.getApplicationContext()); // In case of weird android instancing + synchronized(spoofLock) { + spoofRunning = true; + + if(Build.VERSION.SDK_INT >= 9) { // 2.2 doesn't like this method + ProcessBuilder pb = new ProcessBuilder(FileFinder.SU, "-c", + FileInstaller.getScriptPath(context, "start") + " " + FileInstaller.getScriptPath(context, "config") + " " + + spoof.getSpoof().getSpoofCmd(spoof.getVictimString(), spoof.getRouterIpString())); // Pass config script as arg. + + // We now write the env to a config file, which is loaded in. + Map env = new HashMap(); + + Map configValues = config.getValues(); + if(configValues != null) env.putAll(configValues); + + Map customEnv = spoof.getSpoof().getCustomEnv(); + if(customEnv != null) env.putAll(customEnv); + + if(!spoof.isRunningPassively()) { + env.put("WLAN", spoof.getMyIface()); + env.put("IP", spoof.getMyIp().getHostAddress()); + env.put("SUBNET", spoof.getMySubnetBaseAddressString()); + env.put("MASK", spoof.getMySubnetString()); + env.put("SHORTMASK", String.valueOf(spoof.getMySubnet())); + } + + ProcessRunner.writeEnvConfigFile(context, env); + + su = pb.start(); + } else { + Map systemEnv = System.getenv(); // We also must include this + Map combinedEnv = new HashMap(); + + if(systemEnv != null) combinedEnv.putAll(systemEnv); + Map configValues = config.getValues(); + if(configValues != null) combinedEnv.putAll(configValues); + + Map customEnv = spoof.getSpoof().getCustomEnv(); + if(customEnv != null) combinedEnv.putAll(customEnv); + + if(!spoof.isRunningPassively()) { + combinedEnv.put("WLAN", spoof.getMyIface()); + combinedEnv.put("IP", spoof.getMyIp().getHostAddress()); + combinedEnv.put("SUBNET", spoof.getMySubnetBaseAddressString()); + combinedEnv.put("MASK", spoof.getMySubnetString()); + combinedEnv.put("SHORTMASK", String.valueOf(spoof.getMySubnet())); + } + + String[] envArray = new String[combinedEnv.size()]; + int i = 0; + for(String key : combinedEnv.keySet()) { + envArray[i++] = String.format("%s=%s", key, combinedEnv.get(key)); + } + su = Runtime.getRuntime().exec(new String [] { + FileFinder.SU, "-c", + FileInstaller.getScriptPath(context, "start") + " " + FileInstaller.getScriptPath(context, "config") + " " + + spoof.getSpoof().getSpoofCmd(spoof.getVictimString(), spoof.getRouterIpString()), // Pass config script as arg. + }, envArray); + } + cout = new BufferedReader(new InputStreamReader(su.getInputStream())); + cerr = new BufferedReader(new InputStreamReader(su.getErrorStream())); + cin = new OutputStreamWriter(su.getOutputStream()); + } + } + + /** + * Stops the current spoof. + * @return The final list of output messages + * @throws IOException + */ + public void stopSpoof(SpoofData spoof) throws IOException { + if(!spoofRunning) return; // Don't do anything. + synchronized(spoofLock) { + cin.write(spoof.getSpoof().getStopCmd()); + cin.flush(); + + try { + su.waitFor(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + /** + * Stops the current spoof. + * @return The final list of output messages + * @throws IOException + */ + public ArrayList finishStopSpoof() throws IOException { + synchronized(spoofLock) { + ArrayList finalOutput = getNewSpoofOutput(); + + try { + cin.close(); + cout.close(); + cerr.close(); + } catch (IOException e) { + } + + cin = null; + cout = null; + cerr = null; + su = null; + + spoofRunning = false; + + return finalOutput; + } + } + + + /** + * Checks if the process is stopped. Doesn't actually close anything, though. + * stopSpoof must be called with onlyClosePipes true if this returns true. + * @return + */ + public boolean checkIfStopped() { + if(!spoofRunning) return false; + + if(su == null) return false; + try { + su.exitValue(); + } catch (IllegalThreadStateException e) { + return false; + } + return true; + } + + public synchronized ArrayList getNewSpoofOutput() throws IOException { + ArrayList items = new ArrayList(); + + while(cerr.ready()) { + String line = cerr.readLine(); + items.add(line); + } + while(cout.ready()) { + String line = cout.readLine(); + items.add(line); + } + return items; + } +} diff --git a/src/uk/digitalsquid/netspoofer/config/Config.java b/src/uk/digitalsquid/netspoofer/config/Config.java new file mode 100644 index 0000000..340248b --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/Config.java @@ -0,0 +1,45 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +/** + * Global config of variables etc.. + * @author william + * + */ +public interface Config extends LogConf { + public static final String DEB_IMG = "img/debian.img"; + public static final String DEB_IMG_GZ = "img/debian.img.gz"; + public static final String DEB_VERSION_FILE = "img/version"; + public static final String SF_DEB_IMG_URL = "http://sourceforge.net/projects/netspoof/files/debian-images/debian-0.8.2.img.gz/download"; + public static final String SF_DEB_IMG_URL_NOZIP = "http://sourceforge.net/projects/netspoof/files/debian-images/debian-0.8.2.img/download"; + + /** + * For incremental upgrades + */ + public static final String UPGRADE_URI_FORMAT = "http://sourceforge.net/projects/netspoof/files/update/%d-%d.zip/download"; + // public static final String UPGRADE_URI_FORMAT = "http://digitalsquid.co.uk/download/android-netspoof/upgrade/%d-%d.zip"; + public static final String UPGRADE_URI_FAIL = "http://sourceforge.net/projects/netspoof/files/"; + + public static final int DEB_IMG_URL_SIZE = 440320000; + public static final int DEB_IMG_URL_VERSION = 13; +} diff --git a/src/uk/digitalsquid/netspoofer/config/ConfigChecker.java b/src/uk/digitalsquid/netspoofer/config/ConfigChecker.java new file mode 100644 index 0000000..d566879 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/ConfigChecker.java @@ -0,0 +1,139 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; + +import uk.digitalsquid.netspoofer.InstallService; +import android.app.ActivityManager; +import android.app.ActivityManager.RunningServiceInfo; +import android.content.Context; +import android.os.Environment; +import android.util.Log; + +public final class ConfigChecker implements Config { + + public static final boolean checkInstalled(Context context) { + if(getSDStatus(false)) { + final File sd = context.getExternalFilesDir(null); + if(sd == null) return false; + File debian = new File(sd.getAbsolutePath() + "/" + DEB_VERSION_FILE); + Log.i(TAG, "Checking if file " + debian.getAbsolutePath() + " exists"); + if(debian.exists()) return true; + } + return false; + } + + public static final int getVersionNumber(Context context) { + if(getSDStatus(false)) { + final File sd = context.getExternalFilesDir(null); + if(sd == null) return -1; + File version = new File(sd.getAbsolutePath() + "/" + DEB_VERSION_FILE); + Log.i(TAG, "Getting version number from file"); + String ver; + try { + FileInputStream verReader = new FileInputStream(version); + BufferedReader reader = new BufferedReader(new InputStreamReader(verReader)); + ver = reader.readLine(); + reader.close(); + verReader.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return -1; + } catch (IOException e) { + e.printStackTrace(); + return -1; + } + if(ver != null) { + try { + return Integer.parseInt(ver); + } catch(NumberFormatException e) { + e.printStackTrace(); + return -1; + } + } + } + return -1; + } + + public static final boolean checkInstalledLatest(Context context) { + if(getSDStatus(false)) { + final File sd = context.getExternalFilesDir(null); + if(sd == null) return false; + File version = new File(sd.getAbsolutePath() + "/" + DEB_VERSION_FILE); + Log.i(TAG, "Checking if file " + version.getAbsolutePath() + " is latest"); + String ver; + try { + FileInputStream verReader = new FileInputStream(version); + BufferedReader reader = new BufferedReader(new InputStreamReader(verReader)); + ver = reader.readLine(); + reader.close(); + verReader.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return false; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + if(ver != null) { + try { + if(Integer.parseInt(ver) >= DEB_IMG_URL_VERSION) return true; + } catch(NumberFormatException e) { + e.printStackTrace(); + return false; + } + } + } + return false; + } + + public static final boolean getSDStatus(final boolean checkWritable) { + String state = Environment.getExternalStorageState(); + + if (Environment.MEDIA_MOUNTED.equals(state)) { + // We can read and write the media + return true; + } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { + return !checkWritable; + } else { + return false; + } + } + + private static ActivityManager am; + public static final boolean isInstallServiceRunning(Context context) { + if(am == null) + am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + for (RunningServiceInfo service : am.getRunningServices(Integer.MAX_VALUE)) { + if (InstallService.class.getName().equals(service.service.getClassName())) { + return true; + } + } + return false; + } +} diff --git a/src/uk/digitalsquid/netspoofer/config/FileFinder.java b/src/uk/digitalsquid/netspoofer/config/FileFinder.java new file mode 100644 index 0000000..17a39d4 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/FileFinder.java @@ -0,0 +1,180 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.util.Log; + +public final class FileFinder implements LogConf { + private FileFinder() { } + private static boolean initialised = false; + + private static Context context; + + public static String SU = ""; + public static String BUSYBOX = ""; + + /** + * The system's version of BB, if it exists. + */ + public static String SYSTEM_BUSYBOX = ""; + + private static final String[] BB_PATHS = { "/system/bin/busybox", "/system/xbin/busybox", "/system/sbin/busybox", "/vendor/bin/busybox", "busybox" }; + private static final String[] SU_PATHS = { "/system/bin/su", "/system/xbin/su", "/system/sbin/su", "/vendor/bin/su", "su" }; + + /** + * Searches for the busybox executable. Uses the builtin one if user wants. This is also the default behaviour. + * @return + */ + private static final String findBusybox(boolean useLocal, SharedPreferences prefs) { + if(useLocal && prefs != null) { + if(prefs.getBoolean("builtinbusybox", true)) { + String myBB = FileInstaller.getScriptPath(context, "busybox"); + Log.i(TAG, "Using local copy of BB"); + return myBB; // Found our copy of BB + } + String customPath = prefs.getString("pathToBB", ""); + if(!customPath.equals("") && new File(customPath).exists()) return customPath; + } + for(String bb : BB_PATHS) { + if(new File(bb).exists()) { + return bb; + } + } + return ""; + } + + /** + * Searches for the su executable + * @return + */ + private static final String findSu(SharedPreferences prefs) { + if(prefs != null) { + String customPath = prefs.getString("pathToSu", ""); + if(!customPath.equals("") && new File(customPath).exists()) return customPath; + } + for(String su : SU_PATHS) { + if(new File(su).exists()) { + return su; + } + } + return ""; + } + + public static final void initialise(Context appContext) throws FileNotFoundException { + FileFinder.context = appContext; + if(initialised) { + return; + } + initialised = true; + loadPaths(); + } + + /** + * (re)loads the SU and BB paths, perhaps after a preference change. + * @throws FileNotFoundException + */ + public static final void loadPaths() throws FileNotFoundException { + SharedPreferences prefs = null; + if(context != null) { + prefs = PreferenceManager.getDefaultSharedPreferences(context); + } + BUSYBOX = findBusybox(true, prefs); + SYSTEM_BUSYBOX = findBusybox(false, prefs); + if(BUSYBOX.equals("")) { + throw new FileNotFoundException("busybox"); + } + SU = findSu(prefs); + if(SU.equals("")) { + throw new FileNotFoundException("su"); + } + try { + checkBBInstalledFunctions(); + } catch (FileNotFoundException e) { // If fails with this BB, try system BB. + BUSYBOX = SYSTEM_BUSYBOX; + checkBBInstalledFunctions(); // Let this one throw error + } + } + + /** + * Checks that the necessary BB commands are available + * @throws FileNotFoundException + */ + static final void checkBBInstalledFunctions() throws FileNotFoundException { + List result = new LinkedList(); + try { + ProcessRunner.runProcess(context, null, result, BUSYBOX); + } catch (IOException e) { + Log.e(TAG, "Failed to check BB programs, probably as BB doesn't exist?"); + e.printStackTrace(); + } + String requiredApplets[] = { + "chroot", + "losetup", + "mount", + "mkdir", + "mknod", + "cp", + }; + boolean foundApplets[] = new boolean[requiredApplets.length]; + for(String line : result) { + int i = 0; + for(String applet : requiredApplets) { + if(line.contains(applet)) + foundApplets[i] = true; + i++; + } + } + int i = 0; + for(boolean found : foundApplets) { + if(!found) throw new FileNotFoundException("bb:"+requiredApplets[i]); + i++; + } + } + + /** + * Initialise that doesn't search custom paths. Not recommended. + * @throws FileNotFoundException + */ + public static final void initialise() throws FileNotFoundException { + if(initialised) { + return; + } + initialised = true; + BUSYBOX = findBusybox(true, null); + if(BUSYBOX.equals("")) { + throw new FileNotFoundException("busybox"); + } + SU = findSu(null); + if(SU.equals("")) { + throw new FileNotFoundException("su"); + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/config/FileInstaller.java b/src/uk/digitalsquid/netspoofer/config/FileInstaller.java new file mode 100644 index 0000000..b13bb70 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/FileInstaller.java @@ -0,0 +1,83 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import uk.digitalsquid.netspoofer.JNI; + +import android.content.Context; +import android.content.res.Resources; +import android.util.Log; + +public final class FileInstaller implements LogConf { + private static final String BIN_DIR = "/bin"; + private final Context context; + + public FileInstaller(Context context) throws FileNotFoundException { + this.context = context; + try { + new File(context.getFilesDir().getParent() + BIN_DIR).mkdir(); + } catch (NullPointerException e) { + // One of the above fileops failed, most likely due to broken phone. + Log.e(TAG, "Failed to create binary directory!"); + } + } + + private void installFile(String filename, boolean executable, int id) throws Resources.NotFoundException, IOException { + installFile(filename, id); + if(executable) JNI.setExecutable(filename); + } + + public void installScript(String scriptName, int id) throws Resources.NotFoundException, IOException { + String scriptPath = getScriptPath(scriptName); + installFile(scriptPath, true, id); + } + + private void installFile(String filename, int id) throws Resources.NotFoundException, IOException { + InputStream is = context.getResources().openRawResource(id); + File outFile = new File(filename); + outFile.createNewFile(); + Log.d(TAG, "Copying file '"+filename+"' ..."); + byte buf[] = new byte[1024]; + int len; + OutputStream out = new FileOutputStream(outFile); + while((len = is.read(buf)) > 0) { + out.write(buf, 0, len); + } + out.close(); + is.close(); + } + + public static String getScriptPath(Context context, String scriptName) { + return context.getFilesDir().getParent() + BIN_DIR + "/" + scriptName; + } + + private String getScriptPath(String scriptName) { + return getScriptPath(context, scriptName); + } +} diff --git a/src/uk/digitalsquid/netspoofer/config/IOHelpers.java b/src/uk/digitalsquid/netspoofer/config/IOHelpers.java new file mode 100644 index 0000000..2c5c9de --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/IOHelpers.java @@ -0,0 +1,119 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +public final class IOHelpers { + private IOHelpers() {} + + /** + * Reads a whole file from is, and closes the stream. + * @param is + * @return + * @throws IOException + */ + public static final String readFileContents(InputStream is) throws IOException { + StringBuffer out = new StringBuffer(); + byte[] b = new byte[256]; + for (int n; (n = is.read(b)) != -1;) { + out.append(new String(b, 0, n)); + } + is.close(); + return out.toString(); + } + + /** + * Reads a whole file into an array of lines. + * @param filename + * @return + * @throws IOException + */ + public static final List readFileToLines(String filename) throws IOException { + FileReader reader = new FileReader(filename); + BufferedReader br = new BufferedReader(reader); + + List lines = new ArrayList(); + String line; + while((line = br.readLine()) != null) { + lines.add(line); + } + br.close(); + reader.close(); + return lines; + } + + public static final List runProcessOutputToLines(List args) throws IOException { + ProcessBuilder pb = new ProcessBuilder(args); + + pb.redirectErrorStream(true); + Process proc = pb.start(); + BufferedReader cout = new BufferedReader(new InputStreamReader(proc.getInputStream())); + try { + proc.waitFor(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + List lines = new ArrayList(); + String line; + while((line = cout.readLine()) != null) { + lines.add(line); + } + cout.close(); + return lines; + } + + public static final int runProcess(List args) throws IOException { + ProcessBuilder pb = new ProcessBuilder(args); + + Process proc = pb.start(); + try { + return proc.waitFor(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return -1; + } + + public static final void deleteFolder(File dir) { + if(!dir.exists()) return; + if(!dir.isDirectory()) { + dir.delete(); + return; + } + for(String child : dir.list()) { + File sub = new File(dir, child); + if(sub.isDirectory()) { + deleteFolder(sub); + sub.delete(); + } + else sub.delete(); + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/config/LogConf.java b/src/uk/digitalsquid/netspoofer/config/LogConf.java new file mode 100644 index 0000000..5f5b3ca --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/LogConf.java @@ -0,0 +1,26 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +public interface LogConf { + public static final String TAG = "android-netspoof"; +} diff --git a/src/uk/digitalsquid/netspoofer/config/NetHelpers.java b/src/uk/digitalsquid/netspoofer/config/NetHelpers.java new file mode 100644 index 0000000..b4d9a15 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/NetHelpers.java @@ -0,0 +1,280 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Serializable; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import android.util.Log; + +public final class NetHelpers implements LogConf { + private NetHelpers() {} + + public static final NetworkInterface getIface(InetAddress iface) { + try { + return NetworkInterface.getByInetAddress(iface); + } catch (SocketException e) { + e.printStackTrace(); + return null; + } + } + + public static final InetAddress inetFromInt(int ip) throws UnknownHostException { + return InetAddress.getByAddress(new byte[] { + (byte) ((ip >> 0 ) & 0xFF), + (byte) ((ip >> 8 ) & 0xFF), + (byte) ((ip >> 16) & 0xFF), + (byte) ((ip >>>24) & 0xFF), + }); + } + + public static final long inetFromByte(byte[] ip) { + return + ((long)(ip[0]&0xFF) << 0 ) + + ((long)(ip[1]&0xFF) << 8 ) + + ((long)(ip[2]&0xFF) << 16) + + ((long)(ip[3]&0xFF) << 24); + } + + public static final InetAddress reverseInetFromInt(int ip) throws UnknownHostException { + return reverseInetFromInt((long)ip); + } + public static final InetAddress reverseInetFromInt(long ip) throws UnknownHostException { + return InetAddress.getByAddress(new byte[] { + (byte) ((ip >>>24) & 0xFF), + (byte) ((ip >> 16) & 0xFF), + (byte) ((ip >> 8 ) & 0xFF), + (byte) ((ip >> 0 ) & 0xFF), + }); + } + + /** + * + * @param ip + * @return a long value, to avoid IP signed-ness + */ + public static final long reverseInetFromByte(byte[] ip) { + return + ((long)(ip[0]&0xFF) << 24) + + ((long)(ip[1]&0xFF) << 16) + + ((long)(ip[2]&0xFF) << 8 ) + + ((long)(ip[3]&0xFF) << 0 ); + } + + public static final class GatewayData implements Serializable { + private static final long serialVersionUID = -2588873022535534899L; + + private final InetAddress gateway; + private final String subnet; + + public GatewayData(InetAddress gateway, String subnet) { + this.gateway = gateway; + this.subnet = subnet; + } + + public InetAddress getGateway() { + return gateway; + } + + public String getSubnet() { + return subnet; + } + } + + /** + * Represents an entry in the route table. + * @author william + * + */ + static final class RouteEntry implements Serializable { + + private static final long serialVersionUID = 7930709441175690366L; + + private String destination; + private String gateway; + private String genmask; + private String flags; + private String iface; + public void setDestination(String destination) { + this.destination = destination; + } + public String getDestination() { + return destination; + } + public void setGateway(String gateway) { + this.gateway = gateway; + } + public String getGateway() { + return gateway; + } + public void setGenmask(String genmask) { + this.genmask = genmask; + } + public String getGenmask() { + return genmask; + } + public void setFlags(String flags) { + this.flags = flags; + } + public String getFlags() { + return flags; + } + public void setIface(String iface) { + this.iface = iface; + } + public String getIface() { + return iface; + } + } + + /** + * + * @param iface + * @return + * @throws UnknownHostException + */ + public static final GatewayData getDefaultGateway(NetworkInterface iface) throws UnknownHostException { + if(iface == null) throw new IllegalArgumentException("iface is null"); + + try { FileFinder.initialise(); } catch (FileNotFoundException e1) { } + + final String ifacename = iface.getDisplayName(); + Log.d(TAG, "Checking for routes on iface " + ifacename); + + ArrayList routes = getRoutes(); + + String gateway = "", subnet = ""; + for(RouteEntry route : routes) { + if(!route.getIface().equalsIgnoreCase(ifacename)) continue; // Ignore routes not on wifi + if(route.getFlags().contains("G")) { // This is a route with a gateway + gateway = route.getGateway(); + } + if(route.getFlags().equals("U")) { + subnet = route.getGenmask(); + } + } + if(gateway.equals("")) { // Try again + Log.i(TAG, "Trying more agressive approach to finding gateway"); + for(RouteEntry route : routes) { + if(!route.getIface().equalsIgnoreCase(ifacename)) continue; // Ignore routes not on wifi + if(!route.getGateway().equals("0.0.0.0")) { // Just try the first proper gateway + gateway = route.getGateway(); + break; + } + } + } + if(subnet.equals("")) { // Try again + Log.i(TAG, "Trying more agressive approach to finding subnet"); + for(RouteEntry route : routes) { + if(!route.getIface().equalsIgnoreCase(ifacename)) continue; // Ignore routes not on wifi + if(!route.getGateway().equals("0.0.0.0")) { // Just try the first proper subnet mask + subnet = route.getGenmask(); + break; + } + } + } + return new GatewayData(InetAddress.getByName(gateway), subnet); + } + + public static final ArrayList getRoutes() throws UnknownHostException { + try { FileFinder.initialise(); } catch (FileNotFoundException e1) { } + + List routeArgs = new ArrayList(); + // If not using BB, don't add it. + if(!FileFinder.BUSYBOX.equals("")) routeArgs.add(FileFinder.BUSYBOX); + routeArgs.add("route"); + routeArgs.add("-n"); + + ArrayList routes = new ArrayList(); + try { + // Run route -n, get lines + List routeTable = IOHelpers.runProcessOutputToLines(routeArgs); + + int linePosition = 0; // Used to ignore the first 2 lines + for(String line : routeTable) { + if(linePosition++ < 2) continue; + String line2 = line.replaceAll("\\s+", " "); // Single space only between each part + Log.v(TAG, "Parsing routing line " + line2); + StringTokenizer parts = new StringTokenizer(line2, " "); + if(parts.countTokens() < 8) { // Should be 8 parts + Log.w(TAG, "Found incorrectly formatted route line!"); + continue; + } + + RouteEntry entry = new RouteEntry(); + entry.setDestination(parts.nextToken()); + entry.setGateway(parts.nextToken()); + entry.setGenmask(parts.nextToken()); + entry.setFlags(parts.nextToken()); + parts.nextToken(); // Unused parts + parts.nextToken(); + parts.nextToken(); + entry.setIface(parts.nextToken()); + routes.add(entry); + } + } catch (IOException e) { + e.printStackTrace(); + throw new UnknownHostException("Error executing 'route' command."); + } + + return routes; + } + + /** + * Checks for a file's existence on an HTTP server. + * @param file + * @param isFail If the redirected url = isFail, returns false + * @return + */ + public static final boolean checkFileExistsOnWeb(String file, String isFail) { + try { + URL upgradeUrl = new URL(file); + HttpURLConnection.setFollowRedirects(true); + HttpURLConnection conn = (HttpURLConnection) upgradeUrl.openConnection(); + conn.setConnectTimeout(5000); + conn.setRequestMethod("HEAD"); + + int code = conn.getResponseCode(); + URL url = conn.getURL(); + + if(isFail == null) isFail = ""; + + return code == HttpURLConnection.HTTP_OK && !url.toExternalForm().equals(isFail); + } catch (MalformedURLException e) { + Log.e(TAG, "Malformed URL", e); + } catch (IOException e) { + Log.d(TAG, "Failed to check for HTTP file, probably no internet."); + } + return false; + } +} diff --git a/src/uk/digitalsquid/netspoofer/config/ProcessRunner.java b/src/uk/digitalsquid/netspoofer/config/ProcessRunner.java new file mode 100644 index 0000000..1a9bd05 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/ProcessRunner.java @@ -0,0 +1,145 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import android.content.Context; +import android.os.Build; +import android.util.Log; + +public final class ProcessRunner implements LogConf { + private ProcessRunner() {} + + public static final int runProcess(Context context, String... args) throws IOException { + return runProcess(context, null, args); + } + + /** + * Runs a process with the given environment and args + * @param env + * @param args + * @return + * @throws IOException + */ + public static final int runProcess(Context context, Map env, String... args) throws IOException { + return runProcess(context, env, (List) null, args); + } + + /** + * Runs a process with an environment and saves the output to output. + * @param env The environment + * @param output A list to put the command's output in. + * @param args The program args + * @return + * @throws IOException + */ + public static final int runProcess(Context context, Map env, List output, String... args) throws IOException { + Process proc; + if(Build.VERSION.SDK_INT >= 9) { // 2.2 doesn't like this method + ProcessBuilder pb = new ProcessBuilder(args); + writeEnvConfigFile(context, env); + proc = pb.start(); + } else { + if(env != null) { + Map systemEnv = System.getenv(); // We also must include this + Map combinedEnv = new HashMap(); + combinedEnv.putAll(env); + combinedEnv.putAll(systemEnv); + + String[] envArray = new String[combinedEnv.size()]; + int i = 0; + for(String key : combinedEnv.keySet()) { + envArray[i++] = String.format("%s=%s", key, combinedEnv.get(key)); + } + proc = Runtime.getRuntime().exec(args, envArray); + } else { + proc = Runtime.getRuntime().exec(args); + } + } + BufferedReader cout = new BufferedReader(new InputStreamReader(proc.getInputStream())); + BufferedReader cerr = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + boolean running = true; + while(running) { + while(cout.ready()) { + String msg = cout.readLine(); + if(output != null) output.add(msg); + Log.d(TAG, "cout: " + msg); + } + while(cerr.ready()) { + String msg = cerr.readLine(); + if(output != null) output.add(msg); + Log.d(TAG, "cerr: " + msg); + } + try { + proc.exitValue(); + running = false; + cout.close(); + cerr.close(); + return proc.exitValue(); + } + catch (IllegalThreadStateException e) { } // Not done + try { Thread.sleep(50); } catch (InterruptedException e) { } + } + return 0; + } + + /** + * Writes the config file with the env paramaters. + * The config file is changed before the process is run now. + * This is because of Android 4.3 not liking environment variables. + * @param env + */ + public static final void writeEnvConfigFile(Context context, Map env) { + HashMap fullEnv = env == null ? + new HashMap() : + new HashMap(env); + fullEnv.put("PATH", "/usr/local/bin:/usr/bin:/usr/sbin:/bin:$PATH"); + fullEnv.put("TERM", "linux"); + fullEnv.put("HOME", "/root"); + String scriptPath = FileInstaller.getScriptPath(context, "config"); + FileWriter writer = null; + try { + writer = new FileWriter(scriptPath, false); + writer.write("# Config generated by writeEnvConfigFile\n"); + for(Entry entry : fullEnv.entrySet()) { + writer.write(String.format("export %s=\"%s\"\n", entry.getKey(), entry.getValue())); + } + writer.write("\n"); + } catch (FileNotFoundException e) { + Log.e(TAG, "Failed to write env config file", e); + } catch (IOException e) { + Log.e(TAG, "Failed to write env config file", e); + } finally { + if(writer != null) + try { writer.close(); } catch (IOException e) { } + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/config/UpgradeInstaller.java b/src/uk/digitalsquid/netspoofer/config/UpgradeInstaller.java new file mode 100644 index 0000000..406d24c --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/config/UpgradeInstaller.java @@ -0,0 +1,105 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.config; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +import uk.digitalsquid.netspoofer.InstallService.DLProgress; +import uk.digitalsquid.netspoofer.InstallService.DLProgressPublisher; +import android.content.Context; +import android.util.Log; + +/** + * Installs upgrades, copying files into the chroot. + * @author william + * + */ +public final class UpgradeInstaller implements Config { + + /** + * Exceptions describing what went wrong during an upgrade + * @author william + * + */ + public static class UpgradeException extends IOException { + private static final long serialVersionUID = 491497913367265516L; + + public static final int FAILED_TO_START = 1; + public static final int FAILED_TO_RUN_SCRIPT = 2; + + int reason; + + public UpgradeException(int reason) { + super(); + this.reason = reason; + } + } + + public static final void copyUpgrade(Context context, DLProgressPublisher callback, File src) throws UpgradeException { + ChrootManager chroot = new ChrootManager(context, new ChrootConfig(context)); + File dest = new File(chroot.config.getDebianMount()); + + boolean startFailed = false; + try { + startFailed = !chroot.start(); + } catch (IOException e) { + e.printStackTrace(); + startFailed = true; + } + if(startFailed) + throw new UpgradeException(UpgradeException.FAILED_TO_START); + + // Using arbitrary numbers here for progress + callback.publishDLProgress(new DLProgress(DLProgress.STATUS_PATCHING, 1, 4)); + + Map env = chroot.config.getValues(); + try { + if(ProcessRunner.runProcess(context, env, FileFinder.SU, "-c", + FileInstaller.getScriptPath(context, "applyupgrade") + " " + + FileInstaller.getScriptPath(context, "config") + " " + + src.getAbsolutePath() + " " + + dest.getAbsolutePath() + ) != 0) { + Log.w(TAG, "Upgrade script failed to run!"); + chroot.stop(); + throw new UpgradeException(UpgradeException.FAILED_TO_RUN_SCRIPT); + } + } catch (IOException e1) { + e1.printStackTrace(); + Log.w(TAG, "Upgrade script failed to run!", e1); + try { chroot.stop(); } catch (IOException e) { } + throw new UpgradeException(UpgradeException.FAILED_TO_RUN_SCRIPT); + } + + callback.publishDLProgress(new DLProgress(DLProgress.STATUS_PATCHING, 2, 4)); + + try { + chroot.stop(); + } catch (IOException e) { + e.printStackTrace(); + // No error needed - don't worry if umount failed. + } + callback.publishDLProgress(new DLProgress(DLProgress.STATUS_PATCHING, 3, 4)); + } +} diff --git a/src/uk/digitalsquid/netspoofer/misc/AsyncTaskHelper.java b/src/uk/digitalsquid/netspoofer/misc/AsyncTaskHelper.java new file mode 100644 index 0000000..b067419 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/misc/AsyncTaskHelper.java @@ -0,0 +1,82 @@ +package uk.digitalsquid.netspoofer.misc; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.concurrent.Executor; + +import uk.digitalsquid.netspoofer.config.LogConf; +import android.os.AsyncTask; +import android.util.Log; + +/** + * Provides helper methods for {@link AsyncTask} to do with differing API versions + * @author william + * + */ +public class AsyncTaskHelper implements LogConf { + + /** + * Better version of execute which copes with honeycomb and greater, which + * by default run methods in sequence. See + * http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor(java.util.concurrent.Executor, Params...) + * If Network Spoofer is ever upgraded to min API 11, this can be deleted and replaced with an actual method call. + * @param task + * @param args + */ + public static void execute(AsyncTask task, S... args) { + init(); + if(executeOnExecutor == null || THREAD_POOL_EXECUTOR == null) { + task.execute(args); + } else { + try { + executeOnExecutor.invoke(task, THREAD_POOL_EXECUTOR, args); + + // In error cases, invoke old method instead. + } catch (IllegalArgumentException e) { + Log.e(TAG, "Failed to invoke executeOnExecutor", e); + task.execute(args); + } catch (IllegalAccessException e) { + Log.e(TAG, "Failed to invoke executeOnExecutor", e); + task.execute(args); + } catch (InvocationTargetException e) { + Log.e(TAG, "Failed to invoke executeOnExecutor", e); + task.execute(args); + } + } + } + + private static boolean initialised = false; + + private static Method executeOnExecutor; + private static Executor THREAD_POOL_EXECUTOR; + + private static synchronized void init() { + if(initialised) return; + // Get AsyncTask.executeOnExecutor method - needed to correctly call parallel AsyncTasks + // on platforms that have this method. + try { + executeOnExecutor = AsyncTask.class.getMethod("executeOnExecutor", Executor.class, Object[].class); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + executeOnExecutor = null; + Log.i(TAG, "AsyncTask.executeOnExecutor method not found, will use AsyncTask.execute"); + } + + try { + THREAD_POOL_EXECUTOR = (Executor) AsyncTask.class.getField("THREAD_POOL_EXECUTOR").get(null); + } catch (IllegalArgumentException e) { + Log.w(TAG, "Failed to get THREAD_POOL_EXECUTOR", e); + } catch (SecurityException e) { + Log.w(TAG, "Failed to get THREAD_POOL_EXECUTOR", e); + } catch (IllegalAccessException e) { + Log.w(TAG, "Failed to get THREAD_POOL_EXECUTOR", e); + } catch (NoSuchFieldException e) { + Log.w(TAG, "Failed to get THREAD_POOL_EXECUTOR", e); + } + + Log.i(TAG, "Initiated AsyncTaskHelper"); + + initialised = true; + } +} diff --git a/src/uk/digitalsquid/netspoofer/misc/CheckedLinearLayout.java b/src/uk/digitalsquid/netspoofer/misc/CheckedLinearLayout.java new file mode 100644 index 0000000..9e3e017 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/misc/CheckedLinearLayout.java @@ -0,0 +1,65 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.misc; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.Checkable; +import android.widget.LinearLayout; + +/** + * A {@link LinearLayout} which forwards it checking abilities to a supplied subclass + * @author william + * + */ +public class CheckedLinearLayout extends LinearLayout implements Checkable { + + private Checkable check; + + public CheckedLinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean isChecked() { + if(check != null) return check.isChecked(); + return false; + } + + @Override + public void setChecked(boolean arg0) { + if(check != null) check.setChecked(arg0); + } + + @Override + public void toggle() { + if(check != null) check.toggle(); + } + + /** + * Sets the subclass to derive from + * @param check + */ + public void setCheckable(Checkable check) { + this.check = check; + } +} diff --git a/src/uk/digitalsquid/netspoofer/misc/UnZip.java b/src/uk/digitalsquid/netspoofer/misc/UnZip.java new file mode 100644 index 0000000..ce06b3b --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/misc/UnZip.java @@ -0,0 +1,78 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.misc; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import uk.digitalsquid.netspoofer.config.Config; +import android.util.Log; + +/** + * Simple zip archive unzipper + * @author william + * + */ +public final class UnZip implements Config { + private UnZip() {} + + private static final int BUFSIZE = 1024; + + public static final boolean unzipArchive(File archive, File destDir) throws IOException { + if(!destDir.exists()) destDir.mkdir(); + + ZipInputStream in = new ZipInputStream(new BufferedInputStream(new FileInputStream(archive))); + + byte buffer[] = new byte[BUFSIZE]; + + ZipEntry entry; + while((entry = in.getNextEntry()) != null) { + File extractTo = new File(destDir, entry.getName()); + if(entry.isDirectory()) { + extractTo.mkdir(); + continue; + } + extractTo.getParentFile().mkdirs(); + + Log.i(TAG, "Writing file " + extractTo); + + OutputStream out = new BufferedOutputStream(new FileOutputStream(extractTo)); + int count; + while((count = in.read(buffer, 0, BUFSIZE)) != -1) { + out.write(buffer, 0, count); + } + out.close(); + } + + in.close(); + + return true; + } + +} diff --git a/src/uk/digitalsquid/netspoofer/servicemsg/ImageLoader.java b/src/uk/digitalsquid/netspoofer/servicemsg/ImageLoader.java new file mode 100644 index 0000000..b5f4451 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/servicemsg/ImageLoader.java @@ -0,0 +1,47 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.servicemsg; + +import android.net.Uri; + +/** + * Loads an image from the user's gallery, saves it as a jpg and puts it in the debian images folder for use. + * @author william + * + */ +public class ImageLoader extends ServiceMsg { + + private static final long serialVersionUID = -2360307367080536820L; + + /** + * The content:// uri of the image. + */ + private final Uri uri; + + public ImageLoader(Uri uri) { + this.uri = uri; + } + + public Uri getUri() { + return uri; + } +} diff --git a/src/uk/digitalsquid/netspoofer/servicemsg/ServiceMsg.java b/src/uk/digitalsquid/netspoofer/servicemsg/ServiceMsg.java new file mode 100644 index 0000000..2564e58 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/servicemsg/ServiceMsg.java @@ -0,0 +1,50 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.servicemsg; + +import java.io.Serializable; + +/** + * Base class for messages to the service. + * Also used for some simple commands. + * @author william + * + */ +public class ServiceMsg implements Serializable { + private static final long serialVersionUID = 4093240028206997618L; + public static final int MESSAGE_OTHER = 0; + public static final int MESSAGE_STOP = 1; + public static final int MESSAGE_GETSPOOFS = 2; + public static final int MESSAGE_STOPSPOOF = 3; + + private final int message; + + public ServiceMsg() { + message = MESSAGE_OTHER; + } + public ServiceMsg(int message) { + this.message = message; + } + public int getMessage() { + return message; + } +} diff --git a/src/uk/digitalsquid/netspoofer/servicemsg/SpoofStarter.java b/src/uk/digitalsquid/netspoofer/servicemsg/SpoofStarter.java new file mode 100644 index 0000000..764018a --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/servicemsg/SpoofStarter.java @@ -0,0 +1,39 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.servicemsg; + +import uk.digitalsquid.netspoofer.spoofs.SpoofData; + +public class SpoofStarter extends ServiceMsg { + private static final long serialVersionUID = 6740057018207849838L; + + private final SpoofData spoof; + + public SpoofStarter(SpoofData spoof) { + super(); + this.spoof = spoof; + } + + public SpoofData getSpoof() { + return spoof; + } +} diff --git a/src/uk/digitalsquid/netspoofer/servicestatus/InitialiseStatus.java b/src/uk/digitalsquid/netspoofer/servicestatus/InitialiseStatus.java new file mode 100644 index 0000000..bf3aaf9 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/servicestatus/InitialiseStatus.java @@ -0,0 +1,38 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.servicestatus; + +public class InitialiseStatus extends ServiceStatus { + private static final long serialVersionUID = 7918466113688717777L; + + // Now using values straight from NetSpoofService + /* + * public static final int INIT_COMPLETE = 0; + * public static final int INIT_FAIL = 1; + */ + + public final int status; + + public InitialiseStatus(int status) { + this.status = status; + } +} diff --git a/src/uk/digitalsquid/netspoofer/servicestatus/NewLogOutput.java b/src/uk/digitalsquid/netspoofer/servicestatus/NewLogOutput.java new file mode 100644 index 0000000..5cafcf5 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/servicestatus/NewLogOutput.java @@ -0,0 +1,38 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.servicestatus; + +import java.util.ArrayList; + +public class NewLogOutput extends ServiceStatus { + private static final long serialVersionUID = 8663033245576144897L; + + private final ArrayList logLines; + + public NewLogOutput(ArrayList lines) { + logLines = lines; + } + + public ArrayList getLogLines() { + return logLines; + } +} diff --git a/src/uk/digitalsquid/netspoofer/servicestatus/Notifyer.java b/src/uk/digitalsquid/netspoofer/servicestatus/Notifyer.java new file mode 100644 index 0000000..d0ee4ba --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/servicestatus/Notifyer.java @@ -0,0 +1,50 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.servicestatus; + +/** + * Message for managing notifications + * @author william + * + */ +public class Notifyer extends ServiceStatus { + + public static final int STATUS_SHOW = 0; + public static final int STATUS_HIDE = 1; + + private static final long serialVersionUID = -3703680009063029815L; + + private final int notificationType, status; + + public Notifyer(int type, int status) { + notificationType = type; + this.status = status; + } + + public int getNotificationType() { + return notificationType; + } + + public int getStatus() { + return status; + } +} diff --git a/src/uk/digitalsquid/netspoofer/servicestatus/ServiceStatus.java b/src/uk/digitalsquid/netspoofer/servicestatus/ServiceStatus.java new file mode 100644 index 0000000..7c2380f --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/servicestatus/ServiceStatus.java @@ -0,0 +1,29 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.servicestatus; + +import java.io.Serializable; + +public class ServiceStatus implements Serializable { + private static final long serialVersionUID = 465731953387884355L; + +} diff --git a/src/uk/digitalsquid/netspoofer/servicestatus/SpoofList.java b/src/uk/digitalsquid/netspoofer/servicestatus/SpoofList.java new file mode 100644 index 0000000..71a7a32 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/servicestatus/SpoofList.java @@ -0,0 +1,40 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.servicestatus; + +import java.util.ArrayList; + +import uk.digitalsquid.netspoofer.spoofs.Spoof; + +public class SpoofList extends ServiceStatus { + private static final long serialVersionUID = -3777527861258107613L; + + private final ArrayList spoofs; + + public SpoofList(ArrayList spoofs) { + this.spoofs = spoofs; + } + + public ArrayList getSpoofs() { + return spoofs; + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/CustomGSearchSpoof.java b/src/uk/digitalsquid/netspoofer/spoofs/CustomGSearchSpoof.java new file mode 100644 index 0000000..e635ebd --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/CustomGSearchSpoof.java @@ -0,0 +1,79 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import java.util.Map; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.widget.EditText; + +/** + * A custom version of the Google spoof which allows the user to enter their own google search query. + * @author william + * + */ +public class CustomGSearchSpoof extends SquidScriptSpoof { + private static final long serialVersionUID = 8490503138296852028L; + + public CustomGSearchSpoof() { + super("Custom Google search change", "Change the text in google searches", "googlemod.sh"); + } + + private String customFilter; + + @Override + public Dialog displayExtraDialog(final Context context, final OnExtraDialogDoneListener onDone) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + AlertDialog.Builder alert = new AlertDialog.Builder(context); + + alert.setTitle("Search change pattern"); + alert.setMessage("Enter the text to change the google search to. Put '%' to enter the original search query."); + + final EditText input = new EditText(context); + alert.setView(input); + input.setText(prefs.getString("gSearchText", "")); + + alert.setPositiveButton("Done", new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + customFilter = input.getText().toString().replace('\n', '+').replace('\t', '+').replace(' ', '+'); + prefs.edit().putString("gSearchText", input.getText().toString()).commit(); + onDone.onDone(); + } + }); + + return alert.create(); + } + + @Override + public Map getCustomEnv() { + Map ret = super.getCustomEnv(); + ret.put("GSEARCHSTRING", customFilter); + return ret; + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/CustomGalleryImageChange.java b/src/uk/digitalsquid/netspoofer/spoofs/CustomGalleryImageChange.java new file mode 100644 index 0000000..22745f7 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/CustomGalleryImageChange.java @@ -0,0 +1,90 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import java.util.Map; + +import uk.digitalsquid.netspoofer.NetSpoofService; +import uk.digitalsquid.netspoofer.NetSpoofService.NetSpoofServiceBinder; +import uk.digitalsquid.netspoofer.config.LogConf; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.net.Uri; +import android.os.IBinder; +import android.provider.MediaStore; + +/** + * A custom version of the Google spoof which allows the user to enter their own google search query. + * @author william + * + */ +public class CustomGalleryImageChange extends SquidScriptSpoof implements LogConf { + private static final long serialVersionUID = 8490503138296852028L; + + public CustomGalleryImageChange() { + super("Custom image change (image on phone)", "Change all images on all websites", "trollface.sh"); + } + + /** + * The image name, as it appears in $DEB/var/www/images/ + */ + public static final String IMAGE_NAME = "customimage.jpg"; + + @Override + public Intent activityForResult(Context context) { + return new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI); + } + + @Override + public boolean activityFinished(final Context context, Intent result) { + super.activityFinished(context, result); + final Uri customImageURI = result.getData(); + + // Communication with service to tell it to load image into debian area + // Using service, as this makes sure this is finished before spoof is started. + final ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + NetSpoofServiceBinder binder = (NetSpoofServiceBinder) service; + binder.getService().saveImageToWebserver(customImageURI); + + // Close again + context.unbindService(this); + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { } + }; + + context.bindService(new Intent(context, NetSpoofService.class), serviceConnection, Context.BIND_AUTO_CREATE); + return true; + } + + @Override + public Map getCustomEnv() { + Map ret = super.getCustomEnv(); + ret.put("SPOOFIMAGEURL", "http://127.0.0.1/images/" + IMAGE_NAME); + return ret; + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/CustomImageChange.java b/src/uk/digitalsquid/netspoofer/spoofs/CustomImageChange.java new file mode 100644 index 0000000..3b4f787 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/CustomImageChange.java @@ -0,0 +1,80 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import java.util.Map; + +import uk.digitalsquid.netspoofer.config.LogConf; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.widget.EditText; + +/** + * A custom version of the Image spoof. Uses a URL. + * @author william + * + */ +public class CustomImageChange extends SquidScriptSpoof implements LogConf { + private static final long serialVersionUID = 8490503138296852028L; + + public CustomImageChange() { + super("Custom image change (image on web)", "Change all images on all websites", "trollface.sh"); + } + + private String customImageURL; + + @Override + public Dialog displayExtraDialog(final Context context, final OnExtraDialogDoneListener onDone) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + AlertDialog.Builder alert = new AlertDialog.Builder(context); + + alert.setTitle("Image URL"); + alert.setMessage("Enter the URL of the image you would like to replace all images with."); + + final EditText input = new EditText(context); + input.setText(prefs.getString("imageChangeUrl", "http://")); + alert.setView(input); + + alert.setPositiveButton("Done", new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + customImageURL = input.getText().toString(); + prefs.edit().putString("imageChangeUrl", customImageURL).commit(); + onDone.onDone(); + } + }); + + return alert.create(); + } + + @Override + public Map getCustomEnv() { + Map ret = super.getCustomEnv(); + ret.put("SPOOFIMAGEURL", customImageURL); + return ret; + } +} \ No newline at end of file diff --git a/src/uk/digitalsquid/netspoofer/spoofs/CustomTextChange.java b/src/uk/digitalsquid/netspoofer/spoofs/CustomTextChange.java new file mode 100644 index 0000000..820ba89 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/CustomTextChange.java @@ -0,0 +1,136 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import java.util.HashMap; +import java.util.Map; + +import uk.digitalsquid.netspoofer.R; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.view.LayoutInflater; +import android.widget.ScrollView; +import android.widget.TextView; + +/** + * A custom version of the Google spoof which allows the user to enter their own google search query. + * @author william + * + */ +public class CustomTextChange extends SquidScriptSpoof { + private static final long serialVersionUID = 8490503138296852028L; + + public CustomTextChange() { + super("Text change", "Change all text on all websites", "textchange.sh"); + } + + private final Map changeValues = new HashMap(8); + + private static final int[] froms = { + R.id.textFrom1, + R.id.textFrom2, + R.id.textFrom3, + R.id.textFrom4, + R.id.textFrom5, + R.id.textFrom6, + R.id.textFrom7, + R.id.textFrom8, + }; + private static final int[] tos = { + R.id.textTo1, + R.id.textTo2, + R.id.textTo3, + R.id.textTo4, + R.id.textTo5, + R.id.textTo6, + R.id.textTo7, + R.id.textTo8, + }; + + /** + * Sets the value in the environment map, and also saves to shared prefs. + * @param old + * @param position + * @param value + */ + private final void setValue(SharedPreferences prefs, boolean old, int position, String value) { + if(old) { + final String key = String.format("TEXT%dOLD", position); + changeValues.put(key, value); + prefs.edit().putString(key, value).commit(); + } else { + final String key = String.format("TEXT%dNEW", position); + changeValues.put(key, value); + prefs.edit().putString(key, value).commit(); + } + } + + @Override + public Dialog displayExtraDialog(final Context context, final OnExtraDialogDoneListener onDone) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + + final LayoutInflater inflater = LayoutInflater.from(context); + final ScrollView view = (ScrollView)inflater.inflate(R.layout.customtextdialog, null); + + // Iterate through all + for(int i = 0; i < 8; i++) { + String from = prefs.getString(String.format("TEXT%dOLD", i), ""); + String to = prefs.getString(String.format("TEXT%dNEW", i), ""); + ((TextView)view.findViewById(froms[i])).setText(from); + ((TextView)view.findViewById(tos[i])).setText(to); + } + + + builder.setView(view); + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Iterate through all + for(int i = 0; i < 8; i++) { + String from = ((TextView)view.findViewById(froms[i])).getText().toString(); + String to = ((TextView)view.findViewById(tos[i])).getText().toString(); + + setValue(prefs, true, i, from); + setValue(prefs, false, i, to); + } + + onDone.onDone(); + } + }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }).setTitle(R.string.customText); + return builder.create(); + } + + @Override + public Map getCustomEnv() { + return changeValues; + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/IPRedirectSpoof.java b/src/uk/digitalsquid/netspoofer/spoofs/IPRedirectSpoof.java new file mode 100644 index 0000000..904410d --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/IPRedirectSpoof.java @@ -0,0 +1,164 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Map; + +import uk.digitalsquid.netspoofer.R; +import uk.digitalsquid.netspoofer.config.LogConf; +import uk.digitalsquid.netspoofer.misc.AsyncTaskHelper; +import android.app.Dialog; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.AsyncTask; +import android.os.AsyncTask.Status; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +/** + * A spoof which redirects a website to another. + * @author william + * + */ +public class IPRedirectSpoof extends SquidScriptSpoof implements LogConf { + private static final long serialVersionUID = -7780822391880161592L; + public static final String KITTENWAR = "kittenwar.com"; + + private InetAddress host; + + public IPRedirectSpoof(String title, String description, String hostTo) throws UnknownHostException { + super(title, description, "redirect.sh"); + if(hostTo == null) { + host = null; + return; + } + host = InetAddress.getByName(hostTo); + } + + /** + * Constructor that leaves host undefined, and shows dialog later. + * @param title + * @param description + * @throws UnknownHostException + */ + public IPRedirectSpoof(String title, String description) { + super(title, description, "redirect.sh"); + } + + @Override + public Dialog displayExtraDialog(final Context context, final OnExtraDialogDoneListener onDone) { + if(host == null) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + final Dialog dialog = new Dialog(context); + + dialog.setTitle("Website redirect"); + + dialog.setContentView(R.layout.iptextfield); + + final TextView input = (TextView) dialog.findViewById(R.id.text); + input.setText(prefs.getString("redirectUrl", "")); + final View[] progressParts = new View[] { + dialog.findViewById(R.id.progress), + dialog.findViewById(R.id.status) }; + final Button + ok = (Button) dialog.findViewById(R.id.ok), + cancel = (Button) dialog.findViewById(R.id.cancel); + + // Run this in BG to make UX better + final AsyncTask bg = new AsyncTask() { + @Override + protected void onPreExecute() { + userEntry = input.getText().toString(); + } + + String userEntry; + + @Override + protected InetAddress doInBackground(Void... params) { + InetAddress host = null; + try { + if(userEntry.equals("")) throw new UnknownHostException("Blank host"); + host = InetAddress.getByName(userEntry); + prefs.edit().putString("redirectUrl", userEntry).commit(); + } catch (UnknownHostException e) { + try { + host = InetAddress.getByName(KITTENWAR); + } catch (UnknownHostException e1) { + e1.printStackTrace(); + } + } + return host; + } + @Override + protected void onPostExecute(InetAddress addr) { + if(!isCancelled()) { + if(addr == null) { + Toast.makeText(context, "Couldn't find specified website, using kittenwar.", Toast.LENGTH_LONG).show(); + } + host = addr; + dialog.dismiss(); + onDone.onDone(); + } + } + }; + + ok.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + for(View v : progressParts) { + v.setVisibility(View.VISIBLE); + } + if(bg.getStatus() != Status.RUNNING) + AsyncTaskHelper.execute(bg); + } + }); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + bg.cancel(false); + dialog.cancel(); + } + }); + + return dialog; + } + else return null; + } + + /** + * Adds redirect env variable + */ + @Override + public Map getCustomEnv() { + Map ret = super.getCustomEnv(); + if(host != null) ret.put("REDIRECTURL", host.getHostName()); + else Log.e(TAG, "Entered URL not here, probably a non-existent website."); + return ret; + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/MultiSpoof.java b/src/uk/digitalsquid/netspoofer/spoofs/MultiSpoof.java new file mode 100644 index 0000000..daf4d28 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/MultiSpoof.java @@ -0,0 +1,122 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import java.util.ArrayList; +import java.util.Map; + +import uk.digitalsquid.netspoofer.MultiSpoofDialogRunner; +import uk.digitalsquid.netspoofer.SpoofSelector; +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; + +/** + * A spoof which runs multiple other spoofs, and concatenates them by piping the scripts together. + * @author william + * + */ +public class MultiSpoof extends Spoof { + + public MultiSpoof() { + super("Multiple spoofs", "Run multiple spoofs at once. May run slowly."); + } + + private ArrayList selectedSpoofs; + private ArrayList finalSpoofs; + + private static final long serialVersionUID = -848683524539301592L; + + @Override + public Intent activityForResult(Context context) { + Intent ret = new Intent(context, SpoofSelector.class); + ret.setAction(Intent.ACTION_PICK); + return ret; + } + + @SuppressWarnings("unchecked") + @Override + public boolean activityFinished(Context context, Intent intent) { + selectedSpoofs = (ArrayList) intent.getSerializableExtra("uk.digitalsquid.netspoof.SpoofSelector.spoofs"); + return true; + } + + @Override + public Intent activityForResult2(Context context) { + Intent ret = new Intent(context, MultiSpoofDialogRunner.class); + ArrayList filteredSpoofs = new ArrayList(); + for(Spoof spoof : selectedSpoofs) { + if(spoof instanceof SquidScriptSpoof) { + filteredSpoofs.add((SquidScriptSpoof) spoof); + } + } + ret.putExtra(MultiSpoofDialogRunner.SPOOF_LIST, filteredSpoofs); + return ret; + } + + @SuppressWarnings("unchecked") + @Override + public boolean activityFinished2(Context context, Intent result) { + finalSpoofs = (ArrayList) result.getSerializableExtra(MultiSpoofDialogRunner.SPOOF_LIST); + return true; + } + + private static final String BASE_REWRITE_URL = "/rewriters/"; + + @Override + public String getSpoofCmd(String victim, String router) { + if(finalSpoofs == null) return null; + final StringBuilder cmdBuilder = new StringBuilder(); + cmdBuilder.append("spoof %s %s 3 \""); + boolean first = true; + for(SquidScriptSpoof spoof : finalSpoofs) { + // Leaving no spaces in script def + if(!first) { + cmdBuilder.append('|'); + } else { + first = false; + } + cmdBuilder.append(BASE_REWRITE_URL); + cmdBuilder.append(spoof.getScriptName()); + } + cmdBuilder.append('"'); + return String.format(cmdBuilder.toString(), victim, router); + } + + @Override + public String getStopCmd() { + return "\n"; + } + + @Override + public Map getCustomEnv() { + Map ret = super.getCustomEnv(); + if(finalSpoofs != null) { + for(SquidScriptSpoof spoof : finalSpoofs) { + ret.putAll(spoof.getCustomEnv()); + } + } + return ret; + } + + @Override public Dialog displayExtraDialog(Context context, OnExtraDialogDoneListener onDone) { return null; } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/SimpleScriptedSpoof.java b/src/uk/digitalsquid/netspoofer/spoofs/SimpleScriptedSpoof.java new file mode 100644 index 0000000..307f952 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/SimpleScriptedSpoof.java @@ -0,0 +1,70 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; + +public class SimpleScriptedSpoof extends Spoof { + private static final long serialVersionUID = 6510405899936627809L; + + private final String start, stop; + + /** + * + * @param title + * @param description + * @param start Starting debian shell command - must contain 2 %s for IP addresses - + * 'all' in victim means arpspoof everyone. + * @param stop + */ + public SimpleScriptedSpoof(String title, String description, String start, String stop) { + super(title, description); + this.start = start; + this.stop = stop; + } + + @Override + public String getSpoofCmd(String victim, String router) { + return String.format(start, victim, router); + } + + @Override + public String getStopCmd() { + return stop; + } + + @Override + public Dialog displayExtraDialog(Context context, + OnExtraDialogDoneListener onDone) { + return null; + } + @Override + public Intent activityForResult(Context context) { + return null; + } + @Override + public boolean activityFinished(Context context, Intent result) { + return false; + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/Spoof.java b/src/uk/digitalsquid/netspoofer/spoofs/Spoof.java new file mode 100644 index 0000000..6557404 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/Spoof.java @@ -0,0 +1,95 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; + +public abstract class Spoof implements Serializable, Comparable { + private static final long serialVersionUID = -3207729013734241941L; + + private final String title, description; + + public Spoof(String title, String description) { + this.description = description; + this.title = title; + } + + public abstract String getSpoofCmd(String victim, String router); + public abstract String getStopCmd(); + + public abstract Dialog displayExtraDialog(Context context, OnExtraDialogDoneListener onDone); + + public abstract Intent activityForResult(Context context); + /** + * A second activity to be displayed afterwards. + * @param context + * @return + */ + public Intent activityForResult2(Context context){ return null; } + + /** + * + * @param result + * @return true to continue the process. + */ + public abstract boolean activityFinished(Context context, Intent result); + /** + * + * @param result + * @return true to continue the process. + */ + public boolean activityFinished2(Context context, Intent result) { return true; } + + public String getDescription() { + return description; + } + + public String getTitle() { + return title; + } + + public static interface OnExtraDialogDoneListener { + void onDone(); + } + + public static interface OnActivityResultListener { + void onResult(Intent result); + } + + public Map getCustomEnv() {return new HashMap();} + + @Override + public int compareTo(Spoof other) { + return getTitle().compareTo(other.getTitle()); + } + + @Override + public String toString() { + return title; + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/SpoofData.java b/src/uk/digitalsquid/netspoofer/spoofs/SpoofData.java new file mode 100644 index 0000000..b0b4d02 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/SpoofData.java @@ -0,0 +1,177 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import java.io.Serializable; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import uk.digitalsquid.netspoofer.VictimSelector.Victim; +import uk.digitalsquid.netspoofer.config.NetHelpers; + +public class SpoofData implements Serializable { + private static final long serialVersionUID = -690081983763949966L; + private static final String[] SUBNETS = { + "0.0.0.0", // This may seem like a stupid way to do this, but I can't be bothered to write a proper subnet decoder which still uses Android API8. + "128.0.0.0", // Vim to the rescue! + "192.0.0.0", + "224.0.0.0", + "240.0.0.0", + "248.0.0.0", + "252.0.0.0", + "254.0.0.0", + "255.0.0.0", + "255.128.0.0", + "255.192.0.0", + "255.224.0.0", + "255.240.0.0", + "255.248.0.0", + "255.252.0.0", + "255.254.0.0", + "255.255.0.0", + "255.255.128.0", + "255.255.192.0", + "255.255.224.0", + "255.255.240.0", + "255.255.248.0", + "255.255.252.0", + "255.255.254.0", + "255.255.255.0", + "255.255.255.128", + "255.255.255.192", + "255.255.255.224", + "255.255.255.240", + "255.255.255.248", + "255.255.255.252", + "255.255.255.254", + "255.255.255.255", + }; + private final Spoof spoof; + + private String myIf; + /** + * NOTE: This isn't the full address, but rather the (CIDL?) notation of /24 etc. + */ + private int mySubnet = 24; + private InetAddress myIp, routerIp; + + private Victim victim; + + private boolean runningPassively = false; + + public SpoofData(Spoof spoof, boolean runningPassively) { + if(!runningPassively) throw new IllegalStateException("Please use the other constructor"); + this.spoof = spoof; + this.setRunningPassively(true); + } + + public SpoofData(Spoof spoof, String myIp, String mySubnet, String myIf, String routerIp) throws UnknownHostException { + this.spoof = spoof; + this.myIp = InetAddress.getByName(myIp); + for(int i = 0; i < SUBNETS.length; i++) { + if(mySubnet.equals(SUBNETS[i])) this.mySubnet = i; + } + this.myIf = myIf; + this.routerIp = InetAddress.getByName(routerIp); + } + + public Spoof getSpoof() { + return spoof; + } + public InetAddress getMyIp() { + return myIp; + } + public long getMyIpInt() { + return NetHelpers.inetFromByte(myIp.getAddress()); + } + public long getMyIpReverseInt() { + return NetHelpers.reverseInetFromByte(myIp.getAddress()); + } + public String getMyIface() { + return myIf; + } + public InetAddress getRouterIp() { + return routerIp; + } + public String getRouterIpString() { + if(routerIp == null) return "none"; + return routerIp.getHostAddress(); + } + public long getRouterIpInt() { + return NetHelpers.inetFromByte(routerIp.getAddress()); + } + public int getMySubnet() { + return mySubnet; + } + public byte[] getMySubnetBytes() { + int mask = 0xffffffff << (32 - mySubnet); + return new byte[]{ + (byte)(mask >>> 24), (byte)(mask >> 16 & 0xff), (byte)(mask >> 8 & 0xff), (byte)(mask & 0xff) }; + } + public long getMySubnetReverseInt() { + return 0xffffffff << (32 - mySubnet); + } + public String getMySubnetString() { + return SUBNETS[mySubnet]; + } + + public long getMySubnetBaseAddressReverseInt() { + long ip = getMyIpReverseInt(); + return ip & getMySubnetReverseInt(); // Bottom possble IP + } + + public String getMySubnetBaseAddressString() { + long baseIp = getMySubnetBaseAddressReverseInt(); + try { + return NetHelpers.reverseInetFromInt(baseIp).getHostAddress(); + } catch (UnknownHostException e) { + e.printStackTrace(); + return null; + } + } + + public void setVictim(Victim victim) { + this.victim = victim; + } + + public Victim getVictim() { + return victim; + } + + public String getVictimString() { + if(isRunningPassively()) return "none"; + if(isEveryoneVictim()) return "all"; + return victim.getIpString(); + } + + public boolean isEveryoneVictim() { + return victim == null; + } + + public void setRunningPassively(boolean runningPassively) { + this.runningPassively = runningPassively; + } + + public boolean isRunningPassively() { + return runningPassively; + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/SquidScriptSpoof.java b/src/uk/digitalsquid/netspoofer/spoofs/SquidScriptSpoof.java new file mode 100644 index 0000000..21356e1 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/SquidScriptSpoof.java @@ -0,0 +1,65 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; + +public class SquidScriptSpoof extends Spoof { + private static final long serialVersionUID = 52887789907180627L; + + private final String scriptName; + + public SquidScriptSpoof(String title, String description, String scriptName) { + super(title, description); + this.scriptName = scriptName; + } + + @Override + public String getSpoofCmd(String victim, String router) { + if(victim == null) victim = "all"; + return String.format("spoof %s %s 2 %s", victim, router, scriptName); + } + + @Override + public String getStopCmd() { + return "\n"; + } + + @Override + public Dialog displayExtraDialog(Context context, OnExtraDialogDoneListener onDone) { + return null; + } + @Override + public Intent activityForResult(Context context) { + return null; + } + @Override + public boolean activityFinished(Context context, Intent result) { + return false; + } + + public String getScriptName() { + return scriptName; + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/VideoChange.java b/src/uk/digitalsquid/netspoofer/spoofs/VideoChange.java new file mode 100644 index 0000000..9ce8add --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/VideoChange.java @@ -0,0 +1,63 @@ +/* + * This file is part of Network Spoofer for Android. + * Network Spoofer lets you change websites on other people’s computers + * from an Android phone. + * Copyright (C) 2011 Will Shackleton + * + * Network Spoofer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Network Spoofer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Network Spoofer, in the file COPYING. + * If not, see . + */ + +package uk.digitalsquid.netspoofer.spoofs; + +import java.util.Map; + +import uk.digitalsquid.netspoofer.YoutubeSelector; +import android.content.Context; +import android.content.Intent; + +/** + * A custom version of the Google spoof which allows the user to enter their own google search query. + * @author william + * + */ +public class VideoChange extends SquidScriptSpoof { + private static final long serialVersionUID = 8490503138296852028L; + + public VideoChange() { + super("Custom Youtube video", "Change all videos on Youtube to a custom one", "rickroll.sh"); + } + + private String videoURL; + + @Override + public Intent activityForResult(Context context) { + return new Intent(context, YoutubeSelector.class); + } + + @Override + public boolean activityFinished(Context context, Intent result) { + super.activityFinished(context, result); + videoURL = result.getStringExtra(YoutubeSelector.CODE); + if(videoURL == null) return false; // No video selected + else return true; + } + + @Override + public Map getCustomEnv() { + Map ret = super.getCustomEnv(); + ret.put("SPOOFVIDEOID", videoURL); + return ret; + } +} diff --git a/status-8.svg b/status-8.svg new file mode 100644 index 0000000..8f232de --- /dev/null +++ b/status-8.svg @@ -0,0 +1,729 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/statusicon.svg b/statusicon.svg new file mode 100644 index 0000000..414bcf2 --- /dev/null +++ b/statusicon.svg @@ -0,0 +1,641 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + +