├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── bin ├── class-dump ├── class-dump-z ├── iosod └── ldid ├── include ├── ActionMenu │ └── ActionMenu.h ├── AssistantExtensions │ └── SiriObjects.h ├── CaptainHook │ └── CaptainHook.h ├── libactivator │ ├── LAActivator.h │ ├── LAActivatorVersion.h │ ├── LAEvent.h │ ├── LAEventDataSource.h │ ├── LAListener.h │ ├── LASettingsViewController.h │ ├── UIImageView+Activator.h │ └── libactivator.h ├── logos │ └── logos.h └── substrate.h └── lib ├── libactionmenu.dylib ├── libactivator.dylib └── libsubstrate.dylib /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | ._* 3 | .VolumeIcon.icns 4 | .com.apple.timemachine.supported 5 | .fseventsd 6 | .localized 7 | .DocumentRevisions-V100 8 | .Spotlight-V100 9 | .vol 10 | Icon 11 | frameworks 12 | include/SpringBoard 13 | templates 14 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kokoabim/iOSOpenDev/020e76695ec6efecf941a100b147a50a6b9e6495/.gitmodules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | iOSOpenDev is an independent project and has not been authorized, sponsored, or otherwise approved by Apple Inc. 2 | 3 | IOS is a registered trademark of Cisco and used under license by Apple Inc. 4 | 5 | Xcode is a registered trademark of Apple Inc. 6 | 7 | iOSOpenDev -- iOS Open Development 8 | Copyright (c) 2012-2013 Spencer James (Kokoabim) . 9 | 10 | GNU GENERAL PUBLIC LICENSE 11 | Version 2, June 1991 12 | 13 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 15 | Everyone is permitted to copy and distribute verbatim copies 16 | of this license document, but changing it is not allowed. 17 | 18 | Preamble 19 | 20 | The licenses for most software are designed to take away your 21 | freedom to share and change it. By contrast, the GNU General Public 22 | License is intended to guarantee your freedom to share and change free 23 | software--to make sure the software is free for all its users. This 24 | General Public License applies to most of the Free Software 25 | Foundation's software and to any other program whose authors commit to 26 | using it. (Some other Free Software Foundation software is covered by 27 | the GNU Lesser General Public License instead.) You can apply it to 28 | your programs, too. 29 | 30 | When we speak of free software, we are referring to freedom, not 31 | price. Our General Public Licenses are designed to make sure that you 32 | have the freedom to distribute copies of free software (and charge for 33 | this service if you wish), that you receive source code or can get it 34 | if you want it, that you can change the software or use pieces of it 35 | in new free programs; and that you know you can do these things. 36 | 37 | To protect your rights, we need to make restrictions that forbid 38 | anyone to deny you these rights or to ask you to surrender the rights. 39 | These restrictions translate to certain responsibilities for you if you 40 | distribute copies of the software, or if you modify it. 41 | 42 | For example, if you distribute copies of such a program, whether 43 | gratis or for a fee, you must give the recipients all the rights that 44 | you have. You must make sure that they, too, receive or can get the 45 | source code. And you must show them these terms so they know their 46 | rights. 47 | 48 | We protect your rights with two steps: (1) copyright the software, and 49 | (2) offer you this license which gives you legal permission to copy, 50 | distribute and/or modify the software. 51 | 52 | Also, for each author's protection and ours, we want to make certain 53 | that everyone understands that there is no warranty for this free 54 | software. If the software is modified by someone else and passed on, we 55 | want its recipients to know that what they have is not the original, so 56 | that any problems introduced by others will not reflect on the original 57 | authors' reputations. 58 | 59 | Finally, any free program is threatened constantly by software 60 | patents. We wish to avoid the danger that redistributors of a free 61 | program will individually obtain patent licenses, in effect making the 62 | program proprietary. To prevent this, we have made it clear that any 63 | patent must be licensed for everyone's free use or not licensed at all. 64 | 65 | The precise terms and conditions for copying, distribution and 66 | modification follow. 67 | 68 | GNU GENERAL PUBLIC LICENSE 69 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 70 | 71 | 0. This License applies to any program or other work which contains 72 | a notice placed by the copyright holder saying it may be distributed 73 | under the terms of this General Public License. The "Program", below, 74 | refers to any such program or work, and a "work based on the Program" 75 | means either the Program or any derivative work under copyright law: 76 | that is to say, a work containing the Program or a portion of it, 77 | either verbatim or with modifications and/or translated into another 78 | language. (Hereinafter, translation is included without limitation in 79 | the term "modification".) Each licensee is addressed as "you". 80 | 81 | Activities other than copying, distribution and modification are not 82 | covered by this License; they are outside its scope. The act of 83 | running the Program is not restricted, and the output from the Program 84 | is covered only if its contents constitute a work based on the 85 | Program (independent of having been made by running the Program). 86 | Whether that is true depends on what the Program does. 87 | 88 | 1. You may copy and distribute verbatim copies of the Program's 89 | source code as you receive it, in any medium, provided that you 90 | conspicuously and appropriately publish on each copy an appropriate 91 | copyright notice and disclaimer of warranty; keep intact all the 92 | notices that refer to this License and to the absence of any warranty; 93 | and give any other recipients of the Program a copy of this License 94 | along with the Program. 95 | 96 | You may charge a fee for the physical act of transferring a copy, and 97 | you may at your option offer warranty protection in exchange for a fee. 98 | 99 | 2. You may modify your copy or copies of the Program or any portion 100 | of it, thus forming a work based on the Program, and copy and 101 | distribute such modifications or work under the terms of Section 1 102 | above, provided that you also meet all of these conditions: 103 | 104 | a) You must cause the modified files to carry prominent notices 105 | stating that you changed the files and the date of any change. 106 | 107 | b) You must cause any work that you distribute or publish, that in 108 | whole or in part contains or is derived from the Program or any 109 | part thereof, to be licensed as a whole at no charge to all third 110 | parties under the terms of this License. 111 | 112 | c) If the modified program normally reads commands interactively 113 | when run, you must cause it, when started running for such 114 | interactive use in the most ordinary way, to print or display an 115 | announcement including an appropriate copyright notice and a 116 | notice that there is no warranty (or else, saying that you provide 117 | a warranty) and that users may redistribute the program under 118 | these conditions, and telling the user how to view a copy of this 119 | License. (Exception: if the Program itself is interactive but 120 | does not normally print such an announcement, your work based on 121 | the Program is not required to print an announcement.) 122 | 123 | These requirements apply to the modified work as a whole. If 124 | identifiable sections of that work are not derived from the Program, 125 | and can be reasonably considered independent and separate works in 126 | themselves, then this License, and its terms, do not apply to those 127 | sections when you distribute them as separate works. But when you 128 | distribute the same sections as part of a whole which is a work based 129 | on the Program, the distribution of the whole must be on the terms of 130 | this License, whose permissions for other licensees extend to the 131 | entire whole, and thus to each and every part regardless of who wrote it. 132 | 133 | Thus, it is not the intent of this section to claim rights or contest 134 | your rights to work written entirely by you; rather, the intent is to 135 | exercise the right to control the distribution of derivative or 136 | collective works based on the Program. 137 | 138 | In addition, mere aggregation of another work not based on the Program 139 | with the Program (or with a work based on the Program) on a volume of 140 | a storage or distribution medium does not bring the other work under 141 | the scope of this License. 142 | 143 | 3. You may copy and distribute the Program (or a work based on it, 144 | under Section 2) in object code or executable form under the terms of 145 | Sections 1 and 2 above provided that you also do one of the following: 146 | 147 | a) Accompany it with the complete corresponding machine-readable 148 | source code, which must be distributed under the terms of Sections 149 | 1 and 2 above on a medium customarily used for software interchange; or, 150 | 151 | b) Accompany it with a written offer, valid for at least three 152 | years, to give any third party, for a charge no more than your 153 | cost of physically performing source distribution, a complete 154 | machine-readable copy of the corresponding source code, to be 155 | distributed under the terms of Sections 1 and 2 above on a medium 156 | customarily used for software interchange; or, 157 | 158 | c) Accompany it with the information you received as to the offer 159 | to distribute corresponding source code. (This alternative is 160 | allowed only for noncommercial distribution and only if you 161 | received the program in object code or executable form with such 162 | an offer, in accord with Subsection b above.) 163 | 164 | The source code for a work means the preferred form of the work for 165 | making modifications to it. For an executable work, complete source 166 | code means all the source code for all modules it contains, plus any 167 | associated interface definition files, plus the scripts used to 168 | control compilation and installation of the executable. However, as a 169 | special exception, the source code distributed need not include 170 | anything that is normally distributed (in either source or binary 171 | form) with the major components (compiler, kernel, and so on) of the 172 | operating system on which the executable runs, unless that component 173 | itself accompanies the executable. 174 | 175 | If distribution of executable or object code is made by offering 176 | access to copy from a designated place, then offering equivalent 177 | access to copy the source code from the same place counts as 178 | distribution of the source code, even though third parties are not 179 | compelled to copy the source along with the object code. 180 | 181 | 4. You may not copy, modify, sublicense, or distribute the Program 182 | except as expressly provided under this License. Any attempt 183 | otherwise to copy, modify, sublicense or distribute the Program is 184 | void, and will automatically terminate your rights under this License. 185 | However, parties who have received copies, or rights, from you under 186 | this License will not have their licenses terminated so long as such 187 | parties remain in full compliance. 188 | 189 | 5. You are not required to accept this License, since you have not 190 | signed it. However, nothing else grants you permission to modify or 191 | distribute the Program or its derivative works. These actions are 192 | prohibited by law if you do not accept this License. Therefore, by 193 | modifying or distributing the Program (or any work based on the 194 | Program), you indicate your acceptance of this License to do so, and 195 | all its terms and conditions for copying, distributing or modifying 196 | the Program or works based on it. 197 | 198 | 6. Each time you redistribute the Program (or any work based on the 199 | Program), the recipient automatically receives a license from the 200 | original licensor to copy, distribute or modify the Program subject to 201 | these terms and conditions. You may not impose any further 202 | restrictions on the recipients' exercise of the rights granted herein. 203 | You are not responsible for enforcing compliance by third parties to 204 | this License. 205 | 206 | 7. If, as a consequence of a court judgment or allegation of patent 207 | infringement or for any other reason (not limited to patent issues), 208 | conditions are imposed on you (whether by court order, agreement or 209 | otherwise) that contradict the conditions of this License, they do not 210 | excuse you from the conditions of this License. If you cannot 211 | distribute so as to satisfy simultaneously your obligations under this 212 | License and any other pertinent obligations, then as a consequence you 213 | may not distribute the Program at all. For example, if a patent 214 | license would not permit royalty-free redistribution of the Program by 215 | all those who receive copies directly or indirectly through you, then 216 | the only way you could satisfy both it and this License would be to 217 | refrain entirely from distribution of the Program. 218 | 219 | If any portion of this section is held invalid or unenforceable under 220 | any particular circumstance, the balance of the section is intended to 221 | apply and the section as a whole is intended to apply in other 222 | circumstances. 223 | 224 | It is not the purpose of this section to induce you to infringe any 225 | patents or other property right claims or to contest validity of any 226 | such claims; this section has the sole purpose of protecting the 227 | integrity of the free software distribution system, which is 228 | implemented by public license practices. Many people have made 229 | generous contributions to the wide range of software distributed 230 | through that system in reliance on consistent application of that 231 | system; it is up to the author/donor to decide if he or she is willing 232 | to distribute software through any other system and a licensee cannot 233 | impose that choice. 234 | 235 | This section is intended to make thoroughly clear what is believed to 236 | be a consequence of the rest of this License. 237 | 238 | 8. If the distribution and/or use of the Program is restricted in 239 | certain countries either by patents or by copyrighted interfaces, the 240 | original copyright holder who places the Program under this License 241 | may add an explicit geographical distribution limitation excluding 242 | those countries, so that distribution is permitted only in or among 243 | countries not thus excluded. In such case, this License incorporates 244 | the limitation as if written in the body of this License. 245 | 246 | 9. The Free Software Foundation may publish revised and/or new versions 247 | of the General Public License from time to time. Such new versions will 248 | be similar in spirit to the present version, but may differ in detail to 249 | address new problems or concerns. 250 | 251 | Each version is given a distinguishing version number. If the Program 252 | specifies a version number of this License which applies to it and "any 253 | later version", you have the option of following the terms and conditions 254 | either of that version or of any later version published by the Free 255 | Software Foundation. If the Program does not specify a version number of 256 | this License, you may choose any version ever published by the Free Software 257 | Foundation. 258 | 259 | 10. If you wish to incorporate parts of the Program into other free 260 | programs whose distribution conditions are different, write to the author 261 | to ask for permission. For software which is copyrighted by the Free 262 | Software Foundation, write to the Free Software Foundation; we sometimes 263 | make exceptions for this. Our decision will be guided by the two goals 264 | of preserving the free status of all derivatives of our free software and 265 | of promoting the sharing and reuse of software generally. 266 | 267 | NO WARRANTY 268 | 269 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 270 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 271 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 272 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 273 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 274 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 275 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 276 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 277 | REPAIR OR CORRECTION. 278 | 279 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 280 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 281 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 282 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 283 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 284 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 285 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 286 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 287 | POSSIBILITY OF SUCH DAMAGES. 288 | 289 | END OF TERMS AND CONDITIONS 290 | 291 | How to Apply These Terms to Your New Programs 292 | 293 | If you develop a new program, and you want it to be of the greatest 294 | possible use to the public, the best way to achieve this is to make it 295 | free software which everyone can redistribute and change under these terms. 296 | 297 | To do so, attach the following notices to the program. It is safest 298 | to attach them to the start of each source file to most effectively 299 | convey the exclusion of warranty; and each file should have at least 300 | the "copyright" line and a pointer to where the full notice is found. 301 | 302 | 303 | Copyright (C) 304 | 305 | This program is free software; you can redistribute it and/or modify 306 | it under the terms of the GNU General Public License as published by 307 | the Free Software Foundation; either version 2 of the License, or 308 | (at your option) any later version. 309 | 310 | This program is distributed in the hope that it will be useful, 311 | but WITHOUT ANY WARRANTY; without even the implied warranty of 312 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 313 | GNU General Public License for more details. 314 | 315 | You should have received a copy of the GNU General Public License along 316 | with this program; if not, write to the Free Software Foundation, Inc., 317 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 318 | 319 | Also add information on how to contact you by electronic and paper mail. 320 | 321 | If the program is interactive, make it output a short notice like this 322 | when it starts in an interactive mode: 323 | 324 | Gnomovision version 69, Copyright (C) year name of author 325 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 326 | This is free software, and you are welcome to redistribute it 327 | under certain conditions; type `show c' for details. 328 | 329 | The hypothetical commands `show w' and `show c' should show the appropriate 330 | parts of the General Public License. Of course, the commands you use may 331 | be called something other than `show w' and `show c'; they could even be 332 | mouse-clicks or menu items--whatever suits your program. 333 | 334 | You should also get your employer (if you work as a programmer) or your 335 | school, if any, to sign a "copyright disclaimer" for the program, if 336 | necessary. Here is a sample; alter the names: 337 | 338 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 339 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 340 | 341 | , 1 April 1989 342 | Ty Coon, President of Vice 343 | 344 | This General Public License does not permit incorporating your program into 345 | proprietary programs. If your program is a subroutine library, you may 346 | consider it more useful to permit linking proprietary applications with the 347 | library. If this is what you want to do, use the GNU Lesser General 348 | Public License instead of this License. 349 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### iOSOpenDev—iOS Open Development 2 | Copyright (c) 2012-2015 Spencer James (Kokoabim). 3 | 4 | * Follow [@kokoabim](https://twitter.com/kokoabim) 5 | * Download [http://iOSOpenDev.com](http://iOSOpenDev.com) 6 | * Wiki [https://github.com/kokoabim/iOSOpenDev/wiki](https://github.com/kokoabim/iOSOpenDev/wiki/_pages) 7 | * IRC channel #iOSOpenDev on irc.saurik.com 8 | -------------------------------------------------------------------------------- /bin/class-dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kokoabim/iOSOpenDev/020e76695ec6efecf941a100b147a50a6b9e6495/bin/class-dump -------------------------------------------------------------------------------- /bin/class-dump-z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kokoabim/iOSOpenDev/020e76695ec6efecf941a100b147a50a6b9e6495/bin/class-dump-z -------------------------------------------------------------------------------- /bin/iosod: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ----------------------------------------------------------------------- 4 | # iOSOpenDev -- iOS Open Development (http://www.iOSOpenDev.com) 5 | # Copyright (C) 2012-2013 Spencer James (Kokoabim) 6 | # ----------------------------------------------------------------------- 7 | # This program is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # You should have received a copy of the GNU General Public License along 16 | # with this program; if not, write to the Free Software Foundation, Inc., 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | # ----------------------------------------------------------------------- 19 | # iOSOpenDev is an independent project and has not been authorized, sponsored, or otherwise approved by Apple Inc. 20 | # IOS is a registered trademark of Cisco and is used under license by Apple Inc. 21 | # Xcode is a registered trademark of Apple Inc. 22 | # ----------------------------------------------------------------------- 23 | 24 | export setCmd="set -eo pipefail" 25 | $setCmd 26 | 27 | # path # 28 | export PATH=/opt/iOSOpenDev/bin:/opt/theos/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:$PATH 29 | 30 | # script # 31 | 32 | export scriptName="${0##*/}" 33 | export scriptVer="1.5" 34 | export originalArguments=("$@") 35 | export activeActionArg 36 | 37 | export iOSOpenDevPath="/opt/iOSOpenDev" 38 | 39 | export userName="${SUDO_USER-$USER}" 40 | export userGroup=`id -g $userName` 41 | export userHome=`eval echo ~$userName` 42 | export bashProfileFiles=("$userHome/.bash_profile" "$userHome/.bashrc" "$userHome/.zshrc" "$userHome/.bash_login" "$userHome/.profile") 43 | 44 | export tempDirsFile="`mktemp -d -t $scriptName`/tempdirs" 45 | touch "$tempDirsFile" 46 | 47 | unset LANG 48 | 49 | # development tools # 50 | 51 | xcodeAsAppPath=`xcode-select -p` 52 | [[ ! -d "$xcodeAsAppPath" ]] || \ 53 | export DEVELOPER_DIR="$xcodeAsAppPath" 54 | 55 | # === "actions" === # 56 | 57 | export ActionNames=( \ 58 | "SignCode" \ 59 | "BuildPackage" "InstallPackage" "RemovePackage" "PurgePackage" \ 60 | "SshToDevice" "RunCmdOnDevice" "RunFuncOnDevice" \ 61 | "UpdateIncludeAndLib" \ 62 | "DumpSDKHeaders" "CopyHeadersToSDK" "DumpAndCopyHeaders" "RemoveCopiedHeaders" "DumpAllHeaders" \ 63 | "AddSshKeyToDevice" \ 64 | "XcodeBuildPhase" "XcodeBuildPhaseLogos" "Help") 65 | export ActionProperty_ShortArg=0 66 | export ActionProperty_ShortUsage=1 67 | export ActionProperty_Options=2 68 | export ActionProperty_MinArgs=3 69 | export ActionProperty_MaxArgs=4 70 | export ActionProperty_Function=5 71 | export ActionProperty_RequireSudo=6 72 | export ActionProperty_LongUsage=7 73 | 74 | export Action_SignCode=("sign" "[-i identity] executable_file" "i:" 1 1 signCode false \ 75 | " Add code signature to . If is omitted, 76 | ldid is used. If is provided, codesign is used and the 77 | certificate of the matching digital identity in the Keychain is used.") 78 | 79 | export Action_BuildPackage=("build" "[-p version_plist] [-z] package_directory output_directory" "p:z" 2 2 buildPackage false \ 80 | " Build a Debian package using and place the package 81 | in . If is provided, the plist will be 82 | used to set the package's control file's Version field before building. 83 | If is provided, a zip file is created in also.") 84 | 85 | export Action_InstallPackage=("install" "[-h host_address] [-p host_port] package_file" "h:p:" 1 1 managePackageOnDevice false \ 86 | " Install on device at . If is 87 | omitted, the environment variable iOSOpenDevDevice is used. If 88 | is omitted, the environment variable iOSOpenDevPort is used or, if that 89 | variable does not exist, the default SSH port 22 is used.") 90 | 91 | export Action_RemovePackage=("remove" "[-h host_address] [-p host_port] package_name" "h:p:" 1 1 managePackageOnDevice false \ 92 | " Remove from device at . If 93 | is omitted, the environment variable iOSOpenDevDevice is used. If 94 | is omitted, the environment variable iOSOpenDevPort is used 95 | or, if that variable does not exist, the default SSH port 22 is used.") 96 | 97 | export Action_PurgePackage=("purge" "[-h host_address] [-p host_port] package_name" "h:p:" 1 1 managePackageOnDevice false \ 98 | " Purge from device at . If is 99 | omitted, the environment variable iOSOpenDevDevice is used. If 100 | is omitted, the environment variable iOSOpenDevPort is used or, if that 101 | variable does not exist, the default SSH port 22 is used.") 102 | 103 | export Action_DumpSDKHeaders=("dump" "[-i] [-z] framework_type output_directory" "iz" 2 2 dumpSDKHeaders false \ 104 | " Generate header files of the specified iOS SDK of its 105 | classes, categories and protocols in . If is 106 | omitted, class-dump-z is used. If is used, class-dump is used. If 107 | is provided, import statements are not converted from \"header.h\" 108 | to . All import statements, if the imported 109 | header file exists in the framework being processed, are converted to 110 | framework-style imports since the header files being dumped will be 111 | copied to SDK directories. If is springboard then 112 | import statements are not converted since the header files are placed 113 | in an include directory. 114 | 115 | Framework type options: 116 | public, private, springboard 117 | 118 | Outputted structure for public and private options: 119 | /Foo.framework/Headers/*.h 120 | 121 | Outputted structure for springboard option: 122 | /*.h") 123 | 124 | export Action_CopyHeadersToSDK=("cp2sdk" "[-t header_tag] framework_type source_directory" "t:" 2 2 copyHeadersToSDK true \ 125 | " Copy header files from to the location of the 126 | specified iOS SDK , tagging each header file with 127 | , if provided. Tagging is performed for distinguishability 128 | between original and other dumped header files. If is 129 | public and is empty, a header tag of \"_Dumped\" is used 130 | so that original SDK header files are not overwritten. 131 | 132 | Framework type options: 133 | public, private, springboard 134 | 135 | Valid source structures for public and private options: 136 | /Foo.framework/Headers/*.h 137 | /Foo.framework/*.h 138 | 139 | Valid source structure for springboard option: 140 | /*.h 141 | 142 | Location of public framework type: 143 | \$SDKROOT/System/Library/Frameworks 144 | 145 | Location of private framework type: 146 | \$SDKROOT/System/Library/PrivateFrameworks 147 | 148 | Location of springboard framework type: 149 | $iOSOpenDevPath/include/SpringBoard") 150 | 151 | export Action_DumpAndCopyHeaders=("dump2sdk" "[-i] [-z] [-t header_tag] framework_type" "it:z" 1 1 dumpAndCopyHeaders true \ 152 | " Generate and copy header files of the specified iOS SDK 153 | , tagging each header file with , if 154 | provided. If is omitted, class-dump-z is used. If is used, 155 | class-dump is used. If is provided, import statements are not 156 | converted from \"header.h\" to . 157 | 158 | Using this would be as if the dump argument was used then followed by 159 | the cp2sdk argument. Header files are outputted to a temporary 160 | directory which is removed. 161 | 162 | Framework type options: 163 | public, private, springboard") 164 | 165 | export Action_RemoveCopiedHeaders=("rmheaders" "framework_type header_tag" "" 2 2 removeCopiedHeaders true \ 166 | " Remove previously copied header files of the specified iOS SDK 167 | which are tagged with . 168 | 169 | Framework type options: 170 | public or private") 171 | 172 | export Action_AddSshKeyToDevice=("sshkey" "[-h host_address] [-p host_port] [-r]" "h:rp:" 0 0 addSshKeyToDevice false \ 173 | " Add the local user's public SSH authentication key as an authorized key 174 | to the root account of the device at . If 175 | is omitted, the environment variable iOSOpenDevDevice is used. If 176 | is omitted, the environment variable iOSOpenDevPort is used 177 | or, if that variable does not exist, the default SSH port 22 is used. If 178 | is omitted, the current user is used. If is used, root is used. 179 | If the local user does not already have a SSH authentication key then 180 | one will be generated and the passphrase to set for it will be asked. 181 | Adding a user's public SSH authentication key as an authorized key will 182 | allow public key authentication which requires no password upon log on 183 | of SSH connections. This is required for Xcode Build Phases of projects 184 | created from iOSOpenDev templates to function. This should be performed 185 | by the account that will be used for developing in Xcode. Public keys 186 | are stored in the root account's ~/.ssh/authorized_keys file.") 187 | 188 | export Action_DumpAllHeaders=("dumpall2sdk" "[-i] [-z]" "iz" 0 0 dumpAllHeaders true \ 189 | " Generate and copy header files of the iOS SDK framework types public, 190 | private and springboard. If is omitted, class-dump-z is used. If 191 | is used, class-dump is used. If is provided, import statements 192 | are not converted from \"header.h\" to .") 193 | 194 | export Action_RunCmdOnDevice=("run" "[-h host_address] [-p host_port] command ..." "h:p:" 0 2048 runCmdOnDevice false \ 195 | " Run on device at . If is 196 | omitted, the environment variable iOSOpenDevDevice is used. If 197 | is omitted, the environment variable iOSOpenDevPort is 198 | used or, if that variable does not exist, the default SSH port 22 199 | is used.") 200 | 201 | export Action_RunFuncOnDevice=("func" "[-h host_address] [-p host_port] function" "h:p:" 1 1 runFuncOnDevice false \ 202 | " Perform on device at . If is 203 | is omitted, the environment variable iOSOpenDevDevice is used. If 204 | is omitted, the environment variable iOSOpenDevPort is used 205 | or, if that variable does not exist, the default SSH port 22 is used. 206 | 207 | Available functions: 208 | respring, reboot") 209 | 210 | export Action_XcodeBuildPhaseLogos=("--xcbp-logos" "" "" 0 0 xcodeBuildPhase_Logos false \ 211 | " DO NOT USE. For use by Xcode as a Build Phase for projects created from 212 | iOSOpenDev templates only.") 213 | 214 | export Action_XcodeBuildPhase=("--xcbp" "" "" 0 0 xcodeBuildPhase false \ 215 | " DO NOT USE. For use by Xcode as a Build Phase for projects created from 216 | iOSOpenDev templates only.") 217 | 218 | export Action_SshToDevice=("ssh" "[-h host_address] [-p host_port]" "h:p:" 0 0 sshToDevice false \ 219 | " Secure Shell (SSH) to device at . If is 220 | omitted, the environment variable iOSOpenDevDevice is used. If 221 | is omitted, the environment variable iOSOpenDevPort is used 222 | or, if that variable does not exist, the default SSH port 22 is used.") 223 | 224 | export Action_UpdateIncludeAndLib=("update" "[-h host_address] [-p host_port]" "h:p:" 0 0 updateIncludeAndLib false \ 225 | " Update include and lib directories using device at . 226 | If is omitted, the environment variable 227 | iOSOpenDevDevice is used. If is omitted, the environment 228 | variable iOSOpenDevPort is used or, if that variable does not exist, 229 | the default SSH port 22 is used.") 230 | 231 | export Action_Help=("--help" "" "" 0 0 "" false \ 232 | " Show this help.") 233 | 234 | # === cleanup & panic === # 235 | 236 | function cleanup() # no args 237 | { 238 | local exitCode=$? 239 | set +e 240 | trap - $signals 241 | 242 | removeTempData 243 | 244 | exit $exitCode 245 | } 246 | export signals="0 1 2 3 15" 247 | trap cleanup $signals 248 | 249 | function panic() # args: exitCode, message... 250 | { 251 | local exitCode=$1 252 | set +e 253 | 254 | shift 255 | [[ "$@" == "" ]] || \ 256 | echo "$@" >&2 257 | 258 | exit $exitCode 259 | } 260 | 261 | # === common functions === # 262 | 263 | function determineBashProfileFile() 264 | { 265 | $setCmd 266 | 267 | local f 268 | local filePath 269 | 270 | for f in "${bashProfileFiles[@]}"; do 271 | if [[ -f "$f" ]]; then 272 | if [[ -n `perl -ne 'print $1 if /^(?:export)? *'"iOSOpenDevPath"'=(.*)$/' "$f"` ]]; then 273 | filePath="$f" 274 | break 275 | fi 276 | fi 277 | done 278 | 279 | if [[ $filePath == "" ]]; then 280 | 281 | filePath="$bashProfileFiles" # use first array item 282 | 283 | touch "$filePath" || \ 284 | panic $? "Failed to touch $filePath" 285 | 286 | changeOwn "$userName:$userGroup" "$filePath" 287 | changeMode 0600 "$filePath" 288 | fi 289 | 290 | # return # 291 | echo "$filePath" 292 | } 293 | 294 | function removeTempData() # no args 295 | { 296 | local tempDirs 297 | 298 | if [[ -f "$tempDirsFile" ]]; then 299 | tempDirs=(`cat "$tempDirsFile"`) 300 | 301 | for td in "${tempDirs[@]}"; do 302 | rm -rf "$td" || true # forget abou' it. 303 | done 304 | 305 | rm -rf "`dirname \"$tempDirsFile\"`" || true # forget abou' it. 306 | fi 307 | } 308 | 309 | function requireDir() # args: dirPath [, makeDirIfNotFound] 310 | { 311 | local dirPath="$1" 312 | local makeDirIfNotFound="$2" 313 | 314 | if [[ ! -d "$dirPath" ]]; then 315 | if [[ $makeDirIfNotFound == "true" ]]; then 316 | 317 | mkdir -p "$dirPath" || \ 318 | panic $? "Failed to create directory $dirPath" 319 | 320 | else 321 | panic 1 "Directory $dirPath not found" 322 | fi 323 | fi 324 | } 325 | 326 | function copyFile() # args: sourceFile, targetDirOrFile 327 | { 328 | local sourceFile="$1" 329 | local targetDirOrFile="$2" 330 | 331 | cp -fR "$sourceFile" "$targetDirOrFile" || \ 332 | panic $? "Failed to copy file $sourceFile to $targetDirOrFile" 333 | } 334 | 335 | function changeMode() # args: mode, target 336 | { 337 | local mode="$1" 338 | local target="$2" 339 | 340 | if [[ -e "$target" ]]; then 341 | 342 | chmod $mode "$target" || \ 343 | panic $? "Failed to change mode to $mode on $target" 344 | fi 345 | } 346 | 347 | function changeOwn() # args: ownerAndOrGroup, target 348 | { 349 | local ownerAndOrGroup="$1" 350 | local target="$2" 351 | 352 | if [[ -e "$target" ]]; then 353 | 354 | chown "$ownerAndOrGroup" "$target" || \ 355 | panic $? "Failed to change ownership to $ownerAndOrGroup on $target" 356 | fi 357 | } 358 | 359 | function requireFile() # args: filePath [, touchFileIfNotFound] 360 | { 361 | local filePath="$1" 362 | local touchFileIfNotFound="$2" 363 | 364 | if [[ ! -f "$filePath" ]]; then 365 | if [[ $touchFileIfNotFound == "true" ]]; then 366 | 367 | touch "$filePath" || \ 368 | panic $? "Failed to touch $filePath" 369 | 370 | else 371 | panic 1 "File $filePath not found" 372 | fi 373 | fi 374 | } 375 | 376 | function requireExportedVariable() # args: envVarName[, message] 377 | { 378 | local envVarName="$1" 379 | local message="$2" 380 | local value 381 | 382 | if [[ ${!envVarName} == "" ]]; then 383 | value=`getBashProfileEnvVarValue "$envVarName"` 384 | 385 | [[ $value != "" ]] || \ 386 | panic 1 "Environment variable $envVarName is not set or is empty" 387 | 388 | eval $envVarName='$value' 389 | export $envVarName 390 | fi 391 | } 392 | 393 | function createSymlink() # args: sourcePath, linkPath 394 | { 395 | local sourcePath="$1" 396 | local linkPath="$2" 397 | 398 | ln -fhs "$sourcePath" "$linkPath" || \ 399 | panic $? "Failed to create symbolic link $linkPath -> $sourcePath" 400 | } 401 | 402 | function extractTar() # args: tarPath, outputPath 403 | { 404 | local tarPath="$1" 405 | local outputPath="$2" 406 | 407 | tar -C "$outputPath" -zxf "$tarPath" || \ 408 | panic $? "Failed to extract $tarPath to $outputPath" 409 | } 410 | 411 | function copyFileToDevice() # args: sourceFile, targetDir, hostAddress, hostPort 412 | { 413 | local sourceFile="$1" 414 | local targetDir="$2" 415 | local hostAddress="$3" 416 | local hostPort="$4" 417 | local targetFilePath 418 | 419 | ssh -p$hostPort root@$hostAddress mkdir -p "\"$targetDir\"" || \ 420 | panic $? "Failed to create directory $targetDir on device $hostAddress" 421 | 422 | targetFilePath="$targetDir/`basename \"$sourceFile\"`" || \ 423 | panic $? "Failed to build target file path" 424 | 425 | ssh -p$hostPort root@$hostAddress rm -f "\"$targetFilePath\"" || \ 426 | panic $? "Failed to remove existing file $targetFilePath on device $hostAddress" 427 | 428 | scp -P$hostPort "$sourceFile" root@$hostAddress:"\"$targetFilePath\"" || \ 429 | panic $? "Failed to copy file $sourceFile to device $hostAddress at directory $targetDir" 430 | } 431 | 432 | function getSdkProperty() # args: sdk, propertyName 433 | { 434 | $setCmd 435 | 436 | local sdk="$1" 437 | local propertyName="$2" 438 | 439 | propertyValue=`xcodebuild -version -sdk $sdk $propertyName` || \ 440 | panic $? "Failed to get $sdk SDK property $propertyName" 441 | 442 | # return # 443 | echo "$propertyValue" 444 | } 445 | 446 | function getBashProfileEnvVarValue() # args: envVarName 447 | { 448 | $setCmd 449 | 450 | local envVarName="$1" 451 | local perlValue 452 | local bashProfileFile 453 | 454 | bashProfileFile=`determineBashProfileFile` 455 | 456 | perlValue=`perl -ne 'print $1 if /^(?:export)? *'"$envVarName"'=(.*)$/' "$bashProfileFile"` || \ 457 | panic $? "Failed to perl" 458 | 459 | # return # 460 | echo "$perlValue" 461 | } 462 | 463 | function getTempDir() # no args 464 | { 465 | $setCmd 466 | 467 | local tempDir 468 | 469 | tempDir=`mktemp -d -t $scriptName` || \ 470 | panic $? "Failed to create temporary directory" 471 | 472 | # remember the temp dir path; in cleanup() these are rm'd # 473 | 474 | echo "$tempDir" >> "$tempDirsFile" || \ 475 | panic $? "Failed to echo into temporary file $tempDirsFile" 476 | 477 | # return # 478 | echo "$tempDir" 479 | } 480 | 481 | function downloadFile() # args: sourceUrl, targetPath 482 | { 483 | local sourceUrl="$1" 484 | local targetPath="$2" 485 | local curlPath 486 | 487 | requireDir "${targetPath%/*}" true 488 | 489 | curlPath=`which curl` || \ 490 | panic $? "Failed to get curl path" 491 | 492 | "$curlPath" --silent --insecure --output "$targetPath" "$sourceUrl" || \ 493 | panic $? "Failed to download $sourceUrl to $targetPath" 494 | } 495 | 496 | # === sign (action) === # 497 | 498 | function signCode() # args: executableToSign, identityToSignWith 499 | { 500 | local executableToSign="$1" 501 | local identityToSignWith="$2" 502 | local cmdBin 503 | local cmdArg 504 | local codesignAllocatePath 505 | local entitlements="$CODE_SIGN_ENTITLEMENTS" 506 | 507 | # process arguments # 508 | 509 | requireFile "$executableToSign" false 510 | 511 | if [[ "$identityToSignWith" == "" || "$identityToSignWith" == "-" ]]; then 512 | 513 | # use ldid # 514 | 515 | cmdBin="ldid" 516 | 517 | if [[ "$entitlements" == "" ]]; then 518 | cmdArg=("-S") 519 | else 520 | cmdArg=("-S${PROJECT_DIR}/${entitlements}") 521 | fi 522 | 523 | else 524 | 525 | # use codesign # 526 | codesignAllocatePath=`xcodebuild -sdk iphoneos -find codesign_allocate` || \ 527 | panic $? "Failed to get codesign_allocate path" 528 | 529 | export CODESIGN_ALLOCATE="$codesignAllocatePath" 530 | 531 | cmdBin=`xcodebuild -sdk iphoneos -find codesign` || \ 532 | panic $? "Failed to get codesign path" 533 | 534 | if [[ "$entitlements" == "" ]]; then 535 | cmdArg=("-fs" "$identityToSignWith") 536 | else 537 | cmdArg=("-fs" "$identityToSignWith" "--entitlements" "${PROJECT_DIR}/${entitlements}") 538 | fi 539 | fi 540 | 541 | echo -n "Signing $executableToSign with `basename \"$cmdBin\"`... " 542 | 543 | "$cmdBin" "${cmdArg[@]}" "$executableToSign" || \ 544 | panic $? "Failed." 545 | 546 | # success # 547 | echo "Done." 548 | } 549 | 550 | 551 | # === build (action) === # 552 | 553 | function readDefaultsValue() # args: plistPath, propertyName 554 | { 555 | $setCmd 556 | 557 | local plistPath="$1" 558 | local propertyName="$2" 559 | local value 560 | 561 | value=`defaults read "${plistPath%.*}" "$propertyName"` || \ 562 | panic $? "Failed to read defaults property $propertyName from $plistPath" 563 | 564 | # return # 565 | echo "$value" 566 | } 567 | 568 | function getVersionFromVersionPList() # args: plistPath 569 | { 570 | $setCmd 571 | 572 | local plistPath="$1" 573 | local version 574 | local major 575 | local minor 576 | local bugFix 577 | local stage 578 | local pkgRev 579 | 580 | major=`readDefaultsValue "$plistPath" "Major"` 581 | minor=`readDefaultsValue "$plistPath" "Minor"` 582 | bugFix=`readDefaultsValue "$plistPath" "BugFix"` 583 | stage=`readDefaultsValue "$plistPath" "Stage"` 584 | pkgRev=`readDefaultsValue "$plistPath" "PackageRevision"` 585 | 586 | version="$major.$minor" 587 | 588 | [[ "$bugFix" == "" ]] || version+=".$bugFix" 589 | [[ "$stage" == "" ]] || version+="$stage" 590 | [[ "$pkgRev" == "" ]] || version+="-$pkgRev" 591 | 592 | # return # 593 | echo "$version" 594 | } 595 | 596 | function setControlFileVersionFieldUsingVersionPList() # args: controlFile, plistPath 597 | { 598 | local controlFile="$1" 599 | local plistPath="$2" 600 | local versionReadFromPList 601 | 602 | requireFile "$controlFile" false 603 | requireFile "$plistPath" false 604 | 605 | # read plist to get version # 606 | 607 | versionReadFromPList=`getVersionFromVersionPList "$plistPath"` 608 | 609 | [[ $versionReadFromPList != "" ]] || \ 610 | panic 1 "Failed to read version from $plistPath" 611 | 612 | # write version to control file # 613 | 614 | echo -n "Setting control file $controlFile Version field to $versionReadFromPList using $plistPath... " 615 | 616 | sed -i "" "s/Version:.*/Version: $versionReadFromPList/g" "$controlFile" || \ 617 | panic $? "Failed." 618 | 619 | # success # 620 | echo "Done." 621 | } 622 | 623 | function getControlFieldValue() # args: controlFile, fieldName [, isRequired] 624 | { 625 | $setCmd 626 | 627 | local controlFile="$1" 628 | local fieldName="$2" 629 | local isRequired="$3" 630 | local perlValue 631 | 632 | perlValue=`perl -ne 'print $1 if /^'"$fieldName"': *(.*) *$/' "$controlFile"` || \ 633 | panic $? "Failed perl command using $controlFile" 634 | 635 | if [[ "$perlValue" == "" ]] && [[ "$isRequired" == "true" ]]; then 636 | panic 1 "Missing control field: $fieldName" 637 | fi 638 | 639 | # return # 640 | echo "$perlValue" 641 | } 642 | 643 | 644 | function getPackageFileNameUsingControlFile() # args: controlFile 645 | { 646 | $setCmd 647 | 648 | local controlFile="$1" 649 | local pkgId 650 | local pkgVer 651 | local pkgArch 652 | 653 | pkgId=`getControlFieldValue "$controlFile" Package true` 654 | pkgVer=`getControlFieldValue "$controlFile" Version true` 655 | pkgArch=`getControlFieldValue "$controlFile" Architecture true` 656 | 657 | # return # 658 | echo "${pkgId}_${pkgVer}_${pkgArch}" 659 | } 660 | 661 | function buildPackage() # args: packageDir, outputDir, versionPList [, useZOption] 662 | { 663 | local packageDir="$1" 664 | local outputDir="$2" 665 | local versionPList="$3" 666 | local useZOption="$4" 667 | local subFileControlTxtToRemove="$packageDir/DEBIAN/control.txt" 668 | local subFilesToRemove=(".DS_Store" "0xdeadfa11") 669 | local packageFileName 670 | local packageName 671 | local zipFileName 672 | 673 | echo "Preparing to build package..." 674 | 675 | # verify arguments # 676 | 677 | requireDir "$packageDir" 678 | 679 | requireDir "$outputDir" true 680 | 681 | [[ "$versionPList" == "" ]] || \ 682 | requireFile "$versionPList" false 683 | 684 | # cleanup # 685 | 686 | [[ ! -f "$subFileControlTxtToRemove" ]] || \ 687 | rm -f "$subFileControlTxtToRemove" || \ 688 | panic $? "Failed to remove file $subFileControlTxtToRemove" 689 | 690 | for f in "${subFilesToRemove[@]}"; do 691 | find "$packageDir" -type f -name "$f" -exec rm -f '{}' \; || \ 692 | panic $? "Failed to remove file $f" 693 | done 694 | 695 | xattr -crs "$packageDir" || true # forget abou' it (does not work on 10.6) 696 | 697 | changeMode 0644 "$packageDir/DEBIAN/control" 698 | changeMode 0755 "$packageDir/DEBIAN/preinst" 699 | changeMode 0755 "$packageDir/DEBIAN/postinst" 700 | changeMode 0755 "$packageDir/DEBIAN/prerm" 701 | changeMode 0755 "$packageDir/DEBIAN/postrm" 702 | 703 | # set control file version field # 704 | 705 | [[ "$versionPList" == "" ]] || \ 706 | setControlFileVersionFieldUsingVersionPList "$packageDir/DEBIAN/control" "$versionPList" 707 | 708 | # determine package name # 709 | 710 | packageName=`getPackageFileNameUsingControlFile "$packageDir/DEBIAN/control"` 711 | 712 | # create package # 713 | 714 | createDebianPackage "$packageDir" "$packageName" "$outputDir" 715 | 716 | # create zip # 717 | 718 | if [[ $useZOption == "true" ]]; then 719 | 720 | zipFileName="$outputDir/${packageName}.zip" 721 | 722 | echo -n "Creating zip $zipFileName... " 723 | 724 | rm -f "$zipFileName" || \ 725 | panic $? "Failed to remove $zipFileName" 726 | 727 | pushd "$packageDir" 1> /dev/null 728 | 729 | zip -qrX "$zipFileName" * || \ 730 | panic $? "Failed." 731 | 732 | popd 1> /dev/null 733 | 734 | echo "Done." 735 | fi 736 | } 737 | 738 | function createDebianPackage() # args: sourceDir, packageName [, outputDir] 739 | { 740 | $setCmd 741 | 742 | local sourceDir="$1" 743 | local packageName="$2" 744 | local outputDir="$3" 745 | 746 | local packageFile="${outputDir:-.}/$packageName.deb" 747 | 748 | echo -n "Building package $packageFileName... " 749 | 750 | local tempDir="`getTempDir`" 751 | 752 | createTarForDebianPackage "$sourceDir/DEBIAN" "$tempDir" "control" "-n" 753 | createTarForDebianPackage "$sourceDir" "$tempDir" "data" "--exclude" "DEBIAN/*" "--exclude" "DEBIAN" 754 | 755 | echo "2.0" > "$tempDir/debian-binary" || \ 756 | panic $? "Failed to create debian-binary file" 757 | 758 | ar -rc "$packageFile" "$tempDir/debian-binary" "$tempDir/control.tar.gz" "$tempDir/data.tar.gz" || \ 759 | panic $? "Failed to create Debian archive" 760 | 761 | echo "Done." 762 | } 763 | 764 | function createTarForDebianPackage() # args: sourceDir, outputDir, tarName [, options] 765 | { 766 | $setCmd 767 | 768 | local sourceDir="$1" 769 | local outputDir="$2" 770 | local tarName="$3" 771 | shift 3 772 | 773 | pushd "$sourceDir" 1> /dev/null 774 | 775 | tar -cLpz --disable-copyfile --exclude ".*" "$@" -f "$outputDir/$tarName.tar.gz" * || \ 776 | panic $? "Failed to create $tarName archive" 777 | 778 | popd 1> /dev/null 779 | } 780 | 781 | 782 | # === install, remove, purge (actions) === # 783 | 784 | function managePackageOnDevice() # args: manageAction, packageFileOrName, hostAddress, hostPort 785 | { 786 | local manageAction="$1" 787 | local packageFileOrName="$2" 788 | local hostAddress="$3" 789 | local hostPort="$4" 790 | local doingWhat 791 | local direction 792 | local didWhat 793 | local cmdBin="dpkg" 794 | local cmdArg 795 | local devicePackagesDir 796 | 797 | if [[ "$manageAction" == "install" ]]; then 798 | doingWhat="Installing" 799 | direction="on" 800 | didWhat="installed" 801 | cmdArg="--install" 802 | elif [[ "$manageAction" == "remove" ]]; then 803 | doingWhat="Removing" 804 | direction="from" 805 | didWhat="removed" 806 | cmdArg="--remove" 807 | elif [[ "$manageAction" == "purge" ]]; then 808 | doingWhat="Purging" 809 | direction="from" 810 | didWhat="purged" 811 | cmdArg="--purge" 812 | else 813 | panic 1 "Invalid manage action: $manageAction" 814 | fi 815 | 816 | if [[ $hostAddress == "" ]]; then 817 | 818 | requireExportedVariable "iOSOpenDevDevice" 819 | 820 | hostAddress="$iOSOpenDevDevice" 821 | 822 | [[ $hostAddress != "" ]] || \ 823 | panic 1 "Host address not provided and environment variable iOSOpenDevDevice is not set or is empty" 824 | fi 825 | 826 | if [[ $hostPort == "" ]]; then 827 | 828 | hostPort="$iOSOpenDevPort" 829 | 830 | [[ $hostPort != "" ]] || hostPort="22" 831 | 832 | fi 833 | 834 | # if installing, copy package to device # 835 | 836 | if [[ $manageAction == "install" ]]; then 837 | 838 | requireFile "$packageFileOrName" false 839 | 840 | devicePackagesDir="/var/root/iOSOpenDevPackages" 841 | 842 | copyFileToDevice "$packageFileOrName" "$devicePackagesDir" "$hostAddress" "$hostPort" 843 | 844 | packageFileOrName="$devicePackagesDir/`basename \"$packageFileOrName\"`" 845 | fi 846 | 847 | # install, remove or purge package # 848 | 849 | echo "$doingWhat package `basename \"$packageFileOrName\"` $direction device $hostAddress... " 850 | 851 | ssh -p$hostPort root@$hostAddress "$cmdBin" $cmdArg "$packageFileOrName" || \ 852 | panic $? "Failed." 853 | 854 | # success # 855 | echo "Done." 856 | } 857 | 858 | # === rmheaders (action) === # 859 | 860 | function removeCopiedHeaders() # args: removeWhat, headerFileTag 861 | { 862 | local removeWhat="$1" 863 | local headerFileTag="$2" 864 | local fileNamePattern="*${headerFileTag}.h" 865 | local iosSdkPath 866 | local basePath 867 | local foundFiles 868 | local f 869 | 870 | [[ "$removeWhat" != "public" || "$headerFileTag" != "" ]] || \ 871 | panic 1 "Invalid option: cannot target public frameworks with an empty header tag" 872 | 873 | iosSdkPath=`getSdkProperty iphoneos Path` 874 | requireDir "$iosSdkPath" 875 | 876 | if [[ $removeWhat == "private" ]]; then 877 | basePath="$iosSdkPath/System/Library/PrivateFrameworks" 878 | elif [[ $removeWhat == "public" ]]; then 879 | basePath="$iosSdkPath/System/Library/Frameworks" 880 | else 881 | panic $? "Invalid option: $removeWhat" 882 | fi 883 | requireDir "$basePath" 884 | 885 | # find and remove header files # 886 | 887 | foundFiles=(`find "$basePath" -type f -name "$fileNamePattern"`) 888 | 889 | if [[ "${#foundFiles[@]}" != 0 ]]; then 890 | 891 | echo "Removing ${#foundFiles[@]} header files matching '$fileNamePattern' in iOS SDK $removeWhat frameworks..." 892 | 893 | for f in "${foundFiles[@]}"; do 894 | rm -f "$f" || \ 895 | panic $? "Failed to remove file $f" 896 | done 897 | 898 | else 899 | echo "No header files found matching '$fileNamePattern' in iOS SDK $removeWhat frameworks" 900 | fi 901 | } 902 | 903 | # === cp2sdk (action) === # 904 | 905 | function copyHeadersToSDK() # args: copyWhat, sourceDirectory [, headerFileTag] 906 | { 907 | local copyWhat="$1" 908 | local sourceDirectory="$2" 909 | local headerFileTag="$3" 910 | local iosSdkPath 911 | local targetBasePath 912 | local dontUseHeadersDir=false 913 | local copyingToWhere 914 | 915 | requireDir "$sourceDirectory" 916 | 917 | iosSdkPath=`getSdkProperty iphoneos Path` 918 | requireDir "$iosSdkPath" 919 | 920 | if [[ $copyWhat == "private" ]]; then 921 | targetBasePath="$iosSdkPath/System/Library/PrivateFrameworks" 922 | copyingToWhere="iOS SDK $copyWhat frameworks" 923 | 924 | elif [[ $copyWhat == "public" ]]; then 925 | targetBasePath="$iosSdkPath/System/Library/Frameworks" 926 | copyingToWhere="iOS SDK $copyWhat frameworks" 927 | [[ $headerFileTag != "" ]] || \ 928 | headerFileTag="_Dumped" 929 | 930 | elif [[ $copyWhat == "springboard" ]]; then 931 | targetBasePath="$iOSOpenDevPath/include/SpringBoard" 932 | copyingToWhere="$targetBasePath" 933 | dontUseHeadersDir=true 934 | requireDir "$targetBasePath" true # <-- for springboard only (since headers don't go in SDK) 935 | 936 | else 937 | panic $? "Invalid option: $copyWhat" 938 | fi 939 | 940 | requireDir "$targetBasePath" 941 | 942 | echo "Copying header files from $sourceDirectory to $copyingToWhere..." 943 | 944 | processDirToCopyHeadersToSDK "$sourceDirectory" "$sourceDirectory" "$targetBasePath" "$headerFileTag" "$dontUseHeadersDir" 945 | } 946 | 947 | function processDirToCopyHeadersToSDK() # args: pathToTrimOffFromTargetHeaderFilePaths, sourceDirectory, targetBasePath, headerFileTag, dontUseHeadersDir 948 | { 949 | local pathToTrimOffFromTargetHeaderFilePaths="$1" 950 | local sourceDirectory="$2" 951 | local targetBasePath="$3" 952 | local headerFileTag="$4" 953 | local dontUseHeadersDir="$5" 954 | 955 | local foundDirs 956 | local d 957 | local foundFiles 958 | local f 959 | 960 | local fileName 961 | local sourceDirectoryWithNoHeaders 962 | local targetDir 963 | local targetfile 964 | 965 | # files # 966 | 967 | foundFiles=(`find "$sourceDirectory" -type f -maxdepth 1 -mindepth 1 -name "*.h"`) 968 | 969 | for f in "${foundFiles[@]}"; do 970 | sourceDirectoryWithNoHeaders="${sourceDirectory%/Headers}" 971 | targetDir="$targetBasePath${sourceDirectoryWithNoHeaders/#$pathToTrimOffFromTargetHeaderFilePaths}" 972 | 973 | [[ $dontUseHeadersDir == "true" ]] || \ 974 | targetDir+="/Headers" 975 | 976 | fileName="${f/#$sourceDirectory}" 977 | targetfile="${targetDir}${fileName%.h}${headerFileTag}.h" 978 | 979 | requireDir "$targetDir" true 980 | changeMode 0777 "$targetDir" 981 | 982 | copyFile "$f" "$targetfile" 983 | changeMode 0666 "$targetfile" 984 | done 985 | 986 | # dirs # 987 | 988 | foundDirs=(`find -E "$sourceDirectory" -type d -maxdepth 1 -mindepth 1 -iregex "^.*/(Frameworks|.+\.framework|Headers)$"`) 989 | 990 | for d in "${foundDirs[@]}"; do 991 | processDirToCopyHeadersToSDK "$pathToTrimOffFromTargetHeaderFilePaths" "$d" "$targetBasePath" "$headerFileTag" $dontUseHeadersDir 992 | done 993 | } 994 | 995 | # === dump === # 996 | 997 | function dumpSDKHeaders() # args: dumpWhat, outputDirectory [, useZOption] [, useIOption] 998 | { 999 | local dumpWhat="$1" 1000 | local outputDirectory="$2" 1001 | local useZOption="$3" 1002 | local useIOption="$4" 1003 | local iosSdkPath 1004 | local iosSdkVersion 1005 | local sourceBasePath 1006 | local classDumpBin 1007 | local classDumpArgs 1008 | local dontUseHeadersDir=false 1009 | local dumpingWhat 1010 | 1011 | iosSdkPath=`getSdkProperty iphoneos Path` 1012 | requireDir "$iosSdkPath" 1013 | 1014 | iosSdkVersion=`getSdkProperty iphoneos SDKVersion` 1015 | 1016 | if [[ $dumpWhat == "private" ]]; then 1017 | sourceBasePath="$iosSdkPath/System/Library/PrivateFrameworks" 1018 | dumpingWhat="iOS SDK $dumpWhat frameworks" 1019 | elif [[ $dumpWhat == "public" ]]; then 1020 | sourceBasePath="$iosSdkPath/System/Library/Frameworks" 1021 | dumpingWhat="iOS SDK $dumpWhat frameworks" 1022 | elif [[ $dumpWhat == "springboard" ]]; then 1023 | sourceBasePath="$iosSdkPath/System/Library/CoreServices/SpringBoard.app" 1024 | dumpingWhat="iOS SpringBoard Core Service" 1025 | dontUseHeadersDir="true" 1026 | else 1027 | panic $? "Invalid option: $dumpWhat" 1028 | fi 1029 | 1030 | if [[ $useZOption == "true" ]]; then 1031 | classDumpBin="class-dump" 1032 | classDumpArgs="--sdk-ios $iosSdkVersion" 1033 | else 1034 | classDumpBin="class-dump-z" 1035 | classDumpArgs="-pabkkAR -X NS,CF,CG -y $iosSdkPath" 1036 | fi 1037 | 1038 | classDumpBin="`which $classDumpBin`" || \ 1039 | panic $? "Failed to get $classDumpBin path" 1040 | 1041 | echo "Dumping header files of $dumpingWhat to $outputDirectory..." 1042 | 1043 | processDirToDumpSDKHeaders "$sourceBasePath" "$sourceBasePath" "$outputDirectory" $dontUseHeadersDir 1044 | 1045 | if [[ $useIOption != "true" ]]; then 1046 | echo "Fixing import statements..." 1047 | cleanUpDumpedHeaderFiles "$outputDirectory" "$dumpWhat" 1048 | fi 1049 | } 1050 | 1051 | function processDirToDumpSDKHeaders() # args: pathToTrimOffFromTargetHeaderFilePaths, sourceDirectory, outputDirectory, dontUseHeadersDir 1052 | { 1053 | local pathToTrimOffFromTargetHeaderFilePaths="$1" 1054 | local sourceDirectory="$2" 1055 | local outputDirectory="$3" 1056 | local dontUseHeadersDir="$4" 1057 | local foundDirs 1058 | local d 1059 | local foundFiles 1060 | local f 1061 | local targetPath 1062 | 1063 | # files # 1064 | 1065 | foundFiles=(`find -E "$sourceDirectory" -type f -maxdepth 1 -mindepth 1 -iregex "^.*/([^.]+|.+\.dylib|.+\.o)?$" -not -name "PkgInfo"`) 1066 | 1067 | for f in "${foundFiles[@]}"; do 1068 | targetPath="$outputDirectory${sourceDirectory/#$pathToTrimOffFromTargetHeaderFilePaths}" 1069 | 1070 | [[ $dontUseHeadersDir == "true" ]] || \ 1071 | targetPath+="/Headers" 1072 | 1073 | requireDir "$targetPath" true 1074 | "$classDumpBin" $classDumpArgs -H -o "$targetPath" "$f" 2>/dev/null || true # forget abou' it. 1075 | done 1076 | 1077 | # dirs # 1078 | 1079 | foundDirs=(`find "$sourceDirectory" -type d -maxdepth 1 -mindepth 1 -not -name "Headers" -not -name "_CodeSignature"`) 1080 | 1081 | for d in "${foundDirs[@]}"; do 1082 | processDirToDumpSDKHeaders "$pathToTrimOffFromTargetHeaderFilePaths" "$d" "$outputDirectory" $dontUseHeadersDir 1083 | done 1084 | } 1085 | 1086 | function cleanUpDumpedHeaderFiles() # args: baseDir [, forWhat] 1087 | { 1088 | local baseDir="$1" 1089 | local forWhat="$2" 1090 | local removals=("NSObject\\.h" "NSString\\.h") 1091 | local r 1092 | local files 1093 | local f 1094 | local fileDir 1095 | local fwDirBaseName 1096 | local fwName 1097 | local imports 1098 | local i 1099 | local fileName 1100 | local origFileContents 1101 | local newFileContents 1102 | local fName 1103 | 1104 | # springboard only: move XXUnknownSuperclass.h to SBUnknownSuperclass.h 1105 | 1106 | if [[ $forWhat == "springboard" && -f "$baseDir/XXUnknownSuperclass.h" ]]; then 1107 | mv -f "$baseDir/XXUnknownSuperclass.h" "$baseDir/SBUnknownSuperclass.h" || \ 1108 | panic $? "Failed to move $baseDir/XXUnknownSuperclass.h to $baseDir/SBUnknownSuperclass.h" 1109 | fi 1110 | 1111 | # find files 1112 | 1113 | files=(`find "$baseDir" -name '*.h'`) 1114 | 1115 | # remove imports (in $removals) 1116 | 1117 | for r in "${removals[@]}"; do 1118 | for f in "${files[@]}"; do 1119 | perl -i -pe 's/^#import "'"$r"'"$//g' "$f" || \ 1120 | panic $? "Failed to perl $f" 1121 | done 1122 | done 1123 | 1124 | # iterate through all files 1125 | 1126 | for f in "${files[@]}"; do 1127 | fName="${f##*/}" 1128 | fileDir="${f%/*}" 1129 | fwDirBaseName="${f%.framework/*}" 1130 | fwName="${fwDirBaseName##*/}" 1131 | 1132 | origFileContents=`cat "$f"` || \ 1133 | panic $? "Failed to cat $f" 1134 | newFileContents="$origFileContents" 1135 | 1136 | if [[ $forWhat != "springboard" ]]; then 1137 | # change "headerfile.h" imports to imports (if headerfile.h exists in framework's directory) 1138 | 1139 | set +e 1140 | imports=(`perl -ne 'print if /#import[\s]+"[^\/]+"/' "$f"`) 1141 | set -e 1142 | 1143 | for i in "${imports[@]}"; do 1144 | if [[ "$i" == \"*\" ]]; then 1145 | fileName=${i//\"/} 1146 | if [[ -f "$fileDir/$fileName" ]]; then 1147 | newFileContents=`echo "$newFileContents" | sed "s/^#import *\"$fileName\"/#import \\<$fwName\\/$fileName\\>/g"` || \ 1148 | panic $? "Failed to echo into sed" 1149 | fi 1150 | fi 1151 | done 1152 | fi 1153 | 1154 | # address XXUnknownSuperclass 1155 | 1156 | if [[ -f "$fileDir/XXUnknownSuperclass.h" ]] || [[ $forWhat == "springboard" && -f "$fileDir/SBUnknownSuperclass.h" ]]; then 1157 | 1158 | # XXUnknownSuperclass.h found ... 1159 | 1160 | if [[ $forWhat != "springboard" ]]; then 1161 | # change to 1162 | newFileContents=`echo "$newFileContents" | sed "s/^#import *\\\( *\\/\\/ *Unknown library\)/#import \\<${fwName}\\/XXUnknownSuperclass\\.h\\>/g"` || \ 1163 | panic $? "Failed to echo into sed" 1164 | 1165 | else 1166 | # change to "SBUnknownSuperclass.h" 1167 | newFileContents=`echo "$newFileContents" | sed "s/^#import *\\\( *\\/\\/ *Unknown library\)/#import \\"SBUnknownSuperclass\\.h\\"/g"` || \ 1168 | panic $? "Failed to echo into sed" 1169 | 1170 | # change XXUnknownSuperclass to SBUnknownSuperclass 1171 | newFileContents=`echo "$newFileContents" | sed "s/XXUnknownSuperclass/SBUnknownSuperclass/g"` || \ 1172 | panic $? "Failed to echo into sed" 1173 | fi 1174 | else 1175 | # XXUnknownSuperclass.h not found ... 1176 | 1177 | # remove import of 1178 | newFileContents=`echo "$newFileContents" | sed "s/^#import *\\\( *\\/\\/ *Unknown library\)//g"` || \ 1179 | panic $? "Failed to echo into sed" 1180 | 1181 | # replace XXUnknownSuperclass with NSObject 1182 | newFileContents=`echo "$newFileContents" | sed "s/ *: *XXUnknownSuperclass */ : NSObject /g"` || \ 1183 | panic $? "Failed to echo into sed" 1184 | fi 1185 | 1186 | # TODO: insert (XX|SB)UnknownSuperclass interface 1187 | #if [[ $fName == "XXUnknownSuperclass.h" ]]; then 1188 | # "@interface XXUnknownSuperclass : NSObject" 1189 | # "@end" 1190 | #elif [[ $forWhat == "springboard" && $fName == "SBUnknownSuperclass.h" ]]; then 1191 | # "@interface SBUnknownSuperclass : NSObject" 1192 | # "@end" 1193 | #fi 1194 | 1195 | # rewrite file (if changed) 1196 | 1197 | [[ $origFileContents == "$newFileContents" ]] || \ 1198 | echo "$newFileContents" > "$f" || \ 1199 | panic $? "Failed to echo into $f" 1200 | done 1201 | } 1202 | 1203 | # === dump2sdk (action) === # 1204 | 1205 | function dumpAndCopyHeaders() # args: copyWhat [, headerFileTag] [, useZOption] [, useIOption] 1206 | { 1207 | local copyWhat="$1" 1208 | local headerFileTag="$2" 1209 | local useZOption="$3" 1210 | local useIOption="$4" 1211 | local tmpDir 1212 | 1213 | tmpDir=`getTempDir` 1214 | 1215 | dumpSDKHeaders "$copyWhat" "$tmpDir" "$useZOption" "$useIOption" 1216 | 1217 | copyHeadersToSDK "$copyWhat" "$tmpDir" "$headerFileTag" 1218 | } 1219 | 1220 | # === sshkey (action) === # 1221 | 1222 | function addSshKeyToDevice() # args: [hostAddress] [, useROption] [, hostPort] 1223 | { 1224 | local hostAddress="$1" 1225 | local useROption="$2" 1226 | local hostPort="$3" 1227 | local homeDir=`eval echo ~$USER` 1228 | local privateKeyPath="$homeDir/.ssh/id_rsa" 1229 | local publicKeyPath="$homeDir/.ssh/id_rsa.pub" 1230 | local authorizedKeysPath="/var/root/.ssh/authorized_keys" 1231 | local publicKey 1232 | local sshKeygenBin 1233 | local existingAuthorizedKeys 1234 | local grepExit 1235 | 1236 | if [[ "$useROption" == "true" ]]; then 1237 | local argsWithoutROption=(${originalArguments[@]/-r/}) 1238 | requireSudo "${argsWithoutROption[@]}" 1239 | fi 1240 | 1241 | if [[ $hostAddress == "" ]]; then 1242 | 1243 | requireExportedVariable "iOSOpenDevDevice" 1244 | hostAddress="$iOSOpenDevDevice" 1245 | 1246 | [[ $hostAddress != "" ]] || \ 1247 | panic 1 "Host address not provided and environment variable iOSOpenDevDevice is not set or is empty" 1248 | fi 1249 | 1250 | if [[ $hostPort == "" ]]; then 1251 | 1252 | hostPort="$iOSOpenDevPort" 1253 | 1254 | [[ $hostPort != "" ]] || \ 1255 | hostPort=22 1256 | fi 1257 | 1258 | sshKeygenBin=`which ssh-keygen` || \ 1259 | panic $? "Failed to get ssh-keygen path" 1260 | 1261 | if [[ ! -f "$publicKeyPath" ]]; then 1262 | echo "User's SSH authentication key does not exist, generating..." 1263 | "$sshKeygenBin" -t rsa -f "$privateKeyPath" || \ 1264 | panic $? "Failed to generate SSH authentication key" 1265 | fi 1266 | 1267 | requireFile "$publicKeyPath" false 1268 | 1269 | publicKey=`cat "$publicKeyPath"` || \ 1270 | panic $? "Failed to cat $publicKeyPath" 1271 | 1272 | echo "Reading existing authorized keys from device $iOSOpenDevDevice..." 1273 | 1274 | existingAuthorizedKeys=`ssh -p$hostPort -T root@$hostAddress << EOF 1275 | if [[ ! -d "${authorizedKeysPath%/*}" ]]; then 1276 | mkdir "${authorizedKeysPath%/*}" 1277 | chmod 700 "${authorizedKeysPath%/*}" 1278 | fi 1279 | if [[ ! -f "$authorizedKeysPath" ]]; then 1280 | touch "$authorizedKeysPath" 1281 | chmod 600 "$authorizedKeysPath" 1282 | fi 1283 | cat "$authorizedKeysPath" 1284 | EOF 1285 | ` || panic $? "Failed to read $authorizedKeysPath on device $hostAddress" 1286 | 1287 | set +e 1288 | echo "$existingAuthorizedKeys" | grep -q "$publicKey" || grepExit=$? 1289 | set -e 1290 | 1291 | if [[ $grepExit == 2 ]]; then 1292 | panic 2 "Failed to pipe echo into grep" 1293 | elif [[ $grepExit == 1 ]]; then 1294 | echo "Writing SSH authentication public key of local account $USER to device..." 1295 | ssh -p$hostPort root@$hostAddress echo "$publicKey" \>\> "$authorizedKeysPath" || \ 1296 | panic $? "Failed to append public key to $authorizedKeysPath on device $hostAddress" 1297 | 1298 | echo "Password-less SSH connections can now be performed by local account 1299 | $USER to the root account on device $hostAddress." 1300 | elif [[ $grepExit == "" || $grepExit == 0 ]]; then 1301 | echo "Public key is already authorized." 1302 | fi 1303 | } 1304 | 1305 | # === dumpall2sdk (Action) === # 1306 | 1307 | function dumpAllHeaders() # args: [useZOption] [, useIOption] 1308 | { 1309 | local useZOption="$1" 1310 | local useIOption="$2" 1311 | 1312 | dumpAndCopyHeaders "public" "" "$useZOption" "$useIOption" 1313 | dumpAndCopyHeaders "private" "" "$useZOption" "$useIOption" 1314 | dumpAndCopyHeaders "springboard" "" "$useZOption" "$useIOption" 1315 | } 1316 | 1317 | # === run (Action) === # 1318 | 1319 | function runCmdOnDevice() # args: $hostAddress, [, hostPort] ... 1320 | { 1321 | local hostAddress="$1" 1322 | local hostPort="$2" 1323 | shift 2 1324 | 1325 | if [[ $hostAddress == "" ]]; then 1326 | 1327 | requireExportedVariable "iOSOpenDevDevice" 1328 | 1329 | hostAddress="$iOSOpenDevDevice" 1330 | 1331 | [[ $hostAddress != "" ]] || \ 1332 | panic 1 "Host address not provided and environment variable iOSOpenDevDevice is not set or is empty" 1333 | fi 1334 | 1335 | if [[ $hostPort == "" ]]; then 1336 | 1337 | hostPort="$iOSOpenDevPort" 1338 | 1339 | [[ $hostPort != "" ]] || \ 1340 | hostPort=22 1341 | 1342 | fi 1343 | 1344 | ssh -p$hostPort root@$hostAddress "$@" || \ 1345 | panic $? "Failed to run $@ on device $hostAddress" 1346 | } 1347 | 1348 | # === ssh (Action) === # 1349 | 1350 | function sshToDevice() # args: $hostAddress, $hostPort 1351 | { 1352 | local hostAddress="$1" 1353 | local hostPort="$2" 1354 | 1355 | if [[ $hostAddress == "" ]]; then 1356 | 1357 | requireExportedVariable "iOSOpenDevDevice" 1358 | 1359 | hostAddress="$iOSOpenDevDevice" 1360 | 1361 | [[ $hostAddress != "" ]] || \ 1362 | panic 1 "Host address not provided and environment variable iOSOpenDevDevice is not set or is empty" 1363 | fi 1364 | 1365 | if [[ $hostPort == "" ]]; then 1366 | 1367 | hostPort="$iOSOpenDevPort" 1368 | 1369 | [[ $hostPort != "" ]] || \ 1370 | hostPort=22 1371 | 1372 | fi 1373 | 1374 | ssh -p$hostPort root@$hostAddress || \ 1375 | panic $? "Failed to SSH to device $hostAddress" 1376 | } 1377 | 1378 | # === update (Action) === # 1379 | 1380 | function updateIncludeAndLib() # args: $hostAddress, $hostPort 1381 | { 1382 | local hostAddress="$1" 1383 | local hostPort="$2" 1384 | 1385 | if [[ $hostAddress == "" ]]; then 1386 | 1387 | requireExportedVariable "iOSOpenDevDevice" 1388 | 1389 | hostAddress="$iOSOpenDevDevice" 1390 | 1391 | [[ $hostAddress != "" ]] || \ 1392 | panic 1 "Host address not provided and environment variable iOSOpenDevDevice is not set or is empty" 1393 | fi 1394 | 1395 | if [[ $hostPort == "" ]]; then 1396 | 1397 | hostPort="$iOSOpenDevPort" 1398 | 1399 | [[ $hostPort != "" ]] || \ 1400 | hostPort=22 1401 | 1402 | fi 1403 | 1404 | # include 1405 | 1406 | echo "Updating include files..." 1407 | 1408 | copyFromDevice $hostAddress "/usr/include/ActionMenu/ActionMenu.h" "$iOSOpenDevPath/include/ActionMenu" "$hostPort" 1409 | copyFromDevice $hostAddress "/usr/include/SiriObjects.h" "$iOSOpenDevPath/include/AssistantExtensions" "$hostPort" 1410 | downloadFile "https://raw.github.com/rpetrich/CaptainHook/master/CaptainHook.h" "$iOSOpenDevPath/include/CaptainHook/CaptainHook.h" 1411 | copyFromDevice $hostAddress "/usr/include/libactivator/libactivator.h" "$iOSOpenDevPath/include/libactivator" "$hostPort" 1412 | copyFromDevice $hostAddress "/usr/include/substrate.h" "$iOSOpenDevPath/include" "$hostPort" 1413 | 1414 | # lib 1415 | 1416 | echo "Updating lib files..." 1417 | 1418 | copyFromDevice $hostAddress "/usr/lib/libactionmenu.dylib" "$iOSOpenDevPath/lib" "$hostPort" 1419 | copyFromDevice $hostAddress "/usr/lib/libactivator.dylib" "$iOSOpenDevPath/lib" "$hostPort" 1420 | copyFromDevice $hostAddress "/usr/lib/libsubstrate.dylib" "$iOSOpenDevPath/lib" "$hostPort" 1421 | } 1422 | 1423 | function copyFromDevice() # args: hostAddress, sourceFile, targetDir, hostPort 1424 | { 1425 | local hostAddress="$1" 1426 | local sourceFile="$2" 1427 | local targetDir="$3" 1428 | local hostPort="$4" 1429 | 1430 | requireDir "$targetDir" true 1431 | 1432 | scp -P$hostPort -q root@$hostAddress:"\"$sourceFile\"" "$targetDir" || \ 1433 | panic $? "Failed to copy file $sourceFile from device $hostAddress to directory $targetDir" 1434 | } 1435 | 1436 | # === func (Action) === # 1437 | 1438 | function runFuncOnDevice() # args: function, hostAddress, hostPort 1439 | { 1440 | local func="$1" 1441 | local hostAddress="$2" 1442 | local hostPort="$3" 1443 | local cmd 1444 | 1445 | if [[ $hostAddress == "" ]]; then 1446 | 1447 | requireExportedVariable "iOSOpenDevDevice" 1448 | 1449 | hostAddress="$iOSOpenDevDevice" 1450 | 1451 | [[ $hostAddress != "" ]] || \ 1452 | panic 1 "Host address not provided and environment variable iOSOpenDevDevice is not set or is empty" 1453 | fi 1454 | 1455 | if [[ $hostPort == "" ]]; then 1456 | 1457 | hostPort="$iOSOpenDevPort" 1458 | 1459 | [[ $hostPort != "" ]] || \ 1460 | hostPort=22 1461 | 1462 | fi 1463 | 1464 | case "$func" in 1465 | reboot) 1466 | cmd="reboot" 1467 | ;; 1468 | respring) 1469 | cmd="killall SpringBoard" 1470 | ;; 1471 | *) 1472 | panic $? "Invalid function: $func" 1473 | ;; 1474 | esac 1475 | 1476 | ssh -p$hostPort root@$hostAddress $cmd || \ 1477 | panic $? "Failed to perform function $func on device $hostAddress" 1478 | } 1479 | 1480 | # === sudo === # 1481 | 1482 | function requireSudo() # args: ... 1483 | { 1484 | if [[ $EUID != 0 ]]; then 1485 | 1486 | removeTempData 1487 | 1488 | exec sudo "$0" "$@" || \ 1489 | panic $? "Failed to re-execute as root" 1490 | fi 1491 | } 1492 | 1493 | # === xcbp-logos === # 1494 | 1495 | function doesFileContain() # args: filePath, pattern 1496 | { 1497 | $setCmd 1498 | 1499 | local filePath="$1" 1500 | local pattern="$2" 1501 | local perlValue 1502 | local funcReturn 1503 | 1504 | perlValue=`perl -ne 'if (/'"$pattern"'/) { print "true"; exit; }' "$filePath"` || \ 1505 | panic $? "Failed to perl" 1506 | 1507 | if [[ $perlValue == "true" ]]; then 1508 | funcReturn="true" 1509 | else 1510 | funcReturn="false" 1511 | fi 1512 | 1513 | # return # 1514 | echo $funcReturn 1515 | } 1516 | 1517 | function xcodeBuildPhase_Logos() # no args 1518 | { 1519 | [[ "$ACTION" == "build" ]] || \ 1520 | panic 1 "For Xcode Build Phase use only" 1521 | 1522 | echo "Preparing to run Xcode Build Phase for Logos Processor..." 1523 | 1524 | # process environment variables 1525 | 1526 | local pbxProjectFilePath="$PROJECT_FILE_PATH/project.pbxproj" 1527 | local logosProcessor 1528 | local projectFileModified=false 1529 | local projectContainsXmFiles 1530 | local projectContainsXFiles 1531 | local lastKnownXmFileTypeNotObjCpp 1532 | local lastKnownXFileTypeNotObjC 1533 | local xmFileLangSpecNotObjCpp 1534 | local xFileLangSpecNotObjC 1535 | local projectXmFiles 1536 | local projectXFiles 1537 | local logosStdErr 1538 | local logosErr=0 1539 | 1540 | # verify use 1541 | 1542 | [[ -f "$pbxProjectFilePath" ]] || \ 1543 | panic 1 "Xcode project file not found: $pbxProjectFilePath" 1544 | 1545 | logosProcessor=`which logos.pl` || \ 1546 | panic $? "Failed to locate Logos Processor. Is Theos installed? If not, see http://iphonedevwiki.net/index.php/Theos/Getting_Started." 1547 | 1548 | # for *.xm project files, set known file-type and language specifications to Objective-C++ 1549 | 1550 | projectContainsXmFiles=`doesFileContain "$pbxProjectFilePath" '\/\* .+\.xm \*\/ *= *\{.*?isa *= *PBXFileReference\b'` 1551 | projectContainsXFiles=`doesFileContain "$pbxProjectFilePath" '\/\* .+\.x \*\/ *= *\{.*?isa *= *PBXFileReference\b'` 1552 | 1553 | if [[ $projectContainsXmFiles == "true" ]]; then 1554 | 1555 | lastKnownXmFileTypeNotObjCpp=`doesFileContain "$pbxProjectFilePath" '\/\* .+\.xm \*\/ *= *\{.*?isa *= *PBXFileReference\b[^\}]*?\blastKnownFileType *= *text\b'` 1556 | 1557 | if [[ $lastKnownXmFileTypeNotObjCpp == "true" ]]; then 1558 | echo "Modifying Xcode project file: setting *.xm file-types to Objective-C++..." 1559 | 1560 | perl -i -pe 's/^(.*\/\* .+\.xm \*\/ *= *{.*?isa *= *PBXFileReference\b[^}]*?\blastKnownFileType *= *)[^;]+(.*)$/\1sourcecode.cpp.objcpp\2/g' "$pbxProjectFilePath" || \ 1561 | panic $? "Failed to modify Xcode project file" 1562 | 1563 | projectFileModified=true 1564 | fi 1565 | 1566 | xmFileLangSpecNotObjCpp=`perl -ne 'if ($_ =~ /\/\* .+\.xm \*\/ *= *\{.*?isa *= *PBXFileReference\b/ && $_ !~ /\bxcLanguageSpecificationIdentifier *= *xcode\.lang\.objcpp\b/) { print "true"; exit; }' "$pbxProjectFilePath"` || \ 1567 | panic $? "Failed to execute perl on $pbxProjectFilePath" 1568 | 1569 | if [[ $xmFileLangSpecNotObjCpp == "true" ]]; then 1570 | echo "Modifying Xcode project file: setting *.xm language to Objective-C++..." 1571 | 1572 | perl -i -pe 'if ($_ =~ /\/\* .+\.xm \*\/ *= *\{.*?isa *= *PBXFileReference\b/ && $_ !~ /\bxcLanguageSpecificationIdentifier *= *xcode\.lang\.objcpp\b/) { s/^(.*\/\* .+\.xm \*\/ *= *{.*?isa *= *PBXFileReference\b[^}]*)(.*)$/\1xcLanguageSpecificationIdentifier = xcode.lang.objcpp; \2/g; }' "$pbxProjectFilePath" || \ 1573 | panic $? "Failed to modify Xcode project file" 1574 | 1575 | projectFileModified=true 1576 | fi 1577 | fi 1578 | 1579 | if [[ $projectContainsXFiles == "true" ]]; then 1580 | 1581 | lastKnownXFileTypeNotObjCpp=`doesFileContain "$pbxProjectFilePath" '\/\* .+\.x \*\/ *= *\{.*?isa *= *PBXFileReference\b[^\}]*?\blastKnownFileType *= *text\b'` 1582 | 1583 | if [[ $lastKnownXFileTypeNotObjC == "true" ]]; then 1584 | echo "Modifying Xcode project file: setting *.x file-types to Objective-C..." 1585 | 1586 | perl -i -pe 's/^(.*\/\* .+\.x \*\/ *= *{.*?isa *= *PBXFileReference\b[^}]*?\blastKnownFileType *= *)[^;]+(.*)$/\1sourcecode.c.objc\2/g' "$pbxProjectFilePath" || \ 1587 | panic $? "Failed to modify Xcode project file" 1588 | 1589 | projectFileModified=true 1590 | fi 1591 | 1592 | xFileLangSpecNotObjC=`perl -ne 'if ($_ =~ /\/\* .+\.x \*\/ *= *\{.*?isa *= *PBXFileReference\b/ && $_ !~ /\bxcLanguageSpecificationIdentifier *= *xcode\.lang\.objc\b/) { print "true"; exit; }' "$pbxProjectFilePath"` || \ 1593 | panic $? "Failed to execute perl on $pbxProjectFilePath" 1594 | 1595 | if [[ $xFileLangSpecNotObjC == "true" ]]; then 1596 | echo "Modifying Xcode project file: setting *.x language to Objective-C..." 1597 | 1598 | perl -i -pe 'if ($_ =~ /\/\* .+\.x \*\/ *= *\{.*?isa *= *PBXFileReference\b/ && $_ !~ /\bxcLanguageSpecificationIdentifier *= *xcode\.lang\.objc\b/) { s/^(.*\/\* .+\.x \*\/ *= *{.*?isa *= *PBXFileReference\b[^}]*)(.*)$/\1xcLanguageSpecificationIdentifier = xcode.lang.objc; \2/g; }' "$pbxProjectFilePath" || \ 1599 | panic $? "Failed to modify Xcode project file" 1600 | 1601 | projectFileModified=true 1602 | fi 1603 | fi 1604 | 1605 | if [[ $projectFileModified == "true" ]]; then 1606 | echo "DON'T WORRY, EVERYTHING IS OK!" 1607 | echo "The Xcode project file was modified to provide better *.xm & *.x file support." 1608 | echo "To dismiss this build error, just perform the build again." 1609 | panic 1 1610 | fi 1611 | 1612 | # for each *.xm project file, use Logos Processor to generate *.mm file 1613 | 1614 | projectXmFiles=($(perl -ne 'if ($_ =~ /\/\* (.+\.xm) \*\/ *= *{.*?isa *= *PBXFileReference\b/) { print "$1\n"; }' "$pbxProjectFilePath")) 1615 | projectXFiles=($(perl -ne 'if ($_ =~ /\/\* (.+\.x) \*\/ *= *{.*?isa *= *PBXFileReference\b/) { print "$1\n"; }' "$pbxProjectFilePath")) 1616 | 1617 | for f in "${projectXmFiles[@]}"; do 1618 | echo "Logos Processor: $f -> ${f%.*}.mm..." 1619 | 1620 | logosStdErr=$(("$logosProcessor" "$PROJECT_DIR/$TARGET_NAME/$f" > "$PROJECT_DIR/$TARGET_NAME/${f%.*}.mm") 2>&1) || \ 1621 | logosErr=$? 1622 | 1623 | if [[ $logosErr != 0 ]]; then 1624 | echo "Failed Logos Processor" >&2 1625 | echo "Logos Processor outputted:" >&2 1626 | echo "$logosStdErr" >&2 1627 | exit $logosErr 1628 | fi 1629 | 1630 | done 1631 | 1632 | for f in "${projectXFiles[@]}"; do 1633 | echo "Logos Processor: $f -> ${f%.*}.m..." 1634 | 1635 | logosStdErr=$(("$logosProcessor" "$PROJECT_DIR/$TARGET_NAME/$f" > "$PROJECT_DIR/$TARGET_NAME/${f%.*}.m") 2>&1) || \ 1636 | panic $? "Failed Logos Processor" 1637 | 1638 | [[ $logosStdErr == "" ]] || \ 1639 | panic 1 "Logos Processor outputted: $logosStdErr" 1640 | done 1641 | 1642 | echo "Note: If any *.xm or *.x file generated above by the Logos Processor (${projectXmFiles[@]}) is not being compiled below, then you must add it to the Xcode project to be compiled." 1643 | 1644 | # success # 1645 | echo "Xcode Build Phase for Logos Processor complete." 1646 | } 1647 | 1648 | # === xcbp (action) === # 1649 | 1650 | function xcodeBuildPhase() # no args 1651 | { 1652 | [[ "$ACTION" == "build" ]] || \ 1653 | panic 1 "For Xcode Build Phase use only" 1654 | 1655 | echo "Preparing to run Xcode Build Phase..." 1656 | 1657 | # process environment variables # 1658 | 1659 | local builtExecutable="$TARGET_BUILD_DIR/$EXECUTABLE_PATH" 1660 | local packageDirectory="$PROJECT_DIR/$TARGET_NAME/Package" 1661 | local packageInstallPath="$packageDirectory$INSTALL_PATH" 1662 | local packageVersionPListPath="$PROJECT_DIR/$TARGET_NAME/PackageVersion.plist" 1663 | local allPackagesDir="$PROJECT_DIR/Packages" 1664 | local builtProductsDir="$BUILT_PRODUCTS_DIR" 1665 | local latestBuildSymlink="$PROJECT_DIR/LatestBuild" 1666 | local stripBin 1667 | local stripOption 1668 | local versionPListPath 1669 | local packageFileName 1670 | 1671 | local packageInstallSource 1672 | if [[ $SHALLOW_BUNDLE != "YES" ]]; then 1673 | packageInstallSource="$TARGET_BUILD_DIR/$EXECUTABLE_PATH" 1674 | else 1675 | packageInstallSource="$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH" 1676 | fi 1677 | 1678 | # if build setting iOSOpenDevDevice is empty, get it from user's Bash profile 1679 | [[ $iOSOpenDevDevice != "" ]] || \ 1680 | iOSOpenDevDevice=`getBashProfileEnvVarValue "iOSOpenDevDevice"` 1681 | 1682 | # if build setting iOSOpenDevPort is empty, try to get it from user's profile 1683 | # or, if that fails, use the default value of 22 1684 | 1685 | [[ $iOSOpenDevPort != "" ]] || \ 1686 | iOSOpenDevPort=`getBashProfileEnvVarValue "iOSOpenDevPort"` 1687 | 1688 | [[ $iOSOpenDevPort != "" ]] || \ 1689 | iOSOpenDevPort=22 1690 | 1691 | 1692 | # verify requirements # 1693 | requireFile "$builtExecutable" false 1694 | requireDir "$packageDirectory" 1695 | 1696 | # create latest build symlink # 1697 | createSymlink "$builtProductsDir" "$latestBuildSymlink" 1698 | 1699 | # if doing Archive, strip executable ... 1700 | # note: even though Xcode strips the executable AFTER this script runs, the 1701 | # executable is stripped now since it will be included in the package 1702 | # that will be built by this script below 1703 | if [[ "$CONFIGURATION" == "Release" && "$VALIDATE_PRODUCT" == "YES" && "$DEPLOYMENT_POSTPROCESSING" == "YES" ]]; then 1704 | if [[ "$STRIP_INSTALLED_PRODUCT" == "YES" ]]; then 1705 | 1706 | stripBin=`xcodebuild -sdk iphoneos -find strip` || \ 1707 | panic $? "Failed to get strip path" 1708 | 1709 | [[ "$STRIP_STYLE" != "debugging" ]] || stripOption="-S" 1710 | 1711 | echo "Stripping $builtExecutable..." 1712 | 1713 | "$stripBin" $stripOption "$builtExecutable" || \ 1714 | panic $? "Failed to strip $builtExecutable" 1715 | fi 1716 | fi 1717 | 1718 | # if doing any, ... # 1719 | 1720 | if [[ "$MACH_O_TYPE" == "staticlib" && "$CODE_SIGN_IDENTITY" == "" ]]; then 1721 | echo "Skipping signing (since ldid would be used and it fails on static libraries)" 1722 | elif [[ "$PLATFORM_NAME" != "iphoneos" ]]; then 1723 | echo "Skipping signing (since platform is not iphoneos)" 1724 | else 1725 | signCode "$builtExecutable" "$CODE_SIGN_IDENTITY" 1726 | fi 1727 | 1728 | changeMode "$INSTALL_MODE_FLAG" "$builtExecutable" 1729 | 1730 | # if doing any and iOSOpenDevCopyOnBuild is YES, then copy executable to device ... 1731 | if [[ "$iOSOpenDevCopyOnBuild" == "YES" ]]; then 1732 | 1733 | if [[ "$iOSOpenDevDevice" != "" ]]; then 1734 | copyFileToDevice "$builtExecutable" "/var/root/iOSOpenDevBuilds/$PROJECT_NAME" "$iOSOpenDevDevice" "$iOSOpenDevPort" 1735 | else 1736 | # build setting iOSOpenDevDevice is empty # 1737 | panic 1 "Unable to copy executable to device since build setting iOSOpenDevDevice is not set or is empty and it is not exported in your Bash personal initialization file" 1738 | fi 1739 | 1740 | fi 1741 | 1742 | # if doing Archive, For Archiving or For Profiling, build package... 1743 | if [[ "$CONFIGURATION" == "Release" && "$VALIDATE_PRODUCT" == "YES" ]] || [[ "$iOSOpenDevInstallOnAnyBuild" == "YES" ]] || [[ "$iOSOpenDevBuildPackageOnAnyBuild" == "YES" ]]; then 1744 | 1745 | # if doing Archive, do... 1746 | #if [[ "$DEPLOYMENT_POSTPROCESSING" == "YES" ]]; then 1747 | #fi 1748 | 1749 | # prepare to build package # 1750 | 1751 | echo "Copying $packageInstallSource to package directory at $packageInstallPath..." 1752 | 1753 | requireDir "$packageInstallPath" true 1754 | 1755 | copyFile "$packageInstallSource" "$packageInstallPath" 1756 | 1757 | # build package # 1758 | 1759 | [[ "$iOSOpenDevUsePackageVersionPList" != "YES" ]] || \ 1760 | versionPListPath="$packageVersionPListPath" 1761 | 1762 | buildPackage "$packageDirectory" "$allPackagesDir" "$versionPListPath" true 1763 | 1764 | # if more than just $iOSOpenDevBuildPackageOnAnyBuild == "YES" ... 1765 | if [[ "$CONFIGURATION" == "Release" && "$VALIDATE_PRODUCT" == "YES" ]] || [[ "$iOSOpenDevInstallOnAnyBuild" == "YES" ]]; then 1766 | 1767 | # if doing For Archiving or For Profiling, see about installing package on device... 1768 | if [[ "$DEPLOYMENT_POSTPROCESSING" == "NO" || "$iOSOpenDevInstallOnAnyBuild" == "YES" ]]; then 1769 | 1770 | # if build setting iOSOpenDevInstallOnProfiling is enabled, installation of package is enabled... 1771 | if [[ "$iOSOpenDevInstallOnProfiling" == "YES" || "$iOSOpenDevInstallOnAnyBuild" == "YES" ]]; then 1772 | 1773 | # if iOSOpenDevDevice has a value, install package on device... 1774 | if [[ "$iOSOpenDevDevice" != "" ]]; then 1775 | 1776 | # get package file name # 1777 | packageFileName="`getPackageFileNameUsingControlFile \"$packageDirectory/DEBIAN/control\"`.deb" 1778 | 1779 | # install package on device # 1780 | managePackageOnDevice "install" "$allPackagesDir/$packageFileName" "$iOSOpenDevDevice" "$iOSOpenDevPort" 1781 | 1782 | # respring? # 1783 | if [[ "$iOSOpenDevRespringOnInstall" == "YES" ]]; then 1784 | echo "Respringing device..." 1785 | runFuncOnDevice "respring" "$iOSOpenDevDevice" "$iOSOpenDevPort" 1786 | fi 1787 | else 1788 | # build setting iOSOpenDevDevice is empty # 1789 | panic 1 "Unable to install package on device since build setting iOSOpenDevDevice is not set or is empty and it is not exported in your Bash personal initialization file" 1790 | fi 1791 | else 1792 | # build setting iOSOpenDevInstallOnProfiling is disabled # 1793 | echo "Installation of package on device is disabled. To enable, set build setting iOSOpenDevInstallOnProfiling to YES." 1794 | fi 1795 | fi 1796 | fi 1797 | fi 1798 | 1799 | # success # 1800 | echo "Xcode Build Phase complete." 1801 | } 1802 | 1803 | # === usage === # 1804 | 1805 | function showUsageAndExit() # args: showEverything 1806 | { 1807 | local showEverything="$1" 1808 | local n 1809 | 1810 | echo "$scriptName (v$scriptVer) -- iOSOpenDev Command-line Tool" 1811 | echo "Usages:" 1812 | 1813 | for n in "${ActionNames[@]}"; do 1814 | eval echo "\" $scriptName \${Action_$n[$ActionProperty_ShortArg]} \${Action_$n[$ActionProperty_ShortUsage]}\"" 1815 | done 1816 | 1817 | if [[ $showEverything == "true" ]]; then 1818 | echo 1819 | echo "Actions:" 1820 | 1821 | for n in "${ActionNames[@]}"; do 1822 | eval echo "\" \${Action_$n[$ActionProperty_ShortArg]} \${Action_$n[$ActionProperty_ShortUsage]}\"" 1823 | eval echo "\"\${Action_$n[$ActionProperty_LongUsage]}\"" 1824 | echo 1825 | done 1826 | fi 1827 | 1828 | panic 1 1829 | } 1830 | 1831 | function showSingleUsageAndExit() 1832 | { 1833 | panic 1 "Usage: $scriptName ${activeActionArg[$ActionProperty_ShortArg]} ${activeActionArg[$ActionProperty_ShortUsage]} 1834 | 1835 | ${activeActionArg[$ActionProperty_LongUsage]} 1836 | " 1837 | 1838 | } 1839 | 1840 | # === start script === # 1841 | 1842 | [[ $1 != "" ]] || showUsageAndExit false 1843 | [[ $1 != "--help" ]] || showUsageAndExit true 1844 | 1845 | # determine active "action" (which is first argument) # 1846 | 1847 | for n in "${ActionNames[@]}"; do 1848 | foundArg=false 1849 | eval [[ "\$1" != "\${Action_$n[$ActionProperty_ShortArg]}" ]] || \ 1850 | foundArg=true 1851 | 1852 | if [[ $foundArg == true ]]; then 1853 | eval activeActionArg=("\"\${Action_$n[@]}\"") 1854 | break; 1855 | fi 1856 | done 1857 | 1858 | [[ $foundArg == true ]] || \ 1859 | panic 1 "Invalid argument: $1" 1860 | 1861 | [[ "$#" != 1 || ${activeActionArg[$ActionProperty_MinArgs]} == 0 ]] || \ 1862 | showSingleUsageAndExit 1863 | 1864 | # process action's options # 1865 | 1866 | shift 1 1867 | 1868 | while getopts ":${activeActionArg[$ActionProperty_Options]}" opt; do 1869 | case "$opt" in 1870 | \?) 1871 | panic 1 "Invalid option: -$OPTARG" 1872 | ;; 1873 | *) 1874 | [[ $opt != ":" ]] || \ 1875 | panic 1 "Option missing value: -$OPTARG" 1876 | 1877 | eval Opt_$opt="\"${OPTARG-true}\"" 1878 | ;; 1879 | esac 1880 | done 1881 | 1882 | # correct amount of arguments left? # 1883 | 1884 | shift $(($OPTIND - 1)) # shift out options 1885 | 1886 | (( "$#" >= ${activeActionArg[$ActionProperty_MinArgs]} && "$#" <= ${activeActionArg[$ActionProperty_MaxArgs]} )) || \ 1887 | showSingleUsageAndExit 1888 | 1889 | # perform action's function # 1890 | 1891 | [[ ${activeActionArg[$ActionProperty_RequireSudo]} == false ]] || \ 1892 | requireSudo "${originalArguments[@]}" 1893 | 1894 | case "${activeActionArg[$ActionProperty_ShortArg]}" in 1895 | ${Action_SignCode[$ActionProperty_ShortArg]}) 1896 | "${activeActionArg[$ActionProperty_Function]}" "$@" "$Opt_i" 1897 | ;; 1898 | ${Action_BuildPackage[$ActionProperty_ShortArg]}) 1899 | "${activeActionArg[$ActionProperty_Function]}" "$@" "$Opt_p" "$Opt_z" 1900 | ;; 1901 | ${Action_InstallPackage[$ActionProperty_ShortArg]}) 1902 | "${activeActionArg[$ActionProperty_Function]}" "install" "$@" "$Opt_h" "$Opt_p" 1903 | ;; 1904 | ${Action_RemovePackage[$ActionProperty_ShortArg]}) 1905 | "${activeActionArg[$ActionProperty_Function]}" "remove" "$@" "$Opt_h" "$Opt_p" 1906 | ;; 1907 | ${Action_PurgePackage[$ActionProperty_ShortArg]}) 1908 | "${activeActionArg[$ActionProperty_Function]}" "purge" "$@" "$Opt_h" "$Opt_p" 1909 | ;; 1910 | ${Action_DumpSDKHeaders[$ActionProperty_ShortArg]}) 1911 | "${activeActionArg[$ActionProperty_Function]}" "$@" "$Opt_z" "$Opt_i" 1912 | ;; 1913 | ${Action_CopyHeadersToSDK[$ActionProperty_ShortArg]}) 1914 | "${activeActionArg[$ActionProperty_Function]}" "$@" "$Opt_t" 1915 | ;; 1916 | ${Action_DumpAndCopyHeaders[$ActionProperty_ShortArg]}) 1917 | "${activeActionArg[$ActionProperty_Function]}" "$@" "$Opt_t" "$Opt_z" "$Opt_i" 1918 | ;; 1919 | ${Action_RemoveCopiedHeaders[$ActionProperty_ShortArg]}) 1920 | "${activeActionArg[$ActionProperty_Function]}" "$@" 1921 | ;; 1922 | ${Action_AddSshKeyToDevice[$ActionProperty_ShortArg]}) 1923 | "${activeActionArg[$ActionProperty_Function]}" "$Opt_h" "$Opt_r" "$Opt_p" 1924 | ;; 1925 | ${Action_DumpAllHeaders[$ActionProperty_ShortArg]}) 1926 | "${activeActionArg[$ActionProperty_Function]}" "$Opt_z" "$Opt_i" 1927 | ;; 1928 | ${Action_RunCmdOnDevice[$ActionProperty_ShortArg]}) 1929 | "${activeActionArg[$ActionProperty_Function]}" "$Opt_h" "$Opt_p" "$@" 1930 | ;; 1931 | ${Action_RunFuncOnDevice[$ActionProperty_ShortArg]}) 1932 | "${activeActionArg[$ActionProperty_Function]}" "$@" "$Opt_h" "$Opt_p" 1933 | ;; 1934 | ${Action_XcodeBuildPhase[$ActionProperty_ShortArg]}) 1935 | "${activeActionArg[$ActionProperty_Function]}" 1936 | ;; 1937 | ${Action_SshToDevice[$ActionProperty_ShortArg]}) 1938 | "${activeActionArg[$ActionProperty_Function]}" "$Opt_h" "$Opt_p" 1939 | ;; 1940 | ${Action_UpdateIncludeAndLib[$ActionProperty_ShortArg]}) 1941 | "${activeActionArg[$ActionProperty_Function]}" "$Opt_h" "$Opt_p" 1942 | ;; 1943 | ${Action_XcodeBuildPhaseLogos[$ActionProperty_ShortArg]}) 1944 | "${activeActionArg[$ActionProperty_Function]}" 1945 | ;; 1946 | esac 1947 | 1948 | # finished # 1949 | exit 0 1950 | -------------------------------------------------------------------------------- /bin/ldid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kokoabim/iOSOpenDev/020e76695ec6efecf941a100b147a50a6b9e6495/bin/ldid -------------------------------------------------------------------------------- /include/ActionMenu/ActionMenu.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | typedef enum { 4 | AMMenuItemStyleDefault = 0, 5 | // Default display style (what the user has selected) 6 | AMMenuItemStyleText = 1, 7 | // Always display text 8 | AMMenuItemStyleImage = 2, 9 | // Display image where available, otherwise display text 10 | } AMMenuItemStyle; 11 | 12 | typedef enum { 13 | AMActionMenuBehaviorDefault = 0, 14 | // Default additional behaviors provided by Action Menu 15 | AMActionMenuBehaviorDisableMenu = (1 << 0), 16 | // Disable the popup menu that Action Menu has added 17 | } AMActionMenuBehaviors; 18 | 19 | 20 | #define kAMMenuItemPrioritySelect 100 21 | #define kAMMenuItemPrioritySelectAll 200 22 | #define kAMMenuItemPriorityCut 300 23 | #define kAMMenuItemPriorityCopy 400 24 | #define kAMMenuItemPriorityPaste 500 25 | #define kAMMenuItemPriorityDelete 600 26 | #define kAMMenuItemPriorityCorrect 900 27 | #define kAMMenuItemPriorityDefault 1000 28 | 29 | #define kAMMenuItemPriorityCopyAll 450 30 | #define kAMMenuItemPriorityHistory 525 31 | #define kAMMenuItemPriorityFavorites 550 32 | #define kAMMenuItemPriorityDial 925 33 | #define kAMMenuItemPriorityLookup 950 34 | #define kAMMenuItemPriorityFind 975 35 | #define kAMMenuItemPriorityTweet 1100 36 | #define kAMMenuItemPriorityScroll 1200 37 | 38 | #define kAMMenuItemPriorityBuiltins 510 39 | 40 | @protocol AMMenuItem 41 | @property (nonatomic, readonly, assign) SEL action; 42 | // Selector that will be sent to the target when menu item is pressed 43 | @property (nonatomic, readonly, assign) SEL canPerform; 44 | // Selector that will be sent to the target to query whether menu item is valid 45 | @property (nonatomic, readwrite, copy) NSString *title; 46 | // Localized title of the menu item 47 | @property (nonatomic, readwrite, assign) UIImage *image; 48 | // Image that will be used to display the menu item 49 | @property (nonatomic, readwrite, assign) AMMenuItemStyle style; 50 | // Style of the menu item 51 | @property (nonatomic, readwrite, assign) NSInteger priority; 52 | // Specify the priority of the item 53 | @end 54 | 55 | @interface UIMenuController (ActionMenu) 56 | // Plugin Registration functions 57 | - (id)registerAction:(SEL)action title:(NSString *)title canPerform:(SEL)canPerform; 58 | - (id)registerAction:(SEL)action title:(NSString *)title canPerform:(SEL)canPerform forPlugin:(NSString *)pluginName; 59 | // action will be sent to the target when the menu item has been pressed 60 | // canPerform will be sent to the target when the menu is about to be shown and we need to know if the menu item is valid 61 | // title is the localized title of the menu item 62 | // pluginName is the unlocalized title of the plugin 63 | @end 64 | 65 | @interface UIResponder (ActionMenu) 66 | - (NSString *)textualRepresentation; 67 | // Called by plugins to get the text of the object; implement manually for custom views 68 | - (NSString *)selectedTextualRepresentation; 69 | // Returns only the selected text; if unimplemented, will call and return textualRepresentation 70 | - (AMActionMenuBehaviors)actionMenuBehaviors; 71 | // Control which additional ActionMenu behaviors are valid on this target 72 | - (BOOL)always; 73 | // Always returns YES (used by actions that are always valid) 74 | @end 75 | 76 | @interface UIAlertView (ActionMenu) 77 | - (void)showAboveExistingAlert; 78 | @end 79 | 80 | /* 81 | Notes: 82 | Plugins will be loaded lazily from /Libary/ActionMenu/Plugins when the menu is first shown; this is usually much later than one might expect. 83 | If the user disables a plugin after it has been loaded, the plugin will still be resident in memory, but its items will no longer show. 84 | If the user enables a plugin, it will be loaded the next time the menu becomes visible. 85 | 86 | Plugins may be either .dylibs or .bundles 87 | Dylib plugins get a ON/OFF switch in the preferences pane. 88 | Bundle plugins get their own subpane to do what they please with. 89 | */ -------------------------------------------------------------------------------- /include/AssistantExtensions/SiriObjects.h: -------------------------------------------------------------------------------- 1 | // 2 | // SiriObjects.h 3 | // AssistantExtensions 4 | // Version 1.0.2-1 5 | // 6 | // Created by K3A. 7 | // Copyright (c) 2012 K3A.me. All rights reserved. 8 | // 9 | #pragma once 10 | #include 11 | 12 | #ifdef SC_PRIVATE 13 | # import "SiriObjects_private.h" 14 | #endif 15 | 16 | /// A structure representing location data (user position) 17 | typedef struct 18 | { 19 | /// You should check this value. 20 | /// False here means that location data are not available or your extensions is not permitted to access them. 21 | bool valid; 22 | float altitude; 23 | float direction; 24 | float longitude; 25 | int age; 26 | float speed; 27 | float latitude; 28 | float verticalAccuracy; 29 | float horizontalAccuracy; 30 | unsigned long timestamp; 31 | } SOLocationData; 32 | 33 | /// A protocol specifying methods of pattern match. 34 | @protocol AEPatternMatch 35 | @required 36 | /// The Siri language selected at the time of input recognition was received 37 | -(NSString*)language; 38 | /// The complete input phrase 39 | -(NSString*)text; 40 | /// Tokens of the input phrase 41 | -(NSArray*)tokens; 42 | /// A set of tokens of the input phrase 43 | -(NSSet*)tokenSet; 44 | /// User-supplied data 45 | -(id)userInfo; 46 | 47 | /// Returns a value of named element 48 | -(NSString*)namedElement:(NSString*)name; 49 | /// Returns a value of idexed element 50 | -(NSString*)elementAtIndex:(unsigned)idx; 51 | -(NSString*)firstElement; 52 | -(NSString*)secondElement; 53 | -(NSString*)thirdElement; 54 | -(NSString*)fourthElement; 55 | @end 56 | 57 | 58 | /// Ordinary assistant object dictionary (NSMutableDictionary) containing class name, group and properties. 59 | /// The dictionary is by default not deep-mutable, so you can change values for keys in this dictionary only. 60 | typedef NSMutableDictionary SOObject; 61 | /// Root assistant object (NSMutableDictionary). Like SOObject but also with aceId and refId in addition to the class, group and properties. 62 | typedef SOObject SOAceObject; 63 | 64 | @protocol SECommand; 65 | @protocol SESystem; 66 | 67 | 68 | /** Protocol specifying methods for handling one concrete request. 69 | An object of an class conforming to this protocol is passed to handleSpeech in SECommand classes. */ 70 | @protocol SEContext 71 | @required 72 | /** Creates a dictionary representing an ordinary assistant object (does not send it yet) 73 | \param className Name of the class 74 | \param group Name of the object group 75 | \param props Properties of the object 76 | */ 77 | -(SOObject*)createObjectDict:(NSString*)className group:(NSString*)group properties:(NSDictionary*)props; 78 | 79 | /** Creates a dictionary representing utterance view 80 | \param text A text to show and speak 81 | */ 82 | -(SOObject*)createAssistantUtteranceView:(NSString*)text; 83 | /** Creates a dictionary representing utterance view 84 | \param text A text to show 85 | \param speakableText A text to speak 86 | */ 87 | -(SOObject*)createAssistantUtteranceView:(NSString*)text speakableText:(NSString*)speakableText; 88 | /** Creates a dictionary representing utterance view 89 | \param text A text to show 90 | \param speakableText A text to speak 91 | \param dialogIdentifier Dialog identifier 92 | */ 93 | -(SOObject*)createAssistantUtteranceView:(NSString*)text speakableText:(NSString*)speakableText dialogIdentifier:(NSString*)dialogIdentifier; 94 | /** Creates a dictionary representing a snippet 95 | \param snippetClass Name of the snippet class 96 | \param props Dictionary of snippet properties 97 | */ 98 | -(SOObject*)createSnippet:(NSString*)snippetClass properties:(NSDictionary*)props; 99 | 100 | /** Sends a root assistant object to the client 101 | */ 102 | -(BOOL)sendAceObject:(NSString*)className group:(NSString*)group properties:(NSDictionary*)props; 103 | 104 | /** Sends "request completed" to the client 105 | */ 106 | -(BOOL)sendRequestCompleted; 107 | 108 | /** Sends AddViews ace command to the client 109 | \param views Array of views to send 110 | */ 111 | -(BOOL)sendAddViews:(NSArray*)views; 112 | 113 | /** Sends AddViews ace command to the client 114 | \param views Array of views to send 115 | \param dialogPhase Dialog phase, e.g. Reflection (will be replaced), Completion, Summary, Clarification, Error, Acknowledgement 116 | \param scrollToTop Should scroll to top 117 | \param temporary Temporary flag 118 | */ 119 | -(BOOL)sendAddViews:(NSArray*)views dialogPhase:(NSString*)dialogPhase scrollToTop:(BOOL)scrollToTop temporary:(BOOL)temporary; 120 | 121 | /** Create a snippet and send it immediately to the client 122 | \param snippetClass Name of the snippet class 123 | \param props Properties for the snippet class 124 | */ 125 | -(BOOL)sendAddViewsSnippet:(NSString*)snippetClass properties:(NSDictionary*)props; 126 | /** Create a snippet and send it immediately to the client 127 | \param snippetClass Name of the snippet class 128 | \param properties Properties for the snippet class 129 | \param dialogPhase Dialog phase, e.g. Reflection (will be replaced), Completion, Summary, Clarification, Error, Acknowledgement 130 | \param scrollToTop Should scroll to top 131 | \param temporary Temporary flag 132 | */ 133 | -(BOOL)sendAddViewsSnippet:(NSString*)snippetClass properties:(NSDictionary*)props dialogPhase:(NSString*)dialogPhase scrollToTop:(BOOL)scrollToTop temporary:(BOOL)temporary; 134 | 135 | /** Create utterance (text) and send it immediately to the client 136 | \param text Text to send 137 | */ 138 | -(BOOL)sendAddViewsUtteranceView:(NSString*)text; 139 | /** Create utterance (text) and send it immediately to the client 140 | \param text Text to send 141 | \param speakableText Text to speak (different from what is displayed) 142 | */ 143 | -(BOOL)sendAddViewsUtteranceView:(NSString*)text speakableText:(NSString*)speakableText; 144 | /** Create utterance (text) and send it immediately to the client 145 | \param text Text to send 146 | \param speakableText Text to speak (different from what is displayed) 147 | \param dialogPhase Dialog phase, e.g. Reflection (will be replaced), Completion, Summary, Clarification, Error, Acknowledgement 148 | */ 149 | -(BOOL)sendAddViewsUtteranceView:(NSString*)text speakableText:(NSString*)speakableText dialogPhase:(NSString*)dialogPhase scrollToTop:(BOOL)scrollToTop temporary:(BOOL)temporary; 150 | /** Create utterance (text) and send it immediately to the client 151 | \param text Text to send 152 | \param speakableText Text to speak (different from what is displayed) 153 | \param dialogPhase Dialog phase, e.g. Reflection (will be replaced), Completion, Summary, Clarification, Error, Acknowledgement 154 | \param listen Whether to listen for user response just after speaking the text. If YES, next request will be sent to the same SECommand. 155 | \since 1.0.1 156 | */ 157 | -(BOOL)sendAddViewsUtteranceView:(NSString*)text speakableText:(NSString*)speakableText dialogPhase:(NSString*)dialogPhase scrollToTop:(BOOL)scrollToTop temporary:(BOOL)temporary listenAfterSpeaking:(BOOL)listen; //SINCE 1.0.1 158 | 159 | /** Returns the most recent location data. 160 | \param show If TRUE, may show "Getting your current location..." reflection if location is not yet cached. Default TRUE. 161 | \since 1.0.2 162 | */ 163 | -(SOLocationData)getLocationDataShowReflection:(BOOL)show; //SINCE 1.0.2 164 | 165 | /** Sends the object to the client (assistant). 166 | Normally should be used only inside clientToServerObject/serverToClientObject methods. 167 | \param obj The object to send 168 | \since 1.0.2 169 | */ 170 | -(BOOL)sendAceObjectToClient:(SOAceObject*)obj; //SINCE 1.0.2 171 | /** Sends the object to the server (remote side). 172 | Normally should be used only inside clientToServerObject/serverToClientObject methods. 173 | \param obj The object to send 174 | \since 1.0.2 175 | */ 176 | -(BOOL)sendAceObjectToServer:(SOAceObject*)obj; //SINCE 1.0.2 177 | /** Blocks the rest of communication for the request represented by this context (both ways). 178 | This means that the extension will handle everything to serve the rest of the request. 179 | Normally should be used only inside clientToServerObject/serverToClientObject methods. 180 | \param obj The object to send 181 | \since 1.0.2 182 | */ 183 | -(void)blockRestOfRequest; //SINCE 1.0.2 184 | 185 | /** Request exclusive mode which will cause to send all future requests to commands class from which this method was called. Exclusive mode can be ended by calling endExclusiveMode or dismissing the assistant. 186 | \since 1.0.2 187 | */ 188 | -(void)beginExclusiveMode; 189 | 190 | /** Ends the exclusive mode. 191 | \since 1.0.2 192 | */ 193 | -(void)endExclusiveMode; 194 | 195 | /** Hides assistant. This is needed for openURL with "xxx://" schemes, while "xxx:" schems doesn't need this. */ 196 | -(void)dismissAssistant;//SINCE 1.0.2 197 | 198 | /** Returns a boolean indicating whether the current request has been completed (by calling sendRequestCompleted). */ 199 | -(BOOL)requestHasCompleted; 200 | 201 | /** Returns an object which handled the request or nil if the request has not been handled yet. */ 202 | -(NSObject*)object; 203 | 204 | /** Returns a string with refId of the current request. */ 205 | -(NSString*)refId; 206 | @end 207 | // --- end of SEContext --- 208 | 209 | 210 | /** Protocol specifying methods of an extension class representing snippet. 211 | Instances of these classes will be created for every snippet creation request. 212 | A class representing snippet can derive from UIView or just represent some proxy class creating it's UIView on demand. 213 | Don't forget you really should prefix your class with some shortcut, e.g. K3AAwesomeSnippet! 214 | */ 215 | @protocol SESnippet 216 | @optional 217 | /// Initializes a snippet by properties 218 | -(id)initWithProperties:(NSDictionary*)props; 219 | /// Initializes a snippet by properties and system 220 | -(id)initWithProperties:(NSDictionary*)props system:(id)system; 221 | /// Returns a view representing snippet, can be self if the conforming class is already UIView 222 | -(id)view; 223 | @end 224 | 225 | 226 | 227 | 228 | /** Protocol specifying methods for manipulation with AssistantExtension core, an object conforming to this protocol is is passed via initWithSystem to NSPrincipal class of the extension. 229 | */ 230 | @protocol SESystem 231 | @required 232 | /// Register a command class 233 | -(BOOL)registerCommand:(Class)cls; 234 | /// Register a snippet class 235 | -(BOOL)registerSnippet:(Class)cls; 236 | 237 | /** Filter classes which can be sent to clientToServerObject. If this method is not called, all classes will be sent so that the extension can handle every packet of the communication. It's recommended to use this method if you are modifying only one or few classes. 238 | \param allowedClasses An array of NSString* objects representing class names of objects. 239 | \since 1.0.2 240 | */ 241 | -(BOOL)setClientToServerFilter:(NSArray*)allowedClasses; //SINCE 1.0.2 242 | /** Filter classes which can be sent to serverToClientObject. If this method is not called, all classes will be sent so that the extension can handle every packet of the communication. It's recommended to use this method if you are modifying only one or few classes. 243 | \param allowedClasses An array of NSString* objects representing class names of objects. 244 | \since 1.0.2 245 | */ 246 | -(BOOL)setServerToClientFilter:(NSArray*)allowedClasses; //SINCE 1.0.2 247 | 248 | /** Returns the localized version of the input string in currently selected Siri language. 249 | If language strings are not defined for that language, input string will be returned as is, or If language strings are defined for English, those will be used. 250 | \param text Text to translate. 251 | \since 1.0.2 252 | */ 253 | -(NSString*)localizedString:(NSString*)text; //SINCE 1.0.2 254 | /** Returns the localized version of the input string in specified language. 255 | If language strings are not defined for that language, input string will be returned as is, or If language strings are defined for English, those will be used. 256 | \param text Text to translate. 257 | \param lang Language code. 258 | \since 1.0.2 259 | */ 260 | -(NSString*)localizedString:(NSString*)text inLanguage:(NSString*)lang; //SINCE 1.0.2 261 | 262 | /** Removes all previously registered patterns for the current extension. 263 | \since 1.0.2 264 | */ 265 | -(void)removeAllPatterns; 266 | 267 | /** Registers the AEX pattern. This method should be called only from patternsForLang:inSystem: method of commands class. 268 | \param text Text to translate. 269 | \param target An object to call selector on when the pattern is matched. 270 | \param sel A selector to use, default handlePatternMatch:context:. 271 | \param user User-supplied NSObject pointer with any data. Can be nil. 272 | \since 1.0.2 273 | */ 274 | -(BOOL)registerPattern:(NSString*)pattern target:(id)target selector:(SEL)sel userInfo:(id)user; //SINCE 1.0.2 275 | -(BOOL)registerPattern:(NSString*)pattern target:(id)target selector:(SEL)sel; //SINCE 1.0.2 276 | -(BOOL)registerPattern:(NSString*)pattern selector:(SEL)sel userInfo:(id)user; //SINCE 1.0.2 277 | -(BOOL)registerPattern:(NSString*)pattern selector:(SEL)sel; //SINCE 1.0.2 278 | -(BOOL)registerPattern:(NSString*)pattern userInfo:(id)user; //SINCE 1.0.2 279 | -(BOOL)registerPattern:(NSString*)pattern; //SINCE 1.0.2 280 | 281 | /** Registers the pattern defined in Patterns.plist file located in language directory of the current Siri language. If the Patterns.plist file is not found in the directory for current Siri language, AE will look for it in "en" directory. If not found there as well, it will look for it in the extension bundle (so that it can be used for every language). 282 | This method should be called only from patternsForLang:inSystem: method of commands class. 283 | \param name Name of the pattern in the Patterns.plist file. 284 | \param target An object to call selector on when the pattern is matched. 285 | \param sel A selector to use, default handlePatternMatch:context:. 286 | \param user User-supplied NSObject pointer with any data. Can be nil. 287 | \since 1.0.2 288 | */ 289 | -(BOOL)registerNamedPattern:(NSString*)name target:(id)target selector:(SEL)sel userInfo:(id)user; //SINCE 1.0.2 290 | -(BOOL)registerNamedPattern:(NSString*)name target:(id)target selector:(SEL)sel; //SINCE 1.0.2 291 | -(BOOL)registerNamedPattern:(NSString*)name selector:(SEL)sel userInfo:(id)user; //SINCE 1.0.2 292 | -(BOOL)registerNamedPattern:(NSString*)name selector:(SEL)sel; //SINCE 1.0.2 293 | -(BOOL)registerNamedPattern:(NSString*)name userInfo:(id)user; //SINCE 1.0.2 294 | -(BOOL)registerNamedPattern:(NSString*)name; //SINCE 1.0.2 295 | 296 | /** Registers all patterns defined in Patterns.plist file located in language directory of the current Siri language. If the Patterns.plist file is not found in the directory for current Siri language, AE will look for it in "en" directory. If not found there as well, it will look for it in the extension bundle (so that it can be used for every language). 297 | This method should be called only from patternsForLang:inSystem: method of commands class. 298 | \param target An object to call selector on when the pattern is matched. 299 | \param sel A selector to use, default handlePatternMatch:context:. 300 | \param user User-supplied NSObject pointer with any data. Can be nil. 301 | \since 1.0.2 302 | */ 303 | -(BOOL)registerAllNamedPatternsForTarget:(id)target selector:(SEL)sel userInfo:(id)user; 304 | -(BOOL)registerAllNamedPatternsForTarget:(id)target selector:(SEL)sel; 305 | -(BOOL)registerAllNamedPatternsForSelector:(SEL)sel userInfo:(id)user; 306 | -(BOOL)registerAllNamedPatternsForSelector:(SEL)sel; 307 | -(BOOL)registerAllNamedPatternsWithUserInfo:(id)user; 308 | -(BOOL)registerAllNamedPatterns; 309 | 310 | 311 | /// Returns the version string of AssistantExtensions 312 | -(NSString*)systemVersion; //SINCE 1.0.1 313 | @end 314 | 315 | 316 | 317 | 318 | /** Protocol specifying methods of an extension class handling commands. 319 | Classes conforming to this protocol are initialized just after loading bundle and will remain in memory. 320 | Don't forget you really should prefix your class with some shortcut, e.g. K3AAwesomeCommand! 321 | */ 322 | @protocol SECommand 323 | @optional 324 | /** Allows the extension to react to recognized text. 325 | \param text Recognized text 326 | \param tokens An ordered array of lowercase tokens representing recognized words 327 | \param tokenset An unordered set of tokens for fast search - recommended parameter for keyword-matching 328 | \param ctx Context representing the current request also allowing to send responses 329 | */ 330 | -(BOOL)handleSpeech:(NSString*)text tokens:(NSArray*)tokens tokenSet:(NSSet*)tokenset context:(id)ctx; 331 | 332 | /** Default method for handling pattern match. Can be different depending on which registration method was used. 333 | \param match Pattern match result, can be nil when called for the second time (e.g. after "listenAfterSpeaking" request). 334 | \param ctx Context representing the current request also allowing to send responses. 335 | */ 336 | -(BOOL)handlePatternMatch:(id)match context:(id)ctx; 337 | 338 | /** Allows the extension to register recognition patterns for the specified language. 339 | This is the preferred way for handling the recognized text. If implemented in the class, this method will be called after init/initWithSystem as well as after the user changes Siri language. You have to use supplied system pointer to register patterns. All previous patterns (registered for previous language) will be removed before calling this method. 340 | \param lang Language code of the currently selected Siri language. 341 | \param system The system pointer used for registering patterns. The same as the one passed by initWithSystem. 342 | */ 343 | -(void)patternsForLang:(NSString*)lang inSystem:(id)system; 344 | 345 | /** If this method is implemented, it will be called instead of "init" method. The supplied SESystem is the same as the one used for initializing SEExtension and remain the same for the life of your extension. 346 | \since 1.0.2 347 | */ 348 | -(id)initWithSystem:(id)system; 349 | 350 | /** Will be called after the user dismisses the assistant. 351 | Used mostly for cleaning up changes in system like removing additional view controllers. 352 | \since 1.0.2 353 | */ 354 | -(void)assistantDismissed; 355 | 356 | @end 357 | 358 | 359 | 360 | 361 | /// Protocol specifying methods of the extension's principal class 362 | @protocol SEExtension 363 | 364 | @required 365 | /// The first method which is called on your class, system is where you register commands and snippets 366 | -(id)initWithSystem:(id)system; 367 | 368 | @optional 369 | /** Optional method for intercepting and modifying client-to-servrer communication. 370 | You should not need this and you should not use it unless you are sure what you are doing. 371 | If your extension implements this method, it will be called each time a new object is about to be sent. 372 | The object is passed as a deep-mutable dictionary (=deep-mutable SOObject), so you can modify it's keys/values as well as keys/values of all sub-dictionaries and sub-arrays and return modified. 373 | If this method returns nil, the original object will not be sent. 374 | If you need to block the rest of communication for that particular request, call [ctx sendRequestCompleted]; 375 | If you need to handle only a few specific classes, set filter by calling setServerToClientFilter on SESystem (in initWithSystem). 376 | \param dict An object to be sent from the client to the server 377 | \param ctx A context (request) for which the communication is happening 378 | \since 1.0.2 379 | */ 380 | -(SOObject*)clientToServerObject:(SOObject*)dict context:(id)ctx; 381 | /** Optional method for intercepting and modifying client-to-servrer communication. 382 | You should not need this and you should not use it unless you are sure what you are doing. 383 | If your extension implements this method, it will be called each time a new object is about to be sent. 384 | The object is passed as a deep-mutable dictionary (=deep-mutable SOObject), so you can modify it's keys/values as well as keys/values of all sub-dictionaries and sub-arrays and return modified. 385 | If this method returns nil, the original object will not be sent. 386 | If you need to block the rest of communication for that particular request, call [ctx sendRequestCompleted]; 387 | If you need to handle only a few specific classes, set filter by calling setServerToClientFilter on SESystem (in initWithSystem). 388 | \param dict An object to be sent from the server to the client 389 | \param ctx A context (request) for which the communication is happening 390 | \since 1.0.2 391 | */ 392 | -(SOObject*)serverToClientObject:(SOObject*)dict context:(id)ctx; 393 | 394 | /** Extension author 395 | \deprecated Since 1.0.2, developers should use Info.plist of an extension for specifying those metadata. 396 | */ 397 | -(NSString*)author; 398 | /** Extension name 399 | \deprecated Since 1.0.2, developers should use Info.plist of an extension for specifying those metadata. 400 | */ 401 | -(NSString*)name; 402 | /** Extension description 403 | \deprecated Since 1.0.2, developers should use Info.plist of an extension for specifying those metadata. 404 | */ 405 | -(NSString*)description; 406 | /** Extension website URL 407 | \deprecated Since 1.0.2, developers should use Info.plist of an extension for specifying those metadata. 408 | */ 409 | -(NSString*)website; 410 | /** Minimal SiriExtensions version requirement 411 | \since 1.0.1 412 | \deprecated Since 1.0.2, developers should use Info.plist of an extension for specifying those metadata. 413 | */ 414 | -(NSString*)versionRequirement; 415 | 416 | @optional 417 | /** Will be called after the user dismisses the assistant. 418 | Used mostly for cleaning up changes in system like removing additional view controllers. 419 | \since 1.0.2 420 | */ 421 | -(void)assistantDismissed; 422 | 423 | /** Will be called after the assistant is activated. 424 | \since 1.0.2 425 | */ 426 | -(void)assistantActivatedWithContext:(id)ctx; 427 | 428 | @end 429 | // vim:ft=objc 430 | -------------------------------------------------------------------------------- /include/CaptainHook/CaptainHook.h: -------------------------------------------------------------------------------- 1 | // Possible defines: 2 | // CHDebug if defined, CHDebugLog is equivalent to CHLog; else, emits no code 3 | // CHUseSubstrate if defined, uses MSMessageHookEx to hook methods, otherwise uses internal hooking routines. Warning! super call closures are only available on ARM platforms for recent releases of MobileSubstrate 4 | // CHEnableProfiling if defined, enables calls to CHProfileScope() 5 | // CHAppName should be set to the name of the application (if not, defaults to "CaptainHook"); used for logging and profiling 6 | 7 | #import 8 | #import 9 | #import 10 | #import 11 | 12 | #ifndef CHAppName 13 | #define CHAppName "CaptainHook" 14 | #endif 15 | 16 | #ifdef __clang__ 17 | #if __has_feature(objc_arc) 18 | #define CHHasARC 19 | #endif 20 | #endif 21 | 22 | // Some Debugging/Logging Commands 23 | 24 | #define CHStringify_(x) #x 25 | #define CHStringify(x) CHStringify_(x) 26 | #define CHConcat_(a, b) a ## b 27 | #define CHConcat(a, b) CHConcat_(a, b) 28 | 29 | #define CHNothing() do { } while(0) 30 | 31 | #define CHLocationInSource [NSString stringWithFormat:@CHStringify(__LINE__) " in %s", __FUNCTION__] 32 | 33 | #define CHLog(args...) NSLog(@CHAppName ": %@", [NSString stringWithFormat:args]) 34 | #define CHLogSource(args...) NSLog(@CHAppName " @ " CHStringify(__LINE__) " in %s: %@", __FUNCTION__, [NSString stringWithFormat:args]) 35 | 36 | #ifdef CHDebug 37 | #define CHDebugLog(args...) CHLog(args) 38 | #define CHDebugLogSource(args...) CHLogSource(args) 39 | #else 40 | #define CHDebugLog(args...) CHNothing() 41 | #define CHDebugLogSource(args...) CHNothing() 42 | #endif 43 | 44 | // Constructor 45 | #define CHConstructor static __attribute__((constructor)) void CHConcat(CHConstructor, __LINE__)() 46 | #define CHInline inline __attribute__((always_inline)) 47 | 48 | // Cached Class Declaration (allows hooking methods, and fast lookup of classes) 49 | struct CHClassDeclaration_ { 50 | Class class_; 51 | Class metaClass_; 52 | Class superClass_; 53 | }; 54 | typedef struct CHClassDeclaration_ CHClassDeclaration_; 55 | #define CHDeclareClass(name) \ 56 | @class name; \ 57 | static CHClassDeclaration_ name ## $; 58 | 59 | // Loading Cached Classes (use CHLoadClass when class is linkable, CHLoadLateClass when it isn't) 60 | static inline Class CHLoadClass_(CHClassDeclaration_ *declaration, Class value) 61 | { 62 | declaration->class_ = value; 63 | declaration->metaClass_ = object_getClass(value); 64 | declaration->superClass_ = class_getSuperclass(value); 65 | return value; 66 | } 67 | #define CHLoadLateClass(name) CHLoadClass_(&name ## $, objc_getClass(#name)) 68 | #define CHLoadClass(name) CHLoadClass_(&name ## $, [name class]) 69 | 70 | // Quick Lookup of cached classes, and common methods on them 71 | #define CHClass(name) name ## $.class_ 72 | #define CHMetaClass(name) name ## $.metaClass_ 73 | #define CHSuperClass(name) name ## $.superClass_ 74 | #define CHAlloc(name) ((name *)[CHClass(name) alloc]) 75 | #define CHSharedInstance(name) ((name *)[CHClass(name) sharedInstance]) 76 | #define CHIsClass(obj, name) [obj isKindOfClass:CHClass(name)] 77 | #define CHRespondsTo(obj, sel) [obj respondsToSelector:@selector(sel)] 78 | 79 | // Replacement Method Definition 80 | #define CHDeclareSig0_(return_type) \ 81 | const char *return_ = @encode(return_type); \ 82 | size_t return_len = __builtin_strlen(return_); \ 83 | char sig[return_len+2+1]; \ 84 | __builtin_memcpy(sig, return_, return_len); \ 85 | sig[return_len] = _C_ID; \ 86 | sig[return_len+1] = _C_SEL; \ 87 | sig[return_len+2] = '\0'; 88 | #define CHDeclareSig1_(return_type, type1) \ 89 | const char *return_ = @encode(return_type); \ 90 | size_t return_len = __builtin_strlen(return_); \ 91 | const char *type1_ = @encode(type1); \ 92 | size_t type1_len = __builtin_strlen(type1_); \ 93 | char sig[return_len+2+type1_len+1]; \ 94 | __builtin_memcpy(sig, return_, return_len); \ 95 | sig[return_len] = _C_ID; \ 96 | sig[return_len+1] = _C_SEL; \ 97 | __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \ 98 | sig[return_len+type1_len+2] = '\0'; 99 | #define CHDeclareSig2_(return_type, type1, type2) \ 100 | const char *return_ = @encode(return_type); \ 101 | size_t return_len = __builtin_strlen(return_); \ 102 | const char *type1_ = @encode(type1); \ 103 | size_t type1_len = __builtin_strlen(type1_); \ 104 | const char *type2_ = @encode(type2); \ 105 | size_t type2_len = __builtin_strlen(type2_); \ 106 | char sig[return_len+2+type1_len+type2_len+1]; \ 107 | __builtin_memcpy(sig, return_, return_len); \ 108 | sig[return_len] = _C_ID; \ 109 | sig[return_len+1] = _C_SEL; \ 110 | __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \ 111 | __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \ 112 | sig[return_len+type1_len+type2_len+2] = '\0'; 113 | #define CHDeclareSig3_(return_type, type1, type2, type3) \ 114 | const char *return_ = @encode(return_type); \ 115 | size_t return_len = __builtin_strlen(return_); \ 116 | const char *type1_ = @encode(type1); \ 117 | size_t type1_len = __builtin_strlen(type1_); \ 118 | const char *type2_ = @encode(type2); \ 119 | size_t type2_len = __builtin_strlen(type2_); \ 120 | const char *type3_ = @encode(type3); \ 121 | size_t type3_len = __builtin_strlen(type3_); \ 122 | char sig[return_len+2+type1_len+type2_len+type3_len+1]; \ 123 | __builtin_memcpy(sig, return_, return_len); \ 124 | sig[return_len] = _C_ID; \ 125 | sig[return_len+1] = _C_SEL; \ 126 | __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \ 127 | __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \ 128 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \ 129 | sig[return_len+type1_len+type2_len+type3_len+2] = '\0'; 130 | #define CHDeclareSig4_(return_type, type1, type2, type3, type4) \ 131 | const char *return_ = @encode(return_type); \ 132 | size_t return_len = __builtin_strlen(return_); \ 133 | const char *type1_ = @encode(type1); \ 134 | size_t type1_len = __builtin_strlen(type1_); \ 135 | const char *type2_ = @encode(type2); \ 136 | size_t type2_len = __builtin_strlen(type2_); \ 137 | const char *type3_ = @encode(type3); \ 138 | size_t type3_len = __builtin_strlen(type3_); \ 139 | const char *type4_ = @encode(type4); \ 140 | size_t type4_len = __builtin_strlen(type4_); \ 141 | char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+1]; \ 142 | __builtin_memcpy(sig, return_, return_len); \ 143 | sig[return_len] = _C_ID; \ 144 | sig[return_len+1] = _C_SEL; \ 145 | __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \ 146 | __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \ 147 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \ 148 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \ 149 | sig[return_len+type1_len+type2_len+type3_len+type4_len+2] = '\0'; 150 | #define CHDeclareSig5_(return_type, type1, type2, type3, type4, type5) \ 151 | const char *return_ = @encode(return_type); \ 152 | size_t return_len = __builtin_strlen(return_); \ 153 | const char *type1_ = @encode(type1); \ 154 | size_t type1_len = __builtin_strlen(type1_); \ 155 | const char *type2_ = @encode(type2); \ 156 | size_t type2_len = __builtin_strlen(type2_); \ 157 | const char *type3_ = @encode(type3); \ 158 | size_t type3_len = __builtin_strlen(type3_); \ 159 | const char *type4_ = @encode(type4); \ 160 | size_t type4_len = __builtin_strlen(type4_); \ 161 | const char *type5_ = @encode(type5); \ 162 | size_t type5_len = __builtin_strlen(type5_); \ 163 | char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+1]; \ 164 | __builtin_memcpy(sig, return_, return_len); \ 165 | sig[return_len] = _C_ID; \ 166 | sig[return_len+1] = _C_SEL; \ 167 | __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \ 168 | __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \ 169 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \ 170 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \ 171 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \ 172 | sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+2] = '\0'; 173 | #define CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6) \ 174 | const char *return_ = @encode(return_type); \ 175 | size_t return_len = __builtin_strlen(return_); \ 176 | const char *type1_ = @encode(type1); \ 177 | size_t type1_len = __builtin_strlen(type1_); \ 178 | const char *type2_ = @encode(type2); \ 179 | size_t type2_len = __builtin_strlen(type2_); \ 180 | const char *type3_ = @encode(type3); \ 181 | size_t type3_len = __builtin_strlen(type3_); \ 182 | const char *type4_ = @encode(type4); \ 183 | size_t type4_len = __builtin_strlen(type4_); \ 184 | const char *type5_ = @encode(type5); \ 185 | size_t type5_len = __builtin_strlen(type5_); \ 186 | const char *type6_ = @encode(type6); \ 187 | size_t type6_len = __builtin_strlen(type6_); \ 188 | char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+1]; \ 189 | __builtin_memcpy(sig, return_, return_len); \ 190 | sig[return_len] = _C_ID; \ 191 | sig[return_len+1] = _C_SEL; \ 192 | __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \ 193 | __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \ 194 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \ 195 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \ 196 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \ 197 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \ 198 | sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+2] = '\0'; 199 | #define CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7) \ 200 | const char *return_ = @encode(return_type); \ 201 | size_t return_len = __builtin_strlen(return_); \ 202 | const char *type1_ = @encode(type1); \ 203 | size_t type1_len = __builtin_strlen(type1_); \ 204 | const char *type2_ = @encode(type2); \ 205 | size_t type2_len = __builtin_strlen(type2_); \ 206 | const char *type3_ = @encode(type3); \ 207 | size_t type3_len = __builtin_strlen(type3_); \ 208 | const char *type4_ = @encode(type4); \ 209 | size_t type4_len = __builtin_strlen(type4_); \ 210 | const char *type5_ = @encode(type5); \ 211 | size_t type5_len = __builtin_strlen(type5_); \ 212 | const char *type6_ = @encode(type6); \ 213 | size_t type6_len = __builtin_strlen(type6_); \ 214 | const char *type7_ = @encode(type7); \ 215 | size_t type7_len = __builtin_strlen(type7_); \ 216 | char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+1]; \ 217 | __builtin_memcpy(sig, return_, return_len); \ 218 | sig[return_len] = _C_ID; \ 219 | sig[return_len+1] = _C_SEL; \ 220 | __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \ 221 | __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \ 222 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \ 223 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \ 224 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \ 225 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \ 226 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len], type7_, type7_len); \ 227 | sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+2] = '\0'; 228 | #define CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8) \ 229 | const char *return_ = @encode(return_type); \ 230 | size_t return_len = __builtin_strlen(return_); \ 231 | const char *type1_ = @encode(type1); \ 232 | size_t type1_len = __builtin_strlen(type1_); \ 233 | const char *type2_ = @encode(type2); \ 234 | size_t type2_len = __builtin_strlen(type2_); \ 235 | const char *type3_ = @encode(type3); \ 236 | size_t type3_len = __builtin_strlen(type3_); \ 237 | const char *type4_ = @encode(type4); \ 238 | size_t type4_len = __builtin_strlen(type4_); \ 239 | const char *type5_ = @encode(type5); \ 240 | size_t type5_len = __builtin_strlen(type5_); \ 241 | const char *type6_ = @encode(type6); \ 242 | size_t type6_len = __builtin_strlen(type6_); \ 243 | const char *type7_ = @encode(type7); \ 244 | size_t type7_len = __builtin_strlen(type7_); \ 245 | const char *type8_ = @encode(type8); \ 246 | size_t type8_len = __builtin_strlen(type8_); \ 247 | char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+1]; \ 248 | __builtin_memcpy(sig, return_, return_len); \ 249 | sig[return_len] = _C_ID; \ 250 | sig[return_len+1] = _C_SEL; \ 251 | __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \ 252 | __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \ 253 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \ 254 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \ 255 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \ 256 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \ 257 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len], type7_, type7_len); \ 258 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len], type8_, type8_len); \ 259 | sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+2] = '\0'; 260 | #define CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9) \ 261 | const char *return_ = @encode(return_type); \ 262 | size_t return_len = __builtin_strlen(return_); \ 263 | const char *type1_ = @encode(type1); \ 264 | size_t type1_len = __builtin_strlen(type1_); \ 265 | const char *type2_ = @encode(type2); \ 266 | size_t type2_len = __builtin_strlen(type2_); \ 267 | const char *type3_ = @encode(type3); \ 268 | size_t type3_len = __builtin_strlen(type3_); \ 269 | const char *type4_ = @encode(type4); \ 270 | size_t type4_len = __builtin_strlen(type4_); \ 271 | const char *type5_ = @encode(type5); \ 272 | size_t type5_len = __builtin_strlen(type5_); \ 273 | const char *type6_ = @encode(type6); \ 274 | size_t type6_len = __builtin_strlen(type6_); \ 275 | const char *type7_ = @encode(type7); \ 276 | size_t type7_len = __builtin_strlen(type7_); \ 277 | const char *type8_ = @encode(type8); \ 278 | size_t type8_len = __builtin_strlen(type8_); \ 279 | const char *type9_ = @encode(type9); \ 280 | size_t type9_len = __builtin_strlen(type9_); \ 281 | char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+type9_len+1]; \ 282 | __builtin_memcpy(sig, return_, return_len); \ 283 | sig[return_len] = _C_ID; \ 284 | sig[return_len+1] = _C_SEL; \ 285 | __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \ 286 | __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \ 287 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \ 288 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \ 289 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \ 290 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \ 291 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len], type7_, type7_len); \ 292 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len], type8_, type8_len); \ 293 | __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len], type9_, type9_len); \ 294 | sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+type9_len+2] = '\0'; 295 | 296 | #ifdef CHUseSubstrate 297 | #import 298 | #define CHMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \ 299 | static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \ 300 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \ 301 | __attribute__((always_inline)) \ 302 | static inline void $ ## class_name ## _ ## name ## _register() { \ 303 | if (class_val) { \ 304 | MSHookMessageEx(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, (IMP *)&$ ## class_name ## _ ## name ## _super); \ 305 | if (!$ ## class_name ## _ ## name ## _super) { \ 306 | sigdef; \ 307 | class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \ 308 | } \ 309 | } \ 310 | } \ 311 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args) 312 | #define CHMethod_new_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \ 313 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \ 314 | __attribute__((always_inline)) \ 315 | static inline void $ ## class_name ## _ ## name ## _register() { \ 316 | sigdef; \ 317 | class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \ 318 | } \ 319 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args) 320 | #define CHMethod_super_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \ 321 | static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \ 322 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \ 323 | __attribute__((always_inline)) \ 324 | static inline void $ ## class_name ## _ ## name ## _register() { \ 325 | if (class_val) { \ 326 | MSHookMessageEx(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, (IMP *)&$ ## class_name ## _ ## name ## _super); \ 327 | } \ 328 | } \ 329 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args) 330 | #define CHMethod_self_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \ 331 | static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \ 332 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \ 333 | __attribute__((always_inline)) \ 334 | static inline void $ ## class_name ## _ ## name ## _register() { \ 335 | if (class_val) { \ 336 | MSHookMessageEx(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, (IMP *)&$ ## class_name ## _ ## name ## _super); \ 337 | } \ 338 | } \ 339 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args) 340 | #else 341 | #define CHMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \ 342 | static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \ 343 | static return_type $ ## class_name ## _ ## name ## _closure(class_type self, SEL _cmd, ##args) { \ 344 | typedef return_type (*supType)(class_type, SEL, ## args); \ 345 | supType supFn = (supType)class_getMethodImplementation(super_class_val, _cmd); \ 346 | return supFn supercall; \ 347 | } \ 348 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \ 349 | __attribute__((always_inline)) \ 350 | static inline void $ ## class_name ## _ ## name ## _register() { \ 351 | Method method = class_getInstanceMethod(class_val, @selector(sel)); \ 352 | if (method) { \ 353 | $ ## class_name ## _ ## name ## _super = (__typeof__($ ## class_name ## _ ## name ## _super))method_getImplementation(method); \ 354 | if (class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, method_getTypeEncoding(method))) { \ 355 | $ ## class_name ## _ ## name ## _super = &$ ## class_name ## _ ## name ## _closure; \ 356 | } else { \ 357 | method_setImplementation(method, (IMP)&$ ## class_name ## _ ## name ## _method); \ 358 | } \ 359 | } else { \ 360 | sigdef; \ 361 | class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \ 362 | } \ 363 | } \ 364 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args) 365 | #define CHMethod_new_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \ 366 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \ 367 | __attribute__((always_inline)) \ 368 | static inline void $ ## class_name ## _ ## name ## _register() { \ 369 | sigdef; \ 370 | class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \ 371 | } \ 372 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args) 373 | #define CHMethod_super_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \ 374 | static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \ 375 | static return_type $ ## class_name ## _ ## name ## _closure(class_type self, SEL _cmd, ##args) { \ 376 | typedef return_type (*supType)(class_type, SEL, ## args); \ 377 | supType supFn = (supType)class_getMethodImplementation(super_class_val, _cmd); \ 378 | return supFn supercall; \ 379 | } \ 380 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \ 381 | __attribute__((always_inline)) \ 382 | static inline void $ ## class_name ## _ ## name ## _register() { \ 383 | Method method = class_getInstanceMethod(class_val, @selector(sel)); \ 384 | if (method) { \ 385 | $ ## class_name ## _ ## name ## _super = (__typeof__($ ## class_name ## _ ## name ## _super))method_getImplementation(method); \ 386 | if (class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, method_getTypeEncoding(method))) { \ 387 | $ ## class_name ## _ ## name ## _super = &$ ## class_name ## _ ## name ## _closure; \ 388 | } else { \ 389 | method_setImplementation(method, (IMP)&$ ## class_name ## _ ## name ## _method); \ 390 | } \ 391 | } \ 392 | } \ 393 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args) 394 | #define CHMethod_self_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \ 395 | static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \ 396 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \ 397 | __attribute__((always_inline)) \ 398 | static inline void $ ## class_name ## _ ## name ## _register() { \ 399 | Method method = class_getInstanceMethod(class_val, @selector(sel)); \ 400 | if (method) { \ 401 | $ ## class_name ## _ ## name ## _super = (__typeof__($ ## class_name ## _ ## name ## _super))method_getImplementation(method); \ 402 | method_setImplementation(method, (IMP)&$ ## class_name ## _ ## name ## _method); \ 403 | } \ 404 | } \ 405 | static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args) 406 | #endif 407 | #define CHMethod(count, args...) \ 408 | CHMethod ## count(args) 409 | #define CHMethod0(return_type, class_type, name) \ 410 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name, name, CHDeclareSig0_(return_type), (self, _cmd)) 411 | #define CHMethod1(return_type, class_type, name1, type1, arg1) \ 412 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1) 413 | #define CHMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \ 414 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2) 415 | #define CHMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \ 416 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3) 417 | #define CHMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \ 418 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4) 419 | #define CHMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \ 420 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) 421 | #define CHMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \ 422 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) 423 | #define CHMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \ 424 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7) 425 | #define CHMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \ 426 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8) 427 | #define CHMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \ 428 | CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9) 429 | #define CHClassMethod(count, args...) \ 430 | CHClassMethod ## count(args) 431 | #define CHClassMethod0(return_type, class_type, name) \ 432 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name, name, CHDeclareSig0_(return_type), (self, _cmd)) 433 | #define CHClassMethod1(return_type, class_type, name1, type1, arg1) \ 434 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1) 435 | #define CHClassMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \ 436 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2) 437 | #define CHClassMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \ 438 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3) 439 | #define CHClassMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \ 440 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4) 441 | #define CHClassMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \ 442 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) 443 | #define CHClassMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \ 444 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) 445 | #define CHClassMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \ 446 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7) 447 | #define CHClassMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \ 448 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8) 449 | #define CHClassMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \ 450 | CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9) 451 | #define CHOptimizedMethod(count, args...) \ 452 | CHOptimizedMethod ## count(args) 453 | #define CHOptimizedMethod0(optimization, return_type, class_type, name) \ 454 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name, name, CHDeclareSig0_(return_type), (self, _cmd)) 455 | #define CHOptimizedMethod1(optimization, return_type, class_type, name1, type1, arg1) \ 456 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1) 457 | #define CHOptimizedMethod2(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2) \ 458 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2) 459 | #define CHOptimizedMethod3(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \ 460 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3) 461 | #define CHOptimizedMethod4(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \ 462 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4) 463 | #define CHOptimizedMethod5(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \ 464 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) 465 | #define CHOptimizedMethod6(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \ 466 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) 467 | #define CHOptimizedMethod7(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \ 468 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7) 469 | #define CHOptimizedMethod8(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \ 470 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8) 471 | #define CHOptimizedMethod9(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \ 472 | CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9) 473 | #define CHOptimizedClassMethod(count, args...) \ 474 | CHOptimizedClassMethod ## count(args) 475 | #define CHOptimizedClassMethod0(optimization, return_type, class_type, name) \ 476 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name, name, CHDeclareSig0_(return_type), (self, _cmd)) 477 | #define CHOptimizedClassMethod1(optimization, return_type, class_type, name1, type1, arg1) \ 478 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1) 479 | #define CHOptimizedClassMethod2(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2) \ 480 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2) 481 | #define CHOptimizedClassMethod3(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \ 482 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3) 483 | #define CHOptimizedClassMethod4(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \ 484 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4) 485 | #define CHOptimizedClassMethod5(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \ 486 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) 487 | #define CHOptimizedClassMethod6(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \ 488 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) 489 | #define CHOptimizedClassMethod7(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \ 490 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7) 491 | #define CHOptimizedClassMethod8(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \ 492 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8) 493 | #define CHOptimizedClassMethod9(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \ 494 | CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9) 495 | 496 | // Replacement Method Registration 497 | #define CHHook_(class_name, name) \ 498 | $ ## class_name ## _ ## name ## _register() 499 | #define CHHook(count, args...) CHHook ## count(args) 500 | #define CHHook0(class, name) CHHook_(class, name) 501 | #define CHHook1(class, name1) CHHook_(class, name1 ## $) 502 | #define CHHook2(class, name1, name2) CHHook_(class, name1 ## $ ## name2 ## $) 503 | #define CHHook3(class, name1, name2, name3) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $) 504 | #define CHHook4(class, name1, name2, name3, name4) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $) 505 | #define CHHook5(class, name1, name2, name3, name4, name5) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $) 506 | #define CHHook6(class, name1, name2, name3, name4, name5, name6) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $) 507 | #define CHHook7(class, name1, name2, name3, name4, name5, name6, name7) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $) 508 | #define CHHook8(class, name1, name2, name3, name4, name5, name6, name7, name8) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $) 509 | #define CHHook9(class, name1, name2, name3, name4, name5, name6, name7, name8, name9) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $) 510 | #define CHClassHook(count, args...) CHClassHook ## count(args) 511 | #define CHClassHook0(class, name) CHHook_(class, name) 512 | #define CHClassHook1(class, name1) CHHook_(class, name1 ## $) 513 | #define CHClassHook2(class, name1, name2) CHHook_(class, name1 ## $ ## name2 ## $) 514 | #define CHClassHook3(class, name1, name2, name3) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $) 515 | #define CHClassHook4(class, name1, name2, name3, name4) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $) 516 | #define CHClassHook5(class, name1, name2, name3, name4, name5) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $) 517 | #define CHClassHook6(class, name1, name2, name3, name4, name5, name6) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $) 518 | #define CHClassHook7(class, name1, name2, name3, name4, name5, name6, name7) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $) 519 | #define CHClassHook8(class, name1, name2, name3, name4, name5, name6, name7, name8) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $) 520 | #define CHClassHook9(class, name1, name2, name3, name4, name5, name6, name7, name8, name9) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $) 521 | 522 | // Declarative style methods (automatically calls CHHook) 523 | #define CHDeclareMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \ 524 | static inline void $ ## class_name ## _ ## name ## _register(); \ 525 | __attribute__((constructor)) \ 526 | static inline void $ ## class_name ## _ ## name ## _constructor() { \ 527 | CHLoadLateClass(class_name); \ 528 | $ ## class_name ## _ ## name ## _register(); \ 529 | } \ 530 | CHMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, ##args) 531 | #define CHDeclareMethod(count, args...) \ 532 | CHDeclareMethod ## count(args) 533 | #define CHDeclareMethod0(return_type, class_type, name) \ 534 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name, name, CHDeclareSig0_(return_type), (self, _cmd)) 535 | #define CHDeclareMethod1(return_type, class_type, name1, type1, arg1) \ 536 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1) 537 | #define CHDeclareMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \ 538 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2) 539 | #define CHDeclareMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \ 540 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3) 541 | #define CHDeclareMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \ 542 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4) 543 | #define CHDeclareMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \ 544 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## arg5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) 545 | #define CHDeclareMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \ 546 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) 547 | #define CHDeclareMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \ 548 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7) 549 | #define CHDeclareMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \ 550 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8) 551 | #define CHDeclareMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \ 552 | CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9) 553 | #define CHDeclareClassMethod(count, args...) \ 554 | CHDeclareClassMethod ## count(args) 555 | #define CHDeclareClassMethod0(return_type, class_type, name) \ 556 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name, name, CHDeclareSig0_(return_type), (self, _cmd)) 557 | #define CHDeclareClassMethod1(return_type, class_type, name1, type1, arg1) \ 558 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1) 559 | #define CHDeclareClassMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \ 560 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2) 561 | #define CHDeclareClassMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \ 562 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3) 563 | #define CHDeclareClassMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \ 564 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4) 565 | #define CHDeclareClassMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \ 566 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) 567 | #define CHDeclareClassMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \ 568 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) 569 | #define CHDeclareClassMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \ 570 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7) 571 | #define CHDeclareClassMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \ 572 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8) 573 | #define CHDeclareClassMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \ 574 | CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9) 575 | 576 | // Calling super class (or the old method as the case may be) 577 | #define CHSuper_(class_type, _cmd, name, args...) \ 578 | $ ## class_type ## _ ## name ## _super(self, _cmd, ##args) 579 | #define CHSuper(count, args...) \ 580 | CHSuper ## count(args) 581 | #define CHSuper0(class_type, name) \ 582 | CHSuper_(class_type, @selector(name), name) 583 | #define CHSuper1(class_type, name1, val1) \ 584 | CHSuper_(class_type, @selector(name1:), name1 ## $, val1) 585 | #define CHSuper2(class_type, name1, val1, name2, val2) \ 586 | CHSuper_(class_type, @selector(name1:name2:), name1 ## $ ## name2 ## $, val1, val2) 587 | #define CHSuper3(class_type, name1, val1, name2, val2, name3, val3) \ 588 | CHSuper_(class_type, @selector(name1:name2:name3:), name1 ## $ ## name2 ## $ ## name3 ## $, val1, val2, val3) 589 | #define CHSuper4(class_type, name1, val1, name2, val2, name3, val3, name4, val4) \ 590 | CHSuper_(class_type, @selector(name1:name2:name3:name4:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, val1, val2, val3, val4) 591 | #define CHSuper5(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5) \ 592 | CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, val1, val2, val3, val4, val5) 593 | #define CHSuper6(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5, name6, val6) \ 594 | CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:name6:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, val1, val2, val3, val4, val5, val6) 595 | #define CHSuper7(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5, name6, val6, name7, val7) \ 596 | CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:name6:name7:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, val1, val2, val3, val4, val5, val6, val7) 597 | #define CHSuper8(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5, name6, val6, name7, val7, name8, val8) \ 598 | CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:name6:name7:name8:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, val1, val2, val3, val4, val5, val6, val7, val8) 599 | #define CHSuper9(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5, name6, val6, name7, val7, name8, val8, name9, val9) \ 600 | CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:name6:name7:name8:name9:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, val1, val2, val3, val4, val5, val6, val7, val8, val9) 601 | 602 | // Create Class at Runtime (useful for creating subclasses of classes that can't be linked) 603 | #define CHRegisterClass(name, superName) for (int _tmp = ({ CHClass(name) = objc_allocateClassPair(CHClass(superName), #name, 0); CHMetaClass(name) = object_getClass(CHClass(name)); CHSuperClass(name) = class_getSuperclass(CHClass(name)); 1; }); _tmp; _tmp = ({ objc_registerClassPair(CHClass(name)), 0; })) 604 | #define CHAlignmentForSize_(size) ({ \ 605 | size_t s = size; \ 606 | __builtin_constant_p(s) ? ( \ 607 | (s) & (1 << 31) ? 31 : \ 608 | (s) & (1 << 30) ? 30 : \ 609 | (s) & (1 << 29) ? 29 : \ 610 | (s) & (1 << 28) ? 28 : \ 611 | (s) & (1 << 27) ? 27 : \ 612 | (s) & (1 << 26) ? 26 : \ 613 | (s) & (1 << 25) ? 25 : \ 614 | (s) & (1 << 24) ? 24 : \ 615 | (s) & (1 << 23) ? 23 : \ 616 | (s) & (1 << 22) ? 22 : \ 617 | (s) & (1 << 21) ? 21 : \ 618 | (s) & (1 << 20) ? 20 : \ 619 | (s) & (1 << 19) ? 19 : \ 620 | (s) & (1 << 18) ? 18 : \ 621 | (s) & (1 << 17) ? 17 : \ 622 | (s) & (1 << 16) ? 16 : \ 623 | (s) & (1 << 15) ? 15 : \ 624 | (s) & (1 << 14) ? 14 : \ 625 | (s) & (1 << 13) ? 13 : \ 626 | (s) & (1 << 12) ? 12 : \ 627 | (s) & (1 << 11) ? 11 : \ 628 | (s) & (1 << 10) ? 10 : \ 629 | (s) & (1 << 9) ? 9 : \ 630 | (s) & (1 << 8) ? 8 : \ 631 | (s) & (1 << 7) ? 7 : \ 632 | (s) & (1 << 6) ? 6 : \ 633 | (s) & (1 << 5) ? 5 : \ 634 | (s) & (1 << 4) ? 4 : \ 635 | (s) & (1 << 3) ? 3 : \ 636 | (s) & (1 << 2) ? 2 : \ 637 | (s) & (1 << 1) ? 1 : \ 638 | (s) & (1 << 0) ? 0 : \ 639 | 0 \ 640 | ) : (uint32_t)log2f(s); \ 641 | }) 642 | #define CHAddIvar(targetClass, name, type) \ 643 | class_addIvar(targetClass, #name, sizeof(type), CHAlignmentForSize_(sizeof(type)), @encode(type)) 644 | 645 | // Retrieve reference to an Ivar value (can read and assign) 646 | __attribute__((unused)) CHInline 647 | static void *CHIvar_(id object, const char *name) 648 | { 649 | Ivar ivar = class_getInstanceVariable(object_getClass(object), name); 650 | if (ivar) 651 | #ifdef CHHasARC 652 | return (void *)&((char *)(__bridge void *)object)[ivar_getOffset(ivar)]; 653 | #else 654 | return (void *)&((char *)object)[ivar_getOffset(ivar)]; 655 | #endif 656 | return NULL; 657 | } 658 | #define CHIvarRef(object, name, type) \ 659 | ((type *)CHIvar_(object, #name)) 660 | #define CHIvar(object, name, type) \ 661 | (*CHIvarRef(object, name, type)) 662 | // Warning: Dereferences NULL if object is nil or name isn't found. To avoid this save CHIvarRef(...) and test if != NULL 663 | 664 | #define CHDeclareProperty(class, name) static const char k ## class ## _ ## name; 665 | #define CHPropertyGetValue(class, name) objc_getAssociatedObject(self, &k ## class ## _ ## name ) 666 | #define CHPropertySetValue(class, name, value, policy) objc_setAssociatedObject(self, &k ## class ## _ ## name , value, policy) 667 | 668 | #define CHPropertyGetter(class, getter, type) CHOptimizedMethod0(new, type, class, getter) 669 | #define CHPropertySetter(class, setter, type, value) CHOptimizedMethod1(new, void, class, setter, type, value) 670 | 671 | // Obj-C dynamic property declaration (objects) 672 | #define CHProperty(class, type, getter, setter, policy) \ 673 | CHDeclareProperty(class, getter) \ 674 | CHPropertyGetter(class, getter, type) { \ 675 | return CHPropertyGetValue(class, getter); \ 676 | } \ 677 | CHPropertySetter(class, setter, type, getter) { \ 678 | CHPropertySetValue(class, getter, getter, policy); \ 679 | } 680 | #define CHPropertyRetain(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_RETAIN) 681 | #define CHPropertyRetainNonatomic(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_RETAIN_NONATOMIC) 682 | #define CHPropertyCopy(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_COPY) 683 | #define CHPropertyCopyNonatomic(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_COPY_NONATOMIC) 684 | #define CHPropertyAssign(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_ASSIGN) 685 | 686 | #define CHPrimitivePropertyGetValue(class, name, type, val, default) \ 687 | type val = default; \ 688 | do { \ 689 | NSNumber * objVal = CHPropertyGetValue(class, name); \ 690 | [objVal getValue:& val ]; \ 691 | } while(0) 692 | #define CHPrimitivePropertySetValue(class, name, type, val) \ 693 | do { \ 694 | NSValue *objVal = [NSValue value:& val withObjCType:@encode( type )]; \ 695 | CHPropertySetValue(class, name, objVal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); \ 696 | } while(0) 697 | 698 | // Primitive property equivalent (ie. BOOL, int, structs) 699 | #define CHPrimitiveProperty(class, type, getter, setter, default) \ 700 | CHDeclareProperty(class, getter) \ 701 | CHOptimizedMethod0(new, type, class, getter) { \ 702 | CHPrimitivePropertyGetValue( class , getter , type , val , default ); \ 703 | return val; \ 704 | } \ 705 | CHOptimizedMethod1(new, void, class, setter, type, getter) { \ 706 | CHPrimitivePropertySetValue( class , getter, type , getter ); \ 707 | } 708 | 709 | #define CHHookProperty(class, getter, setter) \ 710 | do { \ 711 | CHHook0(class, getter); \ 712 | CHHook1(class, setter); \ 713 | } while(0) 714 | 715 | #ifndef CHHasARC 716 | // Scope Autorelease 717 | __attribute__((unused)) CHInline 718 | static void CHScopeReleased(id *sro) 719 | { 720 | [*sro release]; 721 | } 722 | #define CHScopeReleased \ 723 | __attribute__((cleanup(CHScopeReleased))) 724 | 725 | #define CHAutoreleasePoolForScope() \ 726 | NSAutoreleasePool *CHAutoreleasePoolForScope __attribute__((unused)) CHScopeReleased = [[NSAutoreleasePool alloc] init] 727 | #endif 728 | 729 | // Build Assertion 730 | #define CHBuildAssert(condition) \ 731 | ((void)sizeof(char[1 - 2*!!(condition)])) 732 | 733 | // Profiling 734 | #ifdef CHEnableProfiling 735 | #import 736 | struct CHProfileData 737 | { 738 | NSString *message; 739 | uint64_t startTime; 740 | }; 741 | __attribute__((unused)) CHInline 742 | static void CHInline CHProfileCalculateDurationAndLog_(struct CHProfileData *profileData) 743 | { 744 | uint64_t duration = mach_absolute_time() - profileData->startTime; 745 | mach_timebase_info_data_t info; 746 | mach_timebase_info(&info); 747 | duration = (duration * info.numer) / info.denom; 748 | CHLog(@"Profile time: %lldns; %@", duration, profileData->message); 749 | } 750 | #define CHProfileScopeWithString(string) \ 751 | struct CHProfileData _profileData __attribute__((cleanup(CHProfileCalculateDurationAndLog_))) = ({ struct CHProfileData _tmp; _tmp.message = (string); _tmp.startTime = mach_absolute_time(); _tmp; }) 752 | #else 753 | #define CHProfileScopeWithString(string) \ 754 | CHNothing() 755 | #endif 756 | #define CHProfileScopeWithFormat(args...) \ 757 | CHProfileScopeWithString(([NSString stringWithFormat:args])) 758 | #define CHProfileScope() \ 759 | CHProfileScopeWithFormat(@CHStringify(__LINE__) " in %s", __FUNCTION__) 760 | -------------------------------------------------------------------------------- /include/libactivator/LAActivator.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import "LAActivatorVersion.h" 5 | 6 | // Main event dispatcher that is responsible for sending events, maintaining the list of actions/events, and querying information about them 7 | 8 | @class LAEvent; 9 | @protocol LAListener, LAEventDataSource; 10 | 11 | @interface LAActivator : NSObject LA_PRIVATE_IVARS(LAActivator) 12 | 13 | + (LAActivator *)sharedInstance; 14 | 15 | @property (nonatomic, readonly) LAActivatorVersion version; 16 | @property (nonatomic, readonly, getter=isRunningInsideSpringBoard) BOOL runningInsideSpringBoard; 17 | @property (nonatomic, readonly, getter=isDangerousToSendEvents) BOOL dangerousToSendEvents; 18 | 19 | // Listeners 20 | 21 | - (id)listenerForEvent:(LAEvent *)event; 22 | - (void)sendEventToListener:(LAEvent *)event; 23 | - (void)sendEvent:(LAEvent *)event toListenerWithName:(NSString *)listenerName; 24 | - (void)sendEvent:(LAEvent *)event toListenersWithNames:(NSArray *)listenerNames; 25 | - (void)sendAbortToListener:(LAEvent *)event; 26 | - (void)sendAbortEvent:(LAEvent *)event toListenerWithName:(NSString *)listenerName; 27 | - (void)sendAbortEvent:(LAEvent *)event toListenersWithNames:(NSArray *)listenerNames; 28 | - (void)sendPreviewEventToListenerWithName:(NSString *)listenerName; 29 | - (void)sendDeactivateEventToListeners:(LAEvent *)event; 30 | 31 | - (id)listenerForName:(NSString *)name; 32 | - (BOOL)hasListenerWithName:(NSString *)name; 33 | - (void)registerListener:(id)listener forName:(NSString *)name; // Only available in SpringBoard 34 | - (void)unregisterListenerWithName:(NSString *)name; // Only available in SpringBoard 35 | 36 | - (BOOL)hasSeenListenerWithName:(NSString *)name; 37 | 38 | // Assignments 39 | 40 | - (void)assignEvent:(LAEvent *)event toListenerWithName:(NSString *)listenerName; 41 | - (void)assignEvent:(LAEvent *)event toListenersWithNames:(NSArray *)listenerNames; 42 | - (void)addListenerAssignment:(NSString *)listenerName toEvent:(LAEvent *)event; 43 | - (void)removeListenerAssignment:(NSString *)listenerName fromEvent:(LAEvent *)event; 44 | - (void)unassignEvent:(LAEvent *)event; 45 | - (NSString *)assignedListenerNameForEvent:(LAEvent *)event; 46 | - (NSArray *)assignedListenerNamesForEvent:(LAEvent *)event; 47 | - (NSArray *)eventsAssignedToListenerWithName:(NSString *)listenerName; 48 | 49 | // Events 50 | 51 | @property (nonatomic, readonly) NSArray *availableEventNames; 52 | - (BOOL)eventWithNameIsHidden:(NSString *)name; 53 | - (BOOL)eventWithNameRequiresAssignment:(NSString *)name; 54 | - (NSArray *)compatibleModesForEventWithName:(NSString *)name; 55 | - (BOOL)eventWithName:(NSString *)eventName isCompatibleWithMode:(NSString *)eventMode; 56 | - (BOOL)eventWithNameSupportsUnlockingDeviceToSend:(NSString *)eventName; 57 | 58 | - (BOOL)eventWithNameSupportsConfiguration:(NSString *)eventName; 59 | - (NSString *)configurationViewControllerClassNameForEventWithName:(NSString *)eventName bundle:(NSBundle **)bundle; 60 | - (Class)configurationViewControllerClassForEventWithName:(NSString *)eventName; 61 | - (BOOL)eventWithNameSupportsRemoval:(NSString *)eventName; 62 | - (void)removeEventWithName:(NSString *)eventName; 63 | 64 | - (void)registerEventDataSource:(id)dataSource forEventName:(NSString *)eventName; 65 | - (void)unregisterEventDataSourceWithEventName:(NSString *)eventName; 66 | 67 | // Listener Metadata 68 | 69 | @property (nonatomic, readonly) NSArray *availableListenerNames; 70 | - (id)infoDictionaryValueOfKey:(NSString *)key forListenerWithName:(NSString *)name; 71 | - (BOOL)listenerWithNameRequiresAssignment:(NSString *)name; 72 | - (NSArray *)compatibleEventModesForListenerWithName:(NSString *)name; 73 | - (BOOL)listenerWithName:(NSString *)listenerName isCompatibleWithMode:(NSString *)eventMode; 74 | - (BOOL)listenerWithName:(NSString *)listenerName isCompatibleWithEventName:(NSString *)eventName; 75 | - (BOOL)listenerWithNameNeedsPoweredDisplay:(NSString *)listenerName; 76 | - (NSArray *)exclusiveAssignmentGroupsForListenerName:(NSString *)listenerName; 77 | - (BOOL)listenerNamesAreMutuallyCompatible:(NSArray *)listenerNames; 78 | - (UIImage *)iconForListenerName:(NSString *)listenerName; 79 | - (UIImage *)smallIconForListenerName:(NSString *)listenerName; 80 | 81 | // Event Modes 82 | 83 | @property (nonatomic, readonly) NSArray *availableEventModes; 84 | @property (nonatomic, readonly) NSString *currentEventMode; 85 | @property (nonatomic, readonly) NSString *currentEventModeUnderneathLockScreen; 86 | @property (nonatomic, readonly) BOOL supportsUnlockingDeviceToSendEvents; 87 | 88 | // Blacklisting 89 | 90 | @property (nonatomic, readonly) NSString *displayIdentifierForCurrentApplication; 91 | - (BOOL)applicationWithDisplayIdentifierIsBlacklisted:(NSString *)displayIdentifier; 92 | - (void)setApplicationWithDisplayIdentifier:(NSString *)displayIdentifier isBlacklisted:(BOOL)blacklisted; 93 | 94 | @end 95 | 96 | extern LAActivator *LASharedActivator; 97 | 98 | @interface LAActivator (Localization) 99 | - (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value; 100 | 101 | - (NSString *)localizedTitleForEventMode:(NSString *)eventMode; 102 | - (NSString *)localizedTitleForEventName:(NSString *)eventName; 103 | - (NSString *)localizedTitleForListenerName:(NSString *)listenerName; 104 | - (NSString *)localizedTitleForListenerNames:(NSArray *)listenerNames; 105 | 106 | - (NSString *)localizedGroupForEventName:(NSString *)eventName; 107 | - (NSString *)localizedGroupForListenerName:(NSString *)listenerName; 108 | 109 | - (NSString *)localizedDescriptionForEventMode:(NSString *)eventMode; 110 | - (NSString *)localizedDescriptionForEventName:(NSString *)eventName; 111 | - (NSString *)localizedDescriptionForListenerName:(NSString *)listenerName; 112 | @end 113 | 114 | extern NSString * const LAEventModeSpringBoard; 115 | extern NSString * const LAEventModeApplication; 116 | extern NSString * const LAEventModeLockScreen; 117 | 118 | extern NSString * const LAActivatorAvailableListenersChangedNotification; 119 | extern NSString * const LAActivatorAvailableEventsChangedNotification; 120 | -------------------------------------------------------------------------------- /include/libactivator/LAActivatorVersion.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | typedef enum { 4 | LAActivatorVersion_1_3 = 1030000, 5 | LAActivatorVersion_1_4 = 1040000, 6 | LAActivatorVersion_1_5 = 1050000, 7 | LAActivatorVersion_1_5_1 = 1050100, 8 | LAActivatorVersion_1_5_2 = 1050200, 9 | LAActivatorVersion_1_5_3 = 1050300, 10 | LAActivatorVersion_1_5_4 = 1050400, 11 | LAActivatorVersion_1_5_5 = 1050500, 12 | LAActivatorVersion_1_5_7 = 1050700, 13 | LAActivatorVersion_1_5_8 = 1050800, 14 | LAActivatorVersion_1_5_9 = 1050900, 15 | LAActivatorVersion_1_6 = 1060000, 16 | LAActivatorVersion_1_6_1 = 1060100, 17 | LAActivatorVersion_1_6_2 = 1060200, 18 | LAActivatorVersion_1_7 = 1070000, 19 | LAActivatorVersion_1_7_1 = 1070100, 20 | LAActivatorVersion_1_7_2 = 1070200, 21 | LAActivatorVersion_1_7_3 = 1070300, 22 | LAActivatorVersion_1_7_4 = 1070400, 23 | LAActivatorVersion_1_8_0 = 1070500, 24 | LAActivatorVersion_1_8_1 = 1080100, 25 | LAActivatorVersion_1_8_2 = 1080200, 26 | } LAActivatorVersion; 27 | 28 | #ifndef LA_PRIVATE_IVARS 29 | #define LA_PRIVATE_IVARS(class) 30 | #endif 31 | -------------------------------------------------------------------------------- /include/libactivator/LAEvent.h: -------------------------------------------------------------------------------- 1 | #import "LAActivatorVersion.h" 2 | 3 | // Events represent an assignable gesture that has or could occurred 4 | 5 | @interface LAEvent : NSObject LA_PRIVATE_IVARS(LAEvent) 6 | 7 | + (id)eventWithName:(NSString *)name; 8 | + (id)eventWithName:(NSString *)name mode:(NSString *)mode; 9 | - (id)initWithName:(NSString *)name; 10 | - (id)initWithName:(NSString *)name mode:(NSString *)mode; 11 | 12 | @property (nonatomic, readonly) NSString *name; 13 | @property (nonatomic, readonly) NSString *mode; 14 | @property (nonatomic, getter=isHandled) BOOL handled; 15 | @property (nonatomic, copy) NSDictionary *userInfo; 16 | 17 | @end 18 | 19 | extern NSString * const LAEventNameMenuPressSingle; 20 | extern NSString * const LAEventNameMenuPressDouble; 21 | extern NSString * const LAEventNameMenuPressTriple; 22 | extern NSString * const LAEventNameMenuHoldShort; 23 | extern NSString * const LAEventNameMenuHoldLong; 24 | 25 | extern NSString * const LAEventNameLockHoldShort; 26 | extern NSString * const LAEventNameLockHoldLong; 27 | extern NSString * const LAEventNameLockPressDouble; 28 | extern NSString * const LAEventNameLockPressWithMenu; 29 | 30 | extern NSString * const LAEventNameSpringBoardPinch; 31 | extern NSString * const LAEventNameSpringBoardSpread; 32 | 33 | extern NSString * const LAEventNameStatusBarSwipeRight; 34 | extern NSString * const LAEventNameStatusBarSwipeLeft; 35 | extern NSString * const LAEventNameStatusBarTapDouble; 36 | extern NSString * const LAEventNameStatusBarTapDoubleLeft; 37 | extern NSString * const LAEventNameStatusBarTapDoubleRight; 38 | extern NSString * const LAEventNameStatusBarTapSingle; 39 | extern NSString * const LAEventNameStatusBarTapSingleLeft; 40 | extern NSString * const LAEventNameStatusBarTapSingleRight; 41 | extern NSString * const LAEventNameStatusBarHold; 42 | extern NSString * const LAEventNameStatusBarHoldLeft; 43 | extern NSString * const LAEventNameStatusBarHoldRight; 44 | 45 | extern NSString * const LAEventNameVolumeDownUp; 46 | extern NSString * const LAEventNameVolumeUpDown; 47 | extern NSString * const LAEventNameVolumeDisplayTap; 48 | extern NSString * const LAEventNameVolumeToggleMuteTwice; 49 | extern NSString * const LAEventNameVolumeDownHoldShort; 50 | extern NSString * const LAEventNameVolumeUpHoldShort; 51 | extern NSString * const LAEventNameVolumeDownPress; 52 | extern NSString * const LAEventNameVolumeUpPress; 53 | extern NSString * const LAEventNameVolumeBothPress; 54 | 55 | extern NSString * const LAEventNameSlideInFromBottom; 56 | extern NSString * const LAEventNameSlideInFromBottomLeft; 57 | extern NSString * const LAEventNameSlideInFromBottomRight; 58 | extern NSString * const LAEventNameSlideInFromLeft; 59 | extern NSString * const LAEventNameSlideInFromRight; 60 | extern NSString * const LAEventNameStatusBarSwipeDown; // Now a slide gesture in iOS5.0+; extern and name kept for backwards compatibility 61 | #define LAEventNameSlideInFromTop LAEventNameStatusBarSwipeDown 62 | extern NSString * const LAEventNameSlideInFromTopLeft; 63 | extern NSString * const LAEventNameSlideInFromTopRight; 64 | 65 | extern NSString * const LAEventNameTwoFingerSlideInFromBottom; 66 | extern NSString * const LAEventNameTwoFingerSlideInFromBottomLeft; 67 | extern NSString * const LAEventNameTwoFingerSlideInFromBottomRight; 68 | extern NSString * const LAEventNameTwoFingerSlideInFromLeft; 69 | extern NSString * const LAEventNameTwoFingerSlideInFromRight; 70 | extern NSString * const LAEventNameTwoFingerSlideInFromTop; 71 | extern NSString * const LAEventNameTwoFingerSlideInFromTopLeft; 72 | extern NSString * const LAEventNameTwoFingerSlideInFromTopRight; 73 | 74 | extern NSString * const LAEventNameDragOffBottom; 75 | extern NSString * const LAEventNameDragOffLeft; 76 | extern NSString * const LAEventNameDragOffRight; 77 | extern NSString * const LAEventNameDragOffTop; 78 | 79 | extern NSString * const LAEventScreenBottomSwipeLeft; 80 | extern NSString * const LAEventScreenBottomSwipeRight; 81 | extern NSString * const LAEventScreenLeftSwipeDown; 82 | extern NSString * const LAEventScreenLeftSwipeUp; 83 | extern NSString * const LAEventScreenRightSwipeDown; 84 | extern NSString * const LAEventScreenRightSwipeUp; 85 | 86 | extern NSString * const LAEventNameMotionShake; 87 | 88 | extern NSString * const LAEventNameHeadsetButtonPressSingle; 89 | extern NSString * const LAEventNameHeadsetButtonHoldShort; 90 | extern NSString * const LAEventNameHeadsetConnected; 91 | extern NSString * const LAEventNameHeadsetDisconnected; 92 | 93 | extern NSString * const LAEventNameLockScreenClockDoubleTap; 94 | extern NSString * const LAEventNameLockScreenClockTapHold; 95 | extern NSString * const LAEventNameLockScreenClockSwipeLeft; 96 | extern NSString * const LAEventNameLockScreenClockSwipeRight; 97 | 98 | extern NSString * const LAEventNamePowerConnected; 99 | extern NSString * const LAEventNamePowerDisconnected; 100 | 101 | extern NSString * const LAEventNameThreeFingerTap; 102 | extern NSString * const LAEventNameThreeFingerPinch; 103 | extern NSString * const LAEventNameThreeFingerSpread; 104 | 105 | extern NSString * const LAEventNameFourFingerTap; 106 | extern NSString * const LAEventNameFourFingerPinch; 107 | extern NSString * const LAEventNameFourFingerSpread; 108 | 109 | extern NSString * const LAEventNameFiveFingerTap; 110 | extern NSString * const LAEventNameFiveFingerPinch; 111 | extern NSString * const LAEventNameFiveFingerSpread; 112 | 113 | extern NSString * const LAEventNameClamshellOpen; 114 | extern NSString * const LAEventNameClamshellClose; 115 | 116 | extern NSString * const LAEventNameSpringBoardIconFlickUp; 117 | extern NSString * const LAEventNameSpringBoardIconFlickDown; 118 | extern NSString * const LAEventNameSpringBoardIconFlickLeft; 119 | extern NSString * const LAEventNameSpringBoardIconFlickRight; 120 | 121 | extern NSString * const LAEventNameDeviceLocked; 122 | extern NSString * const LAEventNameDeviceUnlocked; 123 | 124 | extern NSString * const LAEventNameNetworkJoinedWiFi; 125 | extern NSString * const LAEventNameNetworkLeftWiFi; 126 | 127 | // Icon Gestures 128 | extern NSString * const LAEventUserInfoDisplayIdentifier; 129 | extern NSString * const LAEventUserInfoIconView; 130 | 131 | extern NSString * const LAEventUserInfoUnlockedDeviceToSendEvent; 132 | -------------------------------------------------------------------------------- /include/libactivator/LAEventDataSource.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | // Event Data Sources represent the metadata associated with specific events 4 | // A data source is constructed automatically for each event in /Library/Activator/Events 5 | 6 | @protocol LAEventDataSource 7 | 8 | @required 9 | - (NSString *)localizedTitleForEventName:(NSString *)eventName; 10 | - (NSString *)localizedGroupForEventName:(NSString *)eventName; 11 | - (NSString *)localizedDescriptionForEventName:(NSString *)eventName; 12 | 13 | @optional 14 | - (BOOL)eventWithNameIsHidden:(NSString *)eventName; 15 | - (BOOL)eventWithNameRequiresAssignment:(NSString *)eventName; 16 | - (BOOL)eventWithName:(NSString *)eventName isCompatibleWithMode:(NSString *)eventMode; 17 | - (BOOL)eventWithNameSupportsUnlockingDeviceToSend:(NSString *)eventName; 18 | 19 | - (BOOL)eventWithNameSupportsRemoval:(NSString *)eventName; 20 | - (void)removeEventWithName:(NSString *)eventName; 21 | - (NSString *)configurationViewControllerClassNameForEventWithName:(NSString *)eventName bundle:(NSBundle **)bundle; // LAEventConfigurationViewController 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /include/libactivator/LAListener.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | // Listeners represent specific actions that can be performed in response to an event 5 | // Must be registered with LAActivator inside SpringBoard via the registerListener:forName: method 6 | 7 | @class LAActivator, LAEvent, UIImage; 8 | 9 | @protocol LAListener 10 | @optional 11 | 12 | - (void)activator:(LAActivator *)activator didChangeToEventMode:(NSString *)eventMode; 13 | 14 | // Incoming events 15 | - (void)activator:(LAActivator *)activator receiveEvent:(LAEvent *)event forListenerName:(NSString *)listenerName; // Normal assigned events 16 | - (void)activator:(LAActivator *)activator abortEvent:(LAEvent *)event forListenerName:(NSString *)listenerName; // Sent when a chorded event gets escalated (short hold becoems a long hold, for example) 17 | - (BOOL)activator:(LAActivator *)activator receiveUnlockingDeviceEvent:(LAEvent *)event forListenerName:(NSString *)listenerName; // Sent at the lock screen when listener is not compatible with event, but potentially is able to unlock the screen to handle it 18 | - (void)activator:(LAActivator *)activator receiveDeactivateEvent:(LAEvent *)event; // Sent when the menu button is pressed. Only handle if you want to suppress the standard menu button behaviour! 19 | - (void)activator:(LAActivator *)activator otherListenerDidHandleEvent:(LAEvent *)event; // Sent when another listener has handled the event 20 | - (void)activator:(LAActivator *)activator receivePreviewEventForListenerName:(NSString *)listenerName; // Sent from the settings pane when a listener is assigned 21 | 22 | // Simpler versions 23 | - (void)activator:(LAActivator *)activator receiveEvent:(LAEvent *)event; 24 | - (void)activator:(LAActivator *)activator abortEvent:(LAEvent *)event; 25 | 26 | // Metadata (may be cached) 27 | - (NSString *)activator:(LAActivator *)activator requiresLocalizedTitleForListenerName:(NSString *)listenerName; 28 | - (NSString *)activator:(LAActivator *)activator requiresLocalizedDescriptionForListenerName:(NSString *)listenerName; 29 | - (NSString *)activator:(LAActivator *)activator requiresLocalizedGroupForListenerName:(NSString *)listenerName; 30 | - (NSNumber *)activator:(LAActivator *)activator requiresRequiresAssignmentForListenerName:(NSString *)listenerName; 31 | - (NSArray *)activator:(LAActivator *)activator requiresCompatibleEventModesForListenerWithName:(NSString *)listenerName; 32 | - (NSNumber *)activator:(LAActivator *)activator requiresIsCompatibleWithEventName:(NSString *)eventName listenerName:(NSString *)listenerName; 33 | - (NSArray *)activator:(LAActivator *)activator requiresExclusiveAssignmentGroupsForListenerName:(NSString *)listenerName; 34 | - (id)activator:(LAActivator *)activator requiresInfoDictionaryValueOfKey:(NSString *)key forListenerWithName:(NSString *)listenerName; 35 | - (BOOL)activator:(LAActivator *)activator requiresNeedsPoweredDisplayForListenerName:(NSString *)listenerName; 36 | 37 | // Icons 38 | // Fast path that supports scale 39 | - (NSData *)activator:(LAActivator *)activator requiresIconDataForListenerName:(NSString *)listenerName scale:(CGFloat *)scale; 40 | - (NSData *)activator:(LAActivator *)activator requiresSmallIconDataForListenerName:(NSString *)listenerName scale:(CGFloat *)scale; 41 | // Legacy 42 | - (NSData *)activator:(LAActivator *)activator requiresIconDataForListenerName:(NSString *)listenerName; 43 | - (NSData *)activator:(LAActivator *)activator requiresSmallIconDataForListenerName:(NSString *)listenerName; 44 | // For cases where PNG data isn't available quickly 45 | - (UIImage *)activator:(LAActivator *)activator requiresIconForListenerName:(NSString *)listenerName scale:(CGFloat)scale; 46 | - (UIImage *)activator:(LAActivator *)activator requiresSmallIconForListenerName:(NSString *)listenerName scale:(CGFloat)scale; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /include/libactivator/LASettingsViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | // Settings View Controllers represent view controllers that can be displayed the Activator app, Activator's settings pane, and possibly in other Activator-integrated apps 4 | 5 | #ifndef LA_SETTINGS_CONTROLLER 6 | #define LA_SETTINGS_CONTROLLER(superclass) : superclass 7 | #endif 8 | 9 | @interface LASettingsViewController LA_SETTINGS_CONTROLLER(UIViewController) 10 | + (id)controller; 11 | - (id)init; 12 | @end 13 | 14 | @interface LARootSettingsController LA_SETTINGS_CONTROLLER(LASettingsViewController) 15 | @end 16 | 17 | @interface LAModeSettingsController LA_SETTINGS_CONTROLLER(LASettingsViewController) 18 | - (id)initWithMode:(NSString *)mode; 19 | @end 20 | 21 | @interface LAEventSettingsController LA_SETTINGS_CONTROLLER(LASettingsViewController) 22 | - (id)initWithModes:(NSArray *)modes eventName:(NSString *)eventName; 23 | @end 24 | 25 | @interface LAListenerSettingsViewController LA_SETTINGS_CONTROLLER(LASettingsViewController) 26 | @property (nonatomic, copy) NSString *listenerName; 27 | @end 28 | 29 | @interface LAEventConfigurationViewController LA_SETTINGS_CONTROLLER(LASettingsViewController) 30 | - (id)initWithEventName:(NSString *)eventName; 31 | @property (nonatomic, readonly, copy) NSString *eventName; 32 | @property (nonatomic, assign) BOOL showsSaveButton; 33 | - (BOOL)performSave; 34 | @end 35 | -------------------------------------------------------------------------------- /include/libactivator/UIImageView+Activator.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface UIImageView (Activator) 4 | @property (nonatomic, assign) BOOL activatorListenerImageIsThreaded; 5 | @property (nonatomic, copy) NSString *activatorListenerName; 6 | @end 7 | -------------------------------------------------------------------------------- /include/libactivator/libactivator.h: -------------------------------------------------------------------------------- 1 | #import "LAActivator.h" 2 | #import "LAActivatorVersion.h" 3 | #import "LAEvent.h" 4 | #import "LAEventDataSource.h" 5 | #import "LAListener.h" 6 | #import "LASettingsViewController.h" 7 | #import "UIImageView+Activator.h" 8 | -------------------------------------------------------------------------------- /include/logos/logos.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOGOS_H 2 | #define __LOGOS_H 3 | #endif -------------------------------------------------------------------------------- /include/substrate.h: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2013 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published 9 | * by the Free Software Foundation, either version 3 of the License, 10 | * or (at your option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_H_ 23 | #define SUBSTRATE_H_ 24 | 25 | #ifdef __APPLE__ 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | #include 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #include 35 | #include 36 | #endif 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #define _finline \ 43 | inline __attribute__((__always_inline__)) 44 | #define _disused \ 45 | __attribute__((__unused__)) 46 | 47 | #ifdef __cplusplus 48 | #define _default(value) = value 49 | #else 50 | #define _default(value) 51 | #endif 52 | 53 | #ifdef __cplusplus 54 | extern "C" { 55 | #endif 56 | 57 | bool MSHookProcess(pid_t pid, const char *library); 58 | 59 | typedef const void *MSImageRef; 60 | 61 | MSImageRef MSGetImageByName(const char *file); 62 | void *MSFindSymbol(MSImageRef image, const char *name); 63 | 64 | void MSHookFunction(void *symbol, void *replace, void **result); 65 | 66 | #ifdef __APPLE__ 67 | #ifdef __arm__ 68 | __attribute__((__deprecated__)) 69 | IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix _default(NULL)); 70 | #endif 71 | void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result); 72 | #endif 73 | 74 | #ifdef __ANDROID__ 75 | #include 76 | void MSJavaHookClassLoad(JNIEnv *jni, const char *name, void (*callback)(JNIEnv *, jclass, void *), void *data _default(NULL)); 77 | void MSJavaHookMethod(JNIEnv *jni, jclass _class, jmethodID methodID, void *function, void **result); 78 | void MSJavaBlessClassLoader(JNIEnv *jni, jobject loader); 79 | 80 | typedef struct MSJavaObjectKey_ *MSJavaObjectKey; 81 | MSJavaObjectKey MSJavaCreateObjectKey(); 82 | void MSJavaReleaseObjectKey(MSJavaObjectKey key); 83 | void *MSJavaGetObjectKey(JNIEnv *jni, jobject object, MSJavaObjectKey key); 84 | void MSJavaSetObjectKey(JNIEnv *jni, jobject object, MSJavaObjectKey key, void *value, void (*clean)(void *, JNIEnv *, void *) _default(NULL), void *data _default(NULL)); 85 | #endif 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | 91 | #ifdef __cplusplus 92 | 93 | #ifdef __APPLE__ 94 | 95 | namespace etl { 96 | 97 | template 98 | struct Case { 99 | static char value[Case_ + 1]; 100 | }; 101 | 102 | typedef Case Yes; 103 | typedef Case No; 104 | 105 | namespace be { 106 | template 107 | static Yes CheckClass_(void (Checked_::*)()); 108 | 109 | template 110 | static No CheckClass_(...); 111 | } 112 | 113 | template 114 | struct IsClass { 115 | void gcc32(); 116 | 117 | static const bool value = (sizeof(be::CheckClass_(0).value) == sizeof(Yes::value)); 118 | }; 119 | 120 | } 121 | 122 | #ifdef __arm__ 123 | template 124 | __attribute__((__deprecated__)) 125 | static inline Type_ *MSHookMessage(Class _class, SEL sel, Type_ *imp, const char *prefix = NULL) { 126 | return reinterpret_cast(MSHookMessage(_class, sel, reinterpret_cast(imp), prefix)); 127 | } 128 | #endif 129 | 130 | template 131 | static inline void MSHookMessage(Class _class, SEL sel, Type_ *imp, Type_ **result) { 132 | return MSHookMessageEx(_class, sel, reinterpret_cast(imp), reinterpret_cast(result)); 133 | } 134 | 135 | template 136 | static inline Type_ &MSHookIvar(id self, const char *name) { 137 | Ivar ivar(class_getInstanceVariable(object_getClass(self), name)); 138 | void *pointer(ivar == NULL ? NULL : reinterpret_cast(self) + ivar_getOffset(ivar)); 139 | return *reinterpret_cast(pointer); 140 | } 141 | 142 | #define MSAddMessage0(_class, type, arg0) \ 143 | class_addMethod($ ## _class, @selector(arg0), (IMP) &$ ## _class ## $ ## arg0, type); 144 | #define MSAddMessage1(_class, type, arg0) \ 145 | class_addMethod($ ## _class, @selector(arg0:), (IMP) &$ ## _class ## $ ## arg0 ## $, type); 146 | #define MSAddMessage2(_class, type, arg0, arg1) \ 147 | class_addMethod($ ## _class, @selector(arg0:arg1:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $, type); 148 | #define MSAddMessage3(_class, type, arg0, arg1, arg2) \ 149 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $, type); 150 | #define MSAddMessage4(_class, type, arg0, arg1, arg2, arg3) \ 151 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $, type); 152 | #define MSAddMessage5(_class, type, arg0, arg1, arg2, arg3, arg4) \ 153 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $, type); 154 | #define MSAddMessage6(_class, type, arg0, arg1, arg2, arg3, arg4, arg5) \ 155 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $, type); 156 | #define MSAddMessage7(_class, type, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \ 157 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:arg6:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $ $$ arg6 ## $, type); 158 | #define MSAddMessage8(_class, type, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ 159 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:arg6:arg7:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $ $$ arg6 ## $ ## arg7 ## $, type); 160 | 161 | #define MSHookMessage0(_class, arg0) \ 162 | MSHookMessage($ ## _class, @selector(arg0), MSHake(_class ## $ ## arg0)) 163 | #define MSHookMessage1(_class, arg0) \ 164 | MSHookMessage($ ## _class, @selector(arg0:), MSHake(_class ## $ ## arg0 ## $)) 165 | #define MSHookMessage2(_class, arg0, arg1) \ 166 | MSHookMessage($ ## _class, @selector(arg0:arg1:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $)) 167 | #define MSHookMessage3(_class, arg0, arg1, arg2) \ 168 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $)) 169 | #define MSHookMessage4(_class, arg0, arg1, arg2, arg3) \ 170 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $)) 171 | #define MSHookMessage5(_class, arg0, arg1, arg2, arg3, arg4) \ 172 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $)) 173 | #define MSHookMessage6(_class, arg0, arg1, arg2, arg3, arg4, arg5) \ 174 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $)) 175 | #define MSHookMessage7(_class, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \ 176 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:arg6:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $ ## arg6 ## $)) 177 | #define MSHookMessage8(_class, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ 178 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:arg6:arg7:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $ ## arg6 ## $ ## arg7 ## $)) 179 | 180 | #define MSRegister_(name, dollar, colon) \ 181 | namespace { static class C_$ ## name ## $ ## dollar { public: _finline C_$ ## name ## $ ##dollar() { \ 182 | MSHookMessage($ ## name, @selector(colon), MSHake(name ## $ ## dollar)); \ 183 | } } V_$ ## name ## $ ## dollar; } \ 184 | 185 | #define MSIgnore_(name, dollar, colon) 186 | 187 | #ifdef __arm64__ 188 | #define MS_objc_msgSendSuper_stret objc_msgSendSuper 189 | #else 190 | #define MS_objc_msgSendSuper_stret objc_msgSendSuper_stret 191 | #endif 192 | 193 | #define MSMessage_(extra, type, _class, name, dollar, colon, call, args...) \ 194 | static type _$ ## name ## $ ## dollar(Class _cls, type (*_old)(_class, SEL, ## args, ...), type (*_spr)(struct objc_super *, SEL, ## args, ...), _class self, SEL _cmd, ## args); \ 195 | MSHook(type, name ## $ ## dollar, _class self, SEL _cmd, ## args) { \ 196 | Class const _cls($ ## name); \ 197 | type (* const _old)(_class, SEL, ## args, ...) = reinterpret_cast(_ ## name ## $ ## dollar); \ 198 | typedef type (*msgSendSuper_t)(struct objc_super *, SEL, ## args, ...); \ 199 | msgSendSuper_t const _spr(::etl::IsClass::value ? reinterpret_cast(&MS_objc_msgSendSuper_stret) : reinterpret_cast(&objc_msgSendSuper)); \ 200 | return _$ ## name ## $ ## dollar call; \ 201 | } \ 202 | extra(name, dollar, colon) \ 203 | static _finline type _$ ## name ## $ ## dollar(Class _cls, type (*_old)(_class, SEL, ## args, ...), type (*_spr)(struct objc_super *, SEL, ## args, ...), _class self, SEL _cmd, ## args) 204 | 205 | /* for((x=1;x!=7;++x)){ echo -n "#define MSMessage${x}_(extra, type, _class, name";for((y=0;y!=x;++y));do echo -n ", sel$y";done;for((y=0;y!=x;++y));do echo -n ", type$y, arg$y";done;echo ") \\";echo -n " MSMessage_(extra, type, _class, name,";for((y=0;y!=x;++y));do if [[ $y -ne 0 ]];then echo -n " ##";fi;echo -n " sel$y ## $";done;echo -n ", ";for((y=0;y!=x;++y));do echo -n "sel$y:";done;echo -n ", (_cls, _old, _spr, self, _cmd";for((y=0;y!=x;++y));do echo -n ", arg$y";done;echo -n ")";for((y=0;y!=x;++y));do echo -n ", type$y arg$y";done;echo ")";} */ 206 | 207 | #define MSMessage0_(extra, type, _class, name, sel0) \ 208 | MSMessage_(extra, type, _class, name, sel0, sel0, (_cls, _old, _spr, self, _cmd)) 209 | #define MSMessage1_(extra, type, _class, name, sel0, type0, arg0) \ 210 | MSMessage_(extra, type, _class, name, sel0 ## $, sel0:, (_cls, _old, _spr, self, _cmd, arg0), type0 arg0) 211 | #define MSMessage2_(extra, type, _class, name, sel0, sel1, type0, arg0, type1, arg1) \ 212 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $, sel0:sel1:, (_cls, _old, _spr, self, _cmd, arg0, arg1), type0 arg0, type1 arg1) 213 | #define MSMessage3_(extra, type, _class, name, sel0, sel1, sel2, type0, arg0, type1, arg1, type2, arg2) \ 214 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $, sel0:sel1:sel2:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2), type0 arg0, type1 arg1, type2 arg2) 215 | #define MSMessage4_(extra, type, _class, name, sel0, sel1, sel2, sel3, type0, arg0, type1, arg1, type2, arg2, type3, arg3) \ 216 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $, sel0:sel1:sel2:sel3:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3), type0 arg0, type1 arg1, type2 arg2, type3 arg3) 217 | #define MSMessage5_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ 218 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $ ## sel4 ## $, sel0:sel1:sel2:sel3:sel4:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3, arg4), type0 arg0, type1 arg1, type2 arg2, type3 arg3, type4 arg4) 219 | #define MSMessage6_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, sel5, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ 220 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $ ## sel4 ## $ ## sel5 ## $, sel0:sel1:sel2:sel3:sel4:sel5:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3, arg4, arg5), type0 arg0, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) 221 | #define MSMessage7_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, sel5, sel6, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6) \ 222 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $ ## sel4 ## $ ## sel5 ## $ ## sel6 ## $, sel0:sel1:sel2:sel3:sel4:sel5:sel6:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3, arg4, arg5, arg6), type0 arg0, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) 223 | #define MSMessage8_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, sel5, sel6, sel7, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7) \ 224 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $ ## sel4 ## $ ## sel5 ## $ ## sel6 ## $ ## sel7 ## $, sel0:sel1:sel2:sel3:sel4:sel5:sel6:sel7:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type0 arg0, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7) 225 | 226 | #define MSInstanceMessage0(type, _class, args...) MSMessage0_(MSIgnore_, type, _class *, _class, ## args) 227 | #define MSInstanceMessage1(type, _class, args...) MSMessage1_(MSIgnore_, type, _class *, _class, ## args) 228 | #define MSInstanceMessage2(type, _class, args...) MSMessage2_(MSIgnore_, type, _class *, _class, ## args) 229 | #define MSInstanceMessage3(type, _class, args...) MSMessage3_(MSIgnore_, type, _class *, _class, ## args) 230 | #define MSInstanceMessage4(type, _class, args...) MSMessage4_(MSIgnore_, type, _class *, _class, ## args) 231 | #define MSInstanceMessage5(type, _class, args...) MSMessage5_(MSIgnore_, type, _class *, _class, ## args) 232 | #define MSInstanceMessage6(type, _class, args...) MSMessage6_(MSIgnore_, type, _class *, _class, ## args) 233 | #define MSInstanceMessage7(type, _class, args...) MSMessage7_(MSIgnore_, type, _class *, _class, ## args) 234 | #define MSInstanceMessage8(type, _class, args...) MSMessage8_(MSIgnore_, type, _class *, _class, ## args) 235 | 236 | #define MSClassMessage0(type, _class, args...) MSMessage0_(MSIgnore_, type, Class, $ ## _class, ## args) 237 | #define MSClassMessage1(type, _class, args...) MSMessage1_(MSIgnore_, type, Class, $ ## _class, ## args) 238 | #define MSClassMessage2(type, _class, args...) MSMessage2_(MSIgnore_, type, Class, $ ## _class, ## args) 239 | #define MSClassMessage3(type, _class, args...) MSMessage3_(MSIgnore_, type, Class, $ ## _class, ## args) 240 | #define MSClassMessage4(type, _class, args...) MSMessage4_(MSIgnore_, type, Class, $ ## _class, ## args) 241 | #define MSClassMessage5(type, _class, args...) MSMessage5_(MSIgnore_, type, Class, $ ## _class, ## args) 242 | #define MSClassMessage6(type, _class, args...) MSMessage6_(MSIgnore_, type, Class, $ ## _class, ## args) 243 | #define MSClassMessage7(type, _class, args...) MSMessage7_(MSIgnore_, type, Class, $ ## _class, ## args) 244 | #define MSClassMessage8(type, _class, args...) MSMessage8_(MSIgnore_, type, Class, $ ## _class, ## args) 245 | 246 | #define MSInstanceMessageHook0(type, _class, args...) MSMessage0_(MSRegister_, type, _class *, _class, ## args) 247 | #define MSInstanceMessageHook1(type, _class, args...) MSMessage1_(MSRegister_, type, _class *, _class, ## args) 248 | #define MSInstanceMessageHook2(type, _class, args...) MSMessage2_(MSRegister_, type, _class *, _class, ## args) 249 | #define MSInstanceMessageHook3(type, _class, args...) MSMessage3_(MSRegister_, type, _class *, _class, ## args) 250 | #define MSInstanceMessageHook4(type, _class, args...) MSMessage4_(MSRegister_, type, _class *, _class, ## args) 251 | #define MSInstanceMessageHook5(type, _class, args...) MSMessage5_(MSRegister_, type, _class *, _class, ## args) 252 | #define MSInstanceMessageHook6(type, _class, args...) MSMessage6_(MSRegister_, type, _class *, _class, ## args) 253 | #define MSInstanceMessageHook7(type, _class, args...) MSMessage7_(MSRegister_, type, _class *, _class, ## args) 254 | #define MSInstanceMessageHook8(type, _class, args...) MSMessage8_(MSRegister_, type, _class *, _class, ## args) 255 | 256 | #define MSClassMessageHook0(type, _class, args...) MSMessage0_(MSRegister_, type, Class, $ ## _class, ## args) 257 | #define MSClassMessageHook1(type, _class, args...) MSMessage1_(MSRegister_, type, Class, $ ## _class, ## args) 258 | #define MSClassMessageHook2(type, _class, args...) MSMessage2_(MSRegister_, type, Class, $ ## _class, ## args) 259 | #define MSClassMessageHook3(type, _class, args...) MSMessage3_(MSRegister_, type, Class, $ ## _class, ## args) 260 | #define MSClassMessageHook4(type, _class, args...) MSMessage4_(MSRegister_, type, Class, $ ## _class, ## args) 261 | #define MSClassMessageHook5(type, _class, args...) MSMessage5_(MSRegister_, type, Class, $ ## _class, ## args) 262 | #define MSClassMessageHook6(type, _class, args...) MSMessage6_(MSRegister_, type, Class, $ ## _class, ## args) 263 | #define MSClassMessageHook7(type, _class, args...) MSMessage7_(MSRegister_, type, Class, $ ## _class, ## args) 264 | #define MSClassMessageHook8(type, _class, args...) MSMessage8_(MSRegister_, type, Class, $ ## _class, ## args) 265 | 266 | #define MSOldCall(args...) \ 267 | _old(self, _cmd, ## args) 268 | #define MSSuperCall(args...) \ 269 | _spr(& (struct objc_super) {self, class_getSuperclass(_cls)}, _cmd, ## args) 270 | 271 | #define MSIvarHook(type, name) \ 272 | type &name(MSHookIvar(self, #name)) 273 | 274 | #define MSClassHook(name) \ 275 | @class name; \ 276 | static Class $ ## name = objc_getClass(#name); 277 | #define MSMetaClassHook(name) \ 278 | @class name; \ 279 | static Class $$ ## name = object_getClass($ ## name); 280 | 281 | #endif/*__APPLE__*/ 282 | 283 | template 284 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) { 285 | return MSHookFunction( 286 | reinterpret_cast(symbol), 287 | reinterpret_cast(replace), 288 | reinterpret_cast(result) 289 | ); 290 | } 291 | 292 | template 293 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace) { 294 | return MSHookFunction(symbol, replace, reinterpret_cast(NULL)); 295 | } 296 | 297 | template 298 | static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) { 299 | value = reinterpret_cast(MSFindSymbol(image, name)); 300 | } 301 | 302 | template 303 | static inline void MSHookFunction(const char *name, Type_ *replace, Type_ **result = NULL) { 304 | Type_ *symbol; 305 | MSHookSymbol(symbol, name); 306 | return MSHookFunction(symbol, replace, result); 307 | } 308 | 309 | template 310 | static inline void MSHookFunction(MSImageRef image, const char *name, Type_ *replace, Type_ **result = NULL) { 311 | Type_ *symbol; 312 | MSHookSymbol(symbol, name, image); 313 | return MSHookFunction(symbol, replace, result); 314 | } 315 | 316 | #endif 317 | 318 | #ifdef __ANDROID__ 319 | 320 | // g++ versions before 4.7 define __cplusplus to 1 321 | // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773 322 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) 323 | 324 | template 325 | static inline void MSJavaHookMethod(JNIEnv *jni, jclass _class, jmethodID method, Type_ (*replace)(JNIEnv *, Kind_, Args_...), Type_ (**result)(JNIEnv *, Kind_, ...)) { 326 | return MSJavaHookMethod( 327 | jni, _class, method, 328 | reinterpret_cast(replace), 329 | reinterpret_cast(result) 330 | ); 331 | } 332 | 333 | #endif 334 | 335 | #ifdef __cplusplus 336 | 337 | static inline void MSAndroidGetPackage(JNIEnv *jni, jobject global, const char *name, jobject &local, jobject &loader) { 338 | jclass Context(jni->FindClass("android/content/Context")); 339 | jmethodID Context$createPackageContext(jni->GetMethodID(Context, "createPackageContext", "(Ljava/lang/String;I)Landroid/content/Context;")); 340 | jmethodID Context$getClassLoader(jni->GetMethodID(Context, "getClassLoader", "()Ljava/lang/ClassLoader;")); 341 | 342 | jstring string(jni->NewStringUTF(name)); 343 | local = jni->CallObjectMethod(global, Context$createPackageContext, string, 3); 344 | loader = jni->CallObjectMethod(local, Context$getClassLoader); 345 | } 346 | 347 | static inline jclass MSJavaFindClass(JNIEnv *jni, jobject loader, const char *name) { 348 | jclass Class(jni->FindClass("java/lang/Class")); 349 | jmethodID Class$forName(jni->GetStaticMethodID(Class, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;")); 350 | 351 | jstring string(jni->NewStringUTF(name)); 352 | jobject _class(jni->CallStaticObjectMethod(Class, Class$forName, string, JNI_TRUE, loader)); 353 | if (jni->ExceptionCheck()) 354 | return NULL; 355 | 356 | return reinterpret_cast(_class); 357 | } 358 | 359 | _disused static void MSJavaCleanWeak(void *data, JNIEnv *jni, void *value) { 360 | jni->DeleteWeakGlobalRef(reinterpret_cast(value)); 361 | } 362 | 363 | #endif 364 | 365 | #endif 366 | 367 | #define MSHook(type, name, args...) \ 368 | _disused static type (*_ ## name)(args); \ 369 | static type $ ## name(args) 370 | 371 | #define MSJavaHook(type, name, arg0, args...) \ 372 | _disused static type (*_ ## name)(JNIEnv *jni, arg0, ...); \ 373 | static type $ ## name(JNIEnv *jni, arg0, ## args) 374 | 375 | #ifdef __cplusplus 376 | #define MSHake(name) \ 377 | &$ ## name, &_ ## name 378 | #else 379 | #define MSHake(name) \ 380 | &$ ## name, (void **) &_ ## name 381 | #endif 382 | 383 | #define SubstrateConcat_(lhs, rhs) \ 384 | lhs ## rhs 385 | #define SubstrateConcat(lhs, rhs) \ 386 | SubstrateConcat_(lhs, rhs) 387 | 388 | #ifdef __APPLE__ 389 | #define SubstrateSection \ 390 | __attribute__((__section__("__TEXT, __substrate"))) 391 | #else 392 | #define SubstrateSection \ 393 | __attribute__((__section__(".substrate"))) 394 | #endif 395 | 396 | #ifdef __APPLE__ 397 | #define MSFilterCFBundleID "Filter:CFBundleID" 398 | #define MSFilterObjC_Class "Filter:ObjC.Class" 399 | #endif 400 | 401 | #define MSFilterLibrary "Filter:Library" 402 | #define MSFilterExecutable "Filter:Executable" 403 | 404 | #define MSConfig(name, value) \ 405 | extern const char SubstrateConcat(_substrate_, __LINE__)[] SubstrateSection = name "=" value; 406 | 407 | #ifdef __cplusplus 408 | #define MSInitialize \ 409 | static void _MSInitialize(void); \ 410 | namespace { static class $MSInitialize { public: _finline $MSInitialize() { \ 411 | _MSInitialize(); \ 412 | } } $MSInitialize; } \ 413 | static void _MSInitialize() 414 | #else 415 | #define MSInitialize \ 416 | __attribute__((__constructor__)) static void _MSInitialize(void) 417 | #endif 418 | 419 | #define Foundation_f "/System/Library/Frameworks/Foundation.framework/Foundation" 420 | #define UIKit_f "/System/Library/Frameworks/UIKit.framework/UIKit" 421 | #define JavaScriptCore_f "/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore" 422 | #define IOKit_f "/System/Library/Frameworks/IOKit.framework/IOKit" 423 | 424 | #endif//SUBSTRATE_H_ 425 | -------------------------------------------------------------------------------- /lib/libactionmenu.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kokoabim/iOSOpenDev/020e76695ec6efecf941a100b147a50a6b9e6495/lib/libactionmenu.dylib -------------------------------------------------------------------------------- /lib/libactivator.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kokoabim/iOSOpenDev/020e76695ec6efecf941a100b147a50a6b9e6495/lib/libactivator.dylib -------------------------------------------------------------------------------- /lib/libsubstrate.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kokoabim/iOSOpenDev/020e76695ec6efecf941a100b147a50a6b9e6495/lib/libsubstrate.dylib --------------------------------------------------------------------------------