├── LICENSE ├── LogGuru.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── Travis.xcuserdatad │ └── xcschemes │ ├── LogGuru.xcscheme │ └── xcschememanagement.plist ├── LogGuru ├── AppDelegate.h ├── AppDelegate.m ├── AppIcon.icns ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ └── MainMenu.xib ├── FIRUSBLoger.h ├── FIRUSBLoger.m ├── Info.plist ├── MobileDevice.h └── main.m ├── LogGuruTests ├── Info.plist └── LogGuruTests.m └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LogGuru.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1F9612BE1DB8938100DE647E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9612BD1DB8938100DE647E /* AppDelegate.m */; }; 11 | 1F9612C11DB8938100DE647E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9612C01DB8938100DE647E /* main.m */; }; 12 | 1F9612C31DB8938100DE647E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1F9612C21DB8938100DE647E /* Assets.xcassets */; }; 13 | 1F9612C61DB8938100DE647E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1F9612C41DB8938100DE647E /* MainMenu.xib */; }; 14 | 1F9612D11DB8938100DE647E /* LogGuruTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9612D01DB8938100DE647E /* LogGuruTests.m */; }; 15 | 1F9612DD1DB8946100DE647E /* MobileDevice.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F9612DC1DB8946100DE647E /* MobileDevice.framework */; }; 16 | 1F9612DE1DB8946100DE647E /* MobileDevice.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F9612DC1DB8946100DE647E /* MobileDevice.framework */; }; 17 | 1F9612E11DB8B04F00DE647E /* FIRUSBLoger.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9612E01DB8B04F00DE647E /* FIRUSBLoger.m */; }; 18 | 1F9612E21DB8B04F00DE647E /* FIRUSBLoger.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9612E01DB8B04F00DE647E /* FIRUSBLoger.m */; }; 19 | 1F9612E41DB8B13000DE647E /* AppIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 1F9612E31DB8B13000DE647E /* AppIcon.icns */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 1F9612CD1DB8938100DE647E /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 1F9612B11DB8938100DE647E /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 1F9612B81DB8938100DE647E; 28 | remoteInfo = LogGuru; 29 | }; 30 | /* End PBXContainerItemProxy section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 1F9612B91DB8938100DE647E /* LogGuru.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LogGuru.app; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 1F9612BC1DB8938100DE647E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 35 | 1F9612BD1DB8938100DE647E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 36 | 1F9612C01DB8938100DE647E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 37 | 1F9612C21DB8938100DE647E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 38 | 1F9612C51DB8938100DE647E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 39 | 1F9612C71DB8938100DE647E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | 1F9612CC1DB8938100DE647E /* LogGuruTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LogGuruTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 1F9612D01DB8938100DE647E /* LogGuruTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LogGuruTests.m; sourceTree = ""; }; 42 | 1F9612D21DB8938100DE647E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | 1F9612DB1DB8944C00DE647E /* MobileDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MobileDevice.h; sourceTree = ""; }; 44 | 1F9612DC1DB8946100DE647E /* MobileDevice.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileDevice.framework; path = ../../../../../System/Library/PrivateFrameworks/MobileDevice.framework; sourceTree = ""; }; 45 | 1F9612DF1DB8B04F00DE647E /* FIRUSBLoger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRUSBLoger.h; sourceTree = ""; }; 46 | 1F9612E01DB8B04F00DE647E /* FIRUSBLoger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRUSBLoger.m; sourceTree = ""; }; 47 | 1F9612E31DB8B13000DE647E /* AppIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon.icns; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 1F9612B61DB8938100DE647E /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | 1F9612DD1DB8946100DE647E /* MobileDevice.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | 1F9612C91DB8938100DE647E /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | 1F9612DE1DB8946100DE647E /* MobileDevice.framework in Frameworks */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXFrameworksBuildPhase section */ 68 | 69 | /* Begin PBXGroup section */ 70 | 1F9612B01DB8938100DE647E = { 71 | isa = PBXGroup; 72 | children = ( 73 | 1F9612BB1DB8938100DE647E /* LogGuru */, 74 | 1F9612CF1DB8938100DE647E /* LogGuruTests */, 75 | 1F9612BA1DB8938100DE647E /* Products */, 76 | ); 77 | sourceTree = ""; 78 | }; 79 | 1F9612BA1DB8938100DE647E /* Products */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 1F9612B91DB8938100DE647E /* LogGuru.app */, 83 | 1F9612CC1DB8938100DE647E /* LogGuruTests.xctest */, 84 | ); 85 | name = Products; 86 | sourceTree = ""; 87 | }; 88 | 1F9612BB1DB8938100DE647E /* LogGuru */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 1F9612BC1DB8938100DE647E /* AppDelegate.h */, 92 | 1F9612BD1DB8938100DE647E /* AppDelegate.m */, 93 | 1F9612DF1DB8B04F00DE647E /* FIRUSBLoger.h */, 94 | 1F9612E01DB8B04F00DE647E /* FIRUSBLoger.m */, 95 | 1F9612BF1DB8938100DE647E /* Supporting Files */, 96 | ); 97 | path = LogGuru; 98 | sourceTree = ""; 99 | }; 100 | 1F9612BF1DB8938100DE647E /* Supporting Files */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 1F9612C21DB8938100DE647E /* Assets.xcassets */, 104 | 1F9612C71DB8938100DE647E /* Info.plist */, 105 | 1F9612C41DB8938100DE647E /* MainMenu.xib */, 106 | 1F9612E31DB8B13000DE647E /* AppIcon.icns */, 107 | 1F9612DC1DB8946100DE647E /* MobileDevice.framework */, 108 | 1F9612DB1DB8944C00DE647E /* MobileDevice.h */, 109 | 1F9612C01DB8938100DE647E /* main.m */, 110 | ); 111 | name = "Supporting Files"; 112 | sourceTree = ""; 113 | }; 114 | 1F9612CF1DB8938100DE647E /* LogGuruTests */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 1F9612D01DB8938100DE647E /* LogGuruTests.m */, 118 | 1F9612D21DB8938100DE647E /* Info.plist */, 119 | ); 120 | path = LogGuruTests; 121 | sourceTree = ""; 122 | }; 123 | /* End PBXGroup section */ 124 | 125 | /* Begin PBXNativeTarget section */ 126 | 1F9612B81DB8938100DE647E /* LogGuru */ = { 127 | isa = PBXNativeTarget; 128 | buildConfigurationList = 1F9612D51DB8938100DE647E /* Build configuration list for PBXNativeTarget "LogGuru" */; 129 | buildPhases = ( 130 | 1F9612B51DB8938100DE647E /* Sources */, 131 | 1F9612B61DB8938100DE647E /* Frameworks */, 132 | 1F9612B71DB8938100DE647E /* Resources */, 133 | ); 134 | buildRules = ( 135 | ); 136 | dependencies = ( 137 | ); 138 | name = LogGuru; 139 | productName = LogGuru; 140 | productReference = 1F9612B91DB8938100DE647E /* LogGuru.app */; 141 | productType = "com.apple.product-type.application"; 142 | }; 143 | 1F9612CB1DB8938100DE647E /* LogGuruTests */ = { 144 | isa = PBXNativeTarget; 145 | buildConfigurationList = 1F9612D81DB8938100DE647E /* Build configuration list for PBXNativeTarget "LogGuruTests" */; 146 | buildPhases = ( 147 | 1F9612C81DB8938100DE647E /* Sources */, 148 | 1F9612C91DB8938100DE647E /* Frameworks */, 149 | 1F9612CA1DB8938100DE647E /* Resources */, 150 | ); 151 | buildRules = ( 152 | ); 153 | dependencies = ( 154 | 1F9612CE1DB8938100DE647E /* PBXTargetDependency */, 155 | ); 156 | name = LogGuruTests; 157 | productName = LogGuruTests; 158 | productReference = 1F9612CC1DB8938100DE647E /* LogGuruTests.xctest */; 159 | productType = "com.apple.product-type.bundle.unit-test"; 160 | }; 161 | /* End PBXNativeTarget section */ 162 | 163 | /* Begin PBXProject section */ 164 | 1F9612B11DB8938100DE647E /* Project object */ = { 165 | isa = PBXProject; 166 | attributes = { 167 | LastUpgradeCheck = 0730; 168 | ORGANIZATIONNAME = im.fir.logguru; 169 | TargetAttributes = { 170 | 1F9612B81DB8938100DE647E = { 171 | CreatedOnToolsVersion = 7.3.1; 172 | }; 173 | 1F9612CB1DB8938100DE647E = { 174 | CreatedOnToolsVersion = 7.3.1; 175 | TestTargetID = 1F9612B81DB8938100DE647E; 176 | }; 177 | }; 178 | }; 179 | buildConfigurationList = 1F9612B41DB8938100DE647E /* Build configuration list for PBXProject "LogGuru" */; 180 | compatibilityVersion = "Xcode 3.2"; 181 | developmentRegion = English; 182 | hasScannedForEncodings = 0; 183 | knownRegions = ( 184 | en, 185 | Base, 186 | ); 187 | mainGroup = 1F9612B01DB8938100DE647E; 188 | productRefGroup = 1F9612BA1DB8938100DE647E /* Products */; 189 | projectDirPath = ""; 190 | projectRoot = ""; 191 | targets = ( 192 | 1F9612B81DB8938100DE647E /* LogGuru */, 193 | 1F9612CB1DB8938100DE647E /* LogGuruTests */, 194 | ); 195 | }; 196 | /* End PBXProject section */ 197 | 198 | /* Begin PBXResourcesBuildPhase section */ 199 | 1F9612B71DB8938100DE647E /* Resources */ = { 200 | isa = PBXResourcesBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | 1F9612C31DB8938100DE647E /* Assets.xcassets in Resources */, 204 | 1F9612C61DB8938100DE647E /* MainMenu.xib in Resources */, 205 | 1F9612E41DB8B13000DE647E /* AppIcon.icns in Resources */, 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | }; 209 | 1F9612CA1DB8938100DE647E /* Resources */ = { 210 | isa = PBXResourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | }; 216 | /* End PBXResourcesBuildPhase section */ 217 | 218 | /* Begin PBXSourcesBuildPhase section */ 219 | 1F9612B51DB8938100DE647E /* Sources */ = { 220 | isa = PBXSourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | 1F9612C11DB8938100DE647E /* main.m in Sources */, 224 | 1F9612BE1DB8938100DE647E /* AppDelegate.m in Sources */, 225 | 1F9612E11DB8B04F00DE647E /* FIRUSBLoger.m in Sources */, 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | }; 229 | 1F9612C81DB8938100DE647E /* Sources */ = { 230 | isa = PBXSourcesBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | 1F9612E21DB8B04F00DE647E /* FIRUSBLoger.m in Sources */, 234 | 1F9612D11DB8938100DE647E /* LogGuruTests.m in Sources */, 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | /* End PBXSourcesBuildPhase section */ 239 | 240 | /* Begin PBXTargetDependency section */ 241 | 1F9612CE1DB8938100DE647E /* PBXTargetDependency */ = { 242 | isa = PBXTargetDependency; 243 | target = 1F9612B81DB8938100DE647E /* LogGuru */; 244 | targetProxy = 1F9612CD1DB8938100DE647E /* PBXContainerItemProxy */; 245 | }; 246 | /* End PBXTargetDependency section */ 247 | 248 | /* Begin PBXVariantGroup section */ 249 | 1F9612C41DB8938100DE647E /* MainMenu.xib */ = { 250 | isa = PBXVariantGroup; 251 | children = ( 252 | 1F9612C51DB8938100DE647E /* Base */, 253 | ); 254 | name = MainMenu.xib; 255 | sourceTree = ""; 256 | }; 257 | /* End PBXVariantGroup section */ 258 | 259 | /* Begin XCBuildConfiguration section */ 260 | 1F9612D31DB8938100DE647E /* Debug */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ALWAYS_SEARCH_USER_PATHS = NO; 264 | CLANG_ANALYZER_NONNULL = YES; 265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 266 | CLANG_CXX_LIBRARY = "libc++"; 267 | CLANG_ENABLE_MODULES = YES; 268 | CLANG_ENABLE_OBJC_ARC = YES; 269 | CLANG_WARN_BOOL_CONVERSION = YES; 270 | CLANG_WARN_CONSTANT_CONVERSION = YES; 271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 272 | CLANG_WARN_EMPTY_BODY = YES; 273 | CLANG_WARN_ENUM_CONVERSION = YES; 274 | CLANG_WARN_INT_CONVERSION = YES; 275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 276 | CLANG_WARN_UNREACHABLE_CODE = YES; 277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 278 | CODE_SIGN_IDENTITY = "-"; 279 | COPY_PHASE_STRIP = NO; 280 | DEBUG_INFORMATION_FORMAT = dwarf; 281 | ENABLE_STRICT_OBJC_MSGSEND = YES; 282 | ENABLE_TESTABILITY = YES; 283 | GCC_C_LANGUAGE_STANDARD = gnu99; 284 | GCC_DYNAMIC_NO_PIC = NO; 285 | GCC_NO_COMMON_BLOCKS = YES; 286 | GCC_OPTIMIZATION_LEVEL = 0; 287 | GCC_PREPROCESSOR_DEFINITIONS = ( 288 | "DEBUG=1", 289 | "$(inherited)", 290 | ); 291 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 292 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 293 | GCC_WARN_UNDECLARED_SELECTOR = YES; 294 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 295 | GCC_WARN_UNUSED_FUNCTION = YES; 296 | GCC_WARN_UNUSED_VARIABLE = YES; 297 | MACOSX_DEPLOYMENT_TARGET = 10.12; 298 | MTL_ENABLE_DEBUG_INFO = YES; 299 | ONLY_ACTIVE_ARCH = YES; 300 | SDKROOT = macosx; 301 | }; 302 | name = Debug; 303 | }; 304 | 1F9612D41DB8938100DE647E /* Release */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | ALWAYS_SEARCH_USER_PATHS = NO; 308 | CLANG_ANALYZER_NONNULL = YES; 309 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 310 | CLANG_CXX_LIBRARY = "libc++"; 311 | CLANG_ENABLE_MODULES = YES; 312 | CLANG_ENABLE_OBJC_ARC = YES; 313 | CLANG_WARN_BOOL_CONVERSION = YES; 314 | CLANG_WARN_CONSTANT_CONVERSION = YES; 315 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 316 | CLANG_WARN_EMPTY_BODY = YES; 317 | CLANG_WARN_ENUM_CONVERSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN_UNREACHABLE_CODE = YES; 321 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 322 | CODE_SIGN_IDENTITY = "-"; 323 | COPY_PHASE_STRIP = NO; 324 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 325 | ENABLE_NS_ASSERTIONS = NO; 326 | ENABLE_STRICT_OBJC_MSGSEND = YES; 327 | GCC_C_LANGUAGE_STANDARD = gnu99; 328 | GCC_NO_COMMON_BLOCKS = YES; 329 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 330 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 331 | GCC_WARN_UNDECLARED_SELECTOR = YES; 332 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 333 | GCC_WARN_UNUSED_FUNCTION = YES; 334 | GCC_WARN_UNUSED_VARIABLE = YES; 335 | MACOSX_DEPLOYMENT_TARGET = 10.12; 336 | MTL_ENABLE_DEBUG_INFO = NO; 337 | SDKROOT = macosx; 338 | }; 339 | name = Release; 340 | }; 341 | 1F9612D61DB8938100DE647E /* Debug */ = { 342 | isa = XCBuildConfiguration; 343 | buildSettings = { 344 | COMBINE_HIDPI_IMAGES = YES; 345 | FRAMEWORK_SEARCH_PATHS = ( 346 | "$(inherited)", 347 | "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", 348 | ); 349 | INFOPLIST_FILE = LogGuru/Info.plist; 350 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 351 | MACOSX_DEPLOYMENT_TARGET = 10.11; 352 | PRODUCT_BUNDLE_IDENTIFIER = im.fir.logguru; 353 | PRODUCT_NAME = "$(TARGET_NAME)"; 354 | }; 355 | name = Debug; 356 | }; 357 | 1F9612D71DB8938100DE647E /* Release */ = { 358 | isa = XCBuildConfiguration; 359 | buildSettings = { 360 | COMBINE_HIDPI_IMAGES = YES; 361 | FRAMEWORK_SEARCH_PATHS = ( 362 | "$(inherited)", 363 | "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", 364 | ); 365 | INFOPLIST_FILE = LogGuru/Info.plist; 366 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 367 | MACOSX_DEPLOYMENT_TARGET = 10.11; 368 | PRODUCT_BUNDLE_IDENTIFIER = im.fir.logguru; 369 | PRODUCT_NAME = "$(TARGET_NAME)"; 370 | }; 371 | name = Release; 372 | }; 373 | 1F9612D91DB8938100DE647E /* Debug */ = { 374 | isa = XCBuildConfiguration; 375 | buildSettings = { 376 | BUNDLE_LOADER = "$(TEST_HOST)"; 377 | COMBINE_HIDPI_IMAGES = YES; 378 | FRAMEWORK_SEARCH_PATHS = ( 379 | "$(inherited)", 380 | "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", 381 | ); 382 | INFOPLIST_FILE = LogGuruTests/Info.plist; 383 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 384 | MACOSX_DEPLOYMENT_TARGET = 10.11; 385 | PRODUCT_BUNDLE_IDENTIFIER = fir.im.LogGuruTests; 386 | PRODUCT_NAME = "$(TARGET_NAME)"; 387 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LogGuru.app/Contents/MacOS/LogGuru"; 388 | }; 389 | name = Debug; 390 | }; 391 | 1F9612DA1DB8938100DE647E /* Release */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | BUNDLE_LOADER = "$(TEST_HOST)"; 395 | COMBINE_HIDPI_IMAGES = YES; 396 | FRAMEWORK_SEARCH_PATHS = ( 397 | "$(inherited)", 398 | "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", 399 | ); 400 | INFOPLIST_FILE = LogGuruTests/Info.plist; 401 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 402 | MACOSX_DEPLOYMENT_TARGET = 10.11; 403 | PRODUCT_BUNDLE_IDENTIFIER = fir.im.LogGuruTests; 404 | PRODUCT_NAME = "$(TARGET_NAME)"; 405 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LogGuru.app/Contents/MacOS/LogGuru"; 406 | }; 407 | name = Release; 408 | }; 409 | /* End XCBuildConfiguration section */ 410 | 411 | /* Begin XCConfigurationList section */ 412 | 1F9612B41DB8938100DE647E /* Build configuration list for PBXProject "LogGuru" */ = { 413 | isa = XCConfigurationList; 414 | buildConfigurations = ( 415 | 1F9612D31DB8938100DE647E /* Debug */, 416 | 1F9612D41DB8938100DE647E /* Release */, 417 | ); 418 | defaultConfigurationIsVisible = 0; 419 | defaultConfigurationName = Release; 420 | }; 421 | 1F9612D51DB8938100DE647E /* Build configuration list for PBXNativeTarget "LogGuru" */ = { 422 | isa = XCConfigurationList; 423 | buildConfigurations = ( 424 | 1F9612D61DB8938100DE647E /* Debug */, 425 | 1F9612D71DB8938100DE647E /* Release */, 426 | ); 427 | defaultConfigurationIsVisible = 0; 428 | }; 429 | 1F9612D81DB8938100DE647E /* Build configuration list for PBXNativeTarget "LogGuruTests" */ = { 430 | isa = XCConfigurationList; 431 | buildConfigurations = ( 432 | 1F9612D91DB8938100DE647E /* Debug */, 433 | 1F9612DA1DB8938100DE647E /* Release */, 434 | ); 435 | defaultConfigurationIsVisible = 0; 436 | }; 437 | /* End XCConfigurationList section */ 438 | }; 439 | rootObject = 1F9612B11DB8938100DE647E /* Project object */; 440 | } 441 | -------------------------------------------------------------------------------- /LogGuru.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LogGuru.xcodeproj/xcuserdata/Travis.xcuserdatad/xcschemes/LogGuru.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /LogGuru.xcodeproj/xcuserdata/Travis.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | LogGuru.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1F9612B81DB8938100DE647E 16 | 17 | primary 18 | 19 | 20 | 1F9612CB1DB8938100DE647E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /LogGuru/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // FIRForMac 4 | // 5 | // Created by Travis on 14-9-21. 6 | // Copyright (c) 2014年 Fly It Remotely International Corporation. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /LogGuru/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // FIRForMac 4 | // 5 | // Created by Travis on 14-9-21. 6 | // Copyright (c) 2014年 Fly It Remotely International Corporation. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "FIRUSBLoger.h" 11 | 12 | 13 | @interface AppDelegate () 14 | 15 | @property (weak) IBOutlet NSTextField *statView; 16 | @property (unsafe_unretained) IBOutlet NSTextView *logView; 17 | @property (weak) IBOutlet NSWindow *window; 18 | 19 | @property (strong) FIRUSBLoger *logger; 20 | 21 | @property (strong) NSMutableArray *blockProcesses; 22 | 23 | @property (strong) NSMutableArray *lightProcesses; 24 | 25 | @property(assign) BOOL showDeviceName; 26 | @property(assign) BOOL showDate; 27 | @property(assign) BOOL paused; 28 | 29 | @end 30 | 31 | @implementation AppDelegate 32 | 33 | - (IBAction)cleanLog:(id)sender { 34 | if (self.logView.textStorage.length>0) { 35 | [self.logView.textStorage deleteCharactersInRange:NSMakeRange(0, self.logView.textStorage.length-1)]; 36 | } 37 | } 38 | 39 | - (IBAction)pauseLog:(id)sender { 40 | self.paused=!self.paused; 41 | 42 | NSToolbarItem* item=sender; 43 | if(item){ 44 | if(self.paused){ 45 | item.label=@"Log"; 46 | item.image=[NSImage imageNamed:@"NSPlayTemplate"]; 47 | }else{ 48 | item.label=@"Pause"; 49 | item.image=[NSImage imageNamed:@"NSPauseTemplate"]; 50 | } 51 | } 52 | 53 | } 54 | 55 | 56 | 57 | -(void)logMsg:(NSDictionary*)logInfo{ 58 | //printf("%s",[msg UTF8String]); 59 | 60 | if(self.paused) { 61 | return; 62 | } 63 | 64 | if ([self.blockProcesses containsObject:logInfo.process]) { 65 | return; 66 | } 67 | 68 | if ([logInfo.process isEqualToString:@"syslog_relay"]) { 69 | if ([logInfo.log rangeOfString:@"Start"].length>0 && self.logView.textStorage.layoutManagers) { 70 | [self.logView.textStorage appendAttributedString: 71 | [[NSAttributedString alloc] initWithString:@"────── ✂︎ ────── ✂︎ ────── ✂︎ ────── ✂︎ ────── ✂︎ ──────\n" 72 | attributes:@{ 73 | 74 | NSFontAttributeName:[NSFont fontWithName:@"Menlo" size:16] 75 | 76 | }] 77 | 78 | ]; 79 | } 80 | 81 | //[self.logView setString:@""]; 82 | //[self.logView.textStorage deleteCharactersInRange:NSMakeRange(0, self.logView.textStorage.length-1)]; 83 | // [self.logView.textStorage appendAttributedString: 84 | // [[NSAttributedString alloc] initWithString:@"FIR.im Log Service Start...\n"] 85 | // ]; 86 | }else{ 87 | NSColor *dateBg,*dateFg,*processBg,*processFg,*logBg,*logFg; 88 | 89 | //date 90 | NSInteger level=logInfo.level; 91 | switch (level) { 92 | case LogNotice: 93 | case LogAll: 94 | dateBg=[NSColor clearColor]; 95 | dateFg=[NSColor blackColor]; 96 | break; 97 | case LogWarning: 98 | dateBg=[NSColor orangeColor]; 99 | dateFg=[NSColor blueColor]; 100 | break; 101 | case LogError: 102 | dateBg=[NSColor redColor]; 103 | dateBg=[NSColor whiteColor]; 104 | break; 105 | } 106 | 107 | if (self.showDeviceName) { 108 | [self.logView.textStorage appendAttributedString: 109 | [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"[%@]",logInfo.device] 110 | attributes:@{ 111 | 112 | NSFontAttributeName:[NSFont fontWithName:@"Menlo" size:13] 113 | 114 | }] 115 | 116 | ]; 117 | } 118 | 119 | 120 | if (self.showDate) { 121 | [self.logView.textStorage appendAttributedString: 122 | [[NSAttributedString alloc] initWithString:[logInfo.date substringFromIndex:7] attributes:@{ 123 | NSBackgroundColorAttributeName:dateBg, 124 | NSForegroundColorAttributeName:dateFg, 125 | NSFontAttributeName:[NSFont fontWithName:@"Menlo" size:13] 126 | }] 127 | 128 | ]; 129 | } 130 | 131 | 132 | //process 133 | 134 | 135 | processFg=[NSColor brownColor]; 136 | processBg=[NSColor whiteColor]; 137 | 138 | [self.logView.textStorage appendAttributedString: 139 | [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@" %@➜",logInfo.process] attributes:@{ 140 | NSBackgroundColorAttributeName:processBg, 141 | NSForegroundColorAttributeName:processFg, 142 | NSFontAttributeName:[NSFont boldSystemFontOfSize:14] 143 | }] 144 | 145 | ]; 146 | 147 | 148 | 149 | if ([self.lightProcesses containsObject:logInfo.process]) { 150 | logBg=[NSColor colorWithRed:245/255.0 green:171/255.0 blue:53/255.0 alpha:1]; 151 | logFg=[NSColor whiteColor]; 152 | }else{ 153 | logBg=[NSColor whiteColor]; 154 | logFg=[NSColor lightGrayColor]; 155 | } 156 | 157 | [self.logView.textStorage appendAttributedString: 158 | [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n",logInfo.log] 159 | attributes:@{ 160 | NSBackgroundColorAttributeName:logBg, 161 | NSForegroundColorAttributeName:logFg, 162 | NSFontAttributeName:[NSFont fontWithName:@"Menlo" size:13] 163 | }] 164 | 165 | ]; 166 | 167 | 168 | [self.logView scrollRangeToVisible: NSMakeRange(self.logView.textStorage.length, 0)]; 169 | 170 | 171 | } 172 | 173 | } 174 | 175 | -(void)logStat:(NSString*)msg{ 176 | [self.logView.textStorage appendAttributedString: 177 | [[NSAttributedString alloc] initWithString:[msg stringByAppendingString:@"\n"] attributes:@{ 178 | NSBackgroundColorAttributeName:[NSColor grayColor], 179 | NSForegroundColorAttributeName:[NSColor blackColor] 180 | }] 181 | ]; 182 | } 183 | 184 | -(void)awakeFromNib{ 185 | self.window.backgroundColor=[NSColor whiteColor]; 186 | //self.window.titlebarAppearsTransparent=YES; 187 | } 188 | 189 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 190 | 191 | //TODO: cmd+k 清除 明林清@搜狐 18:16:13 192 | 193 | NSUserDefaults *df=[NSUserDefaults standardUserDefaults]; 194 | 195 | self.showDate=![df boolForKey:@"hideDate"]; 196 | self.showDeviceName=[df boolForKey:@"showDeviceName"]; 197 | 198 | //highlight 199 | // 200 | 201 | self.lightProcesses=[NSMutableArray arrayWithObjects: 202 | @"amfid", 203 | @"itunesstored", 204 | @"installd", 205 | @"profiled", 206 | //@"ReportCrash", 207 | nil]; 208 | 209 | self.blockProcesses=[NSMutableArray arrayWithObjects: 210 | @"kernel", 211 | @"atc", 212 | @"lsd", 213 | @"assetsd", 214 | @"assistant_service", 215 | @"assertiond", 216 | @"backboardd", 217 | @"cloudd", 218 | @"calaccessd", 219 | @"callservicesd", 220 | @"configd", 221 | @"discoveryd", 222 | @"dataaccessd", 223 | @"familycircled", 224 | @"geod", 225 | @"geocorrectiond", 226 | @"healthd", 227 | @"kbd", 228 | @"locationd", 229 | @"lockdownd", 230 | @"identityservicesd", 231 | @"mediaserverd", 232 | @"mstreamd", 233 | @"networkd", 234 | @"nfcd", 235 | @"sharingd", 236 | @"seld", 237 | @"searchd", 238 | @"safarifetcherd", 239 | @"syncdefaultsd", 240 | @"pipelined", 241 | @"pppd", 242 | @"tccd", 243 | @"timed", 244 | @"ubd", 245 | @"wifid", 246 | @"CommCenter", 247 | @"CallHistorySyncHelper", 248 | @"InCallService", 249 | @"SpringBoard", 250 | @"WirelessRadioManagerd", 251 | @"MessagesNotificationViewService", 252 | @"com.apple.AppleHDQGasGauge", 253 | @"com.apple.voicetrigger.voicetriggerservice", 254 | @"com.apple.WebKit.WebContent", 255 | 256 | @"AppStore", 257 | @"MobileMail", 258 | @"MobileCal", 259 | @"MobileSafari", 260 | @"MobileSMS", 261 | @"Preferences", 262 | 263 | @"UserEventAgent", 264 | nil]; 265 | 266 | [[NSNotificationCenter defaultCenter] addObserverForName:@"DeviceLog" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { 267 | [self logMsg:note.userInfo]; 268 | }]; 269 | 270 | [[NSNotificationCenter defaultCenter] addObserverForName:@"DeviceChange" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { 271 | 272 | NSDictionary *info=note.userInfo; 273 | 274 | BOOL connect=[info[@"connect"] boolValue]; 275 | int count=[info[@"count"] intValue]; 276 | NSString *udid=info[@"udid"]; 277 | 278 | NSString *stat; 279 | if (count>0) { 280 | stat=[NSString stringWithFormat:@"%d 台设备已连接",count]; 281 | }else{ 282 | stat=@"等待设备连接"; 283 | } 284 | [self.statView setStringValue:stat]; 285 | 286 | [self logStat:[NSString stringWithFormat:@"设备:%@ %@",udid,connect?@"已连接":@"已断开"]]; 287 | 288 | }]; 289 | 290 | self.logger=[[FIRUSBLoger alloc] init]; 291 | [self.logger start]; 292 | } 293 | 294 | - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag { 295 | 296 | [self.window makeKeyAndOrderFront:self]; 297 | 298 | return YES; 299 | } 300 | 301 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 302 | 303 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 304 | 305 | self.logger=nil; 306 | } 307 | - (IBAction)openAbout:(id)sender { 308 | [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://fir.im?utm_source=mac_log_guru"]]; 309 | } 310 | 311 | 312 | 313 | @end 314 | -------------------------------------------------------------------------------- /LogGuru/AppIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PGYER/LogGuru/e291c4cf6d7d259b79f0b2b872698d5d02debb26/LogGuru/AppIcon.icns -------------------------------------------------------------------------------- /LogGuru/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /LogGuru/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | Default 364 | 365 | 366 | 367 | 368 | 369 | 370 | Left to Right 371 | 372 | 373 | 374 | 375 | 376 | 377 | Right to Left 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | Default 389 | 390 | 391 | 392 | 393 | 394 | 395 | Left to Right 396 | 397 | 398 | 399 | 400 | 401 | 402 | Right to Left 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | -------------------------------------------------------------------------------- /LogGuru/FIRUSBLoger.h: -------------------------------------------------------------------------------- 1 | // 2 | // FIRUSBLoger.h 3 | // FIR.im 4 | // 5 | // Created by Travis on 14/12/24. 6 | // Copyright (c) 2014年 Fly It Remotely International Corporation. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum : NSInteger { 12 | LogAll = 0, 13 | LogNotice, 14 | LogWarning, 15 | LogError 16 | } LogLevel; 17 | 18 | 19 | @interface NSDictionary(LogInfo) 20 | @property(readonly) LogLevel level; 21 | @property(readonly) NSString *date; 22 | @property(readonly) NSString *log; 23 | @property(readonly) NSString *process; 24 | @property(readonly) NSString *device; 25 | 26 | @end 27 | 28 | @interface FIRUSBLoger : NSObject 29 | 30 | @property(nonatomic, assign) LogLevel level; 31 | 32 | +(NSDictionary*)logInfo:(NSString*)msg; 33 | -(int)start; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /LogGuru/FIRUSBLoger.m: -------------------------------------------------------------------------------- 1 | // 2 | // FIRUSBLoger.m 3 | // FIR.im 4 | // 5 | // Created by Travis on 14/12/24. 6 | // Copyright (c) 2014年 Fly It Remotely International Corporation. All rights reserved. 7 | // 8 | 9 | #import "FIRUSBLoger.h" 10 | #import "MobileDevice.h" 11 | #import 12 | 13 | 14 | typedef struct { 15 | service_conn_t connection; 16 | CFSocketRef socket; 17 | CFRunLoopSourceRef source; 18 | } DeviceConsoleConnection; 19 | 20 | static CFMutableDictionaryRef liveConnections; 21 | 22 | static NSRegularExpression *reg; 23 | 24 | static int LogLevelLimit; 25 | 26 | static void SocketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) 27 | { 28 | // Skip null bytes 29 | ssize_t length = CFDataGetLength(data); 30 | const char *buffer = (const char *)CFDataGetBytePtr(data); 31 | while (length) { 32 | while (*buffer == '\0') { 33 | buffer++; 34 | length--; 35 | if (length == 0) 36 | return; 37 | } 38 | size_t extentLength = 0; 39 | while ((buffer[extentLength] != '\0') && extentLength != length) { 40 | extentLength++; 41 | } 42 | 43 | if (extentLength>=3) { 44 | NSString * msg=[[NSString alloc] initWithBytes:buffer length:extentLength encoding:NSUTF8StringEncoding]; 45 | if([msg rangeOfString:@"libxpc.dylib"].length==0){ 46 | NSArray *matches= [reg matchesInString:msg options:0 range:NSMakeRange(0, msg.length-1)]; 47 | if (matches) { 48 | NSTextCheckingResult *restult=[matches lastObject]; 49 | if (restult.numberOfRanges==6) { 50 | int lv=LogAll; 51 | NSString *level=[msg substringWithRange:[restult rangeAtIndex:4]]; 52 | if ([level isEqualTo:@"Notice"]) { 53 | lv=LogNotice; 54 | }else if ([level isEqualTo:@"Warning"]) { 55 | lv=LogWarning; 56 | }else if ([level isEqualTo:@"Error"]) { 57 | lv=LogNotice; 58 | } 59 | 60 | if (lv>=LogLevelLimit) { 61 | NSDictionary *info=@{ 62 | @"date" :[msg substringWithRange:[restult rangeAtIndex:1]], 63 | @"device" :[msg substringWithRange:[restult rangeAtIndex:2]], 64 | @"process" :[msg substringWithRange:[restult rangeAtIndex:3]], 65 | @"level" :@(lv), 66 | @"log" :[msg substringWithRange:[restult rangeAtIndex:5]], 67 | }; 68 | 69 | 70 | 71 | [[NSNotificationCenter defaultCenter] postNotificationName:@"DeviceLog" object:nil userInfo:info]; 72 | } 73 | 74 | } 75 | } 76 | 77 | } 78 | } 79 | 80 | length -= extentLength; 81 | buffer += extentLength; 82 | } 83 | } 84 | 85 | static void DeviceNotificationCallback(am_device_notification_callback_info *info, void *unknown) 86 | { 87 | struct am_device *device = info->dev; 88 | CFStringRef deviceId = AMDeviceCopyDeviceIdentifier(device); 89 | NSString *udid=[(__bridge NSString*)deviceId copy]; 90 | CFRelease(deviceId); 91 | 92 | switch (info->msg) { 93 | case ADNCI_MSG_CONNECTED: { 94 | // 95 | if (AMDeviceConnect(device) == MDERR_OK) { 96 | if (AMDeviceIsPaired(device) && (AMDeviceValidatePairing(device) == MDERR_OK)) { 97 | if (AMDeviceStartSession(device) == MDERR_OK) { 98 | service_conn_t connection; 99 | if (AMDeviceStartService(device, AMSVC_SYSLOG_RELAY, &connection, NULL) == MDERR_OK) { 100 | CFSocketRef socket = CFSocketCreateWithNative(kCFAllocatorDefault, connection, kCFSocketDataCallBack, SocketCallback, NULL); 101 | if (socket) { 102 | CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0); 103 | if (source) { 104 | CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); 105 | AMDeviceRetain(device); 106 | DeviceConsoleConnection *data = malloc(sizeof *data); 107 | data->connection = connection; 108 | data->socket = socket; 109 | data->source = source; 110 | CFDictionarySetValue(liveConnections, device, data); 111 | 112 | NSDictionary *info=@{ 113 | @"count":@(CFDictionaryGetCount(liveConnections)), 114 | @"connect":@(1), 115 | @"udid":udid 116 | }; 117 | 118 | [[NSNotificationCenter defaultCenter] postNotificationName:@"DeviceChange" object:nil userInfo:info]; 119 | return; 120 | } 121 | CFRelease(source); 122 | } 123 | } 124 | AMDeviceStopSession(device); 125 | } 126 | } 127 | } 128 | AMDeviceDisconnect(device); 129 | break; 130 | } 131 | case ADNCI_MSG_DISCONNECTED: { 132 | DeviceConsoleConnection *data = (DeviceConsoleConnection *)CFDictionaryGetValue(liveConnections, device); 133 | if (data) { 134 | CFDictionaryRemoveValue(liveConnections, device); 135 | AMDeviceRelease(device); 136 | CFRunLoopRemoveSource(CFRunLoopGetMain(), data->source, kCFRunLoopCommonModes); 137 | CFRelease(data->source); 138 | CFRelease(data->socket); 139 | free(data); 140 | AMDeviceStopSession(device); 141 | AMDeviceDisconnect(device); 142 | 143 | NSDictionary *info=@{ 144 | @"count":@(CFDictionaryGetCount(liveConnections)), 145 | @"connect":@(0), 146 | @"udid":udid 147 | }; 148 | 149 | [[NSNotificationCenter defaultCenter] postNotificationName:@"DeviceChange" object:nil userInfo:info]; 150 | } 151 | break; 152 | } 153 | default: 154 | break; 155 | } 156 | } 157 | 158 | 159 | @implementation NSDictionary(LogInfo) 160 | 161 | -(LogLevel)level{ 162 | return [self[@"level"] integerValue]; 163 | } 164 | 165 | -(NSString*)log{ 166 | return self[@"log"]; 167 | } 168 | 169 | -(NSString*)date{ 170 | return self[@"date"]; 171 | } 172 | 173 | -(NSString*)device{ 174 | return self[@"device"]; 175 | } 176 | 177 | -(NSString*)process{ 178 | return self[@"process"]; 179 | } 180 | 181 | @end 182 | 183 | @implementation FIRUSBLoger 184 | +(NSDictionary*)logInfo:(NSString*)msg{ 185 | 186 | 187 | return nil; 188 | } 189 | 190 | - (instancetype)init 191 | { 192 | self = [super init]; 193 | if (self) { 194 | NSError *err; 195 | 196 | reg=[NSRegularExpression regularExpressionWithPattern:@"([A-z]{3} {1,2}[0-9]{1,2} [0-9]{2}:[0-9]{2}:[0-9]{2}) ([^ ]+) ([^\\[]+)\\[[0-9]{1,8}\\] <([^>]+)>: (.+)$" options:0 error:&err]; 197 | 198 | LogLevelLimit=LogAll; 199 | } 200 | return self; 201 | } 202 | 203 | -(void)setLevel:(LogLevel)level{ 204 | LogLevelLimit=level; 205 | } 206 | -(LogLevel)level{ 207 | return LogLevelLimit; 208 | } 209 | 210 | -(int)start{ 211 | liveConnections = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); 212 | am_device_notification *notification; 213 | AMDeviceNotificationSubscribe(DeviceNotificationCallback, 0, 0, NULL, ¬ification); 214 | return 0; 215 | } 216 | 217 | 218 | @end 219 | -------------------------------------------------------------------------------- /LogGuru/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | AppIcon.icns 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSApplicationCategoryType 26 | public.app-category.developer-tools 27 | LSMinimumSystemVersion 28 | $(MACOSX_DEPLOYMENT_TARGET) 29 | NSHumanReadableCopyright 30 | Copyright © 2016年 im.fir.logguru. All rights reserved. 31 | NSMainNibFile 32 | MainMenu 33 | NSPrincipalClass 34 | NSApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /LogGuru/MobileDevice.h: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | * MobileDevice.h - interface to MobileDevice.framework 3 | * $LastChangedDate: 2007-07-09 18:59:29 -0700 (Mon, 09 Jul 2007) $ 4 | * 5 | * Copied from http://iphonesvn.halifrag.com/svn/iPhone/ 6 | * With modifications from Allen Porter and Scott Turner 7 | * 8 | * ------------------------------------------------------------------------- */ 9 | 10 | #ifndef MOBILEDEVICE_H 11 | #define MOBILEDEVICE_H 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #if defined(WIN32) 18 | #include 19 | typedef unsigned int mach_error_t; 20 | #elif defined(__APPLE__) 21 | #include 22 | #include 23 | #endif 24 | 25 | /* Error codes */ 26 | #define MDERR_APPLE_MOBILE (err_system(0x3a)) 27 | #define MDERR_IPHONE (err_sub(0)) 28 | 29 | /* Apple Mobile (AM*) errors */ 30 | #define MDERR_OK ERR_SUCCESS 31 | #define MDERR_SYSCALL (ERR_MOBILE_DEVICE | 0x01) 32 | #define MDERR_OUT_OF_MEMORY (ERR_MOBILE_DEVICE | 0x03) 33 | #define MDERR_QUERY_FAILED (ERR_MOBILE_DEVICE | 0x04) 34 | #define MDERR_INVALID_ARGUMENT (ERR_MOBILE_DEVICE | 0x0b) 35 | #define MDERR_DICT_NOT_LOADED (ERR_MOBILE_DEVICE | 0x25) 36 | 37 | /* Apple File Connection (AFC*) errors */ 38 | #define MDERR_AFC_OUT_OF_MEMORY 0x03 39 | 40 | /* USBMux errors */ 41 | #define MDERR_USBMUX_ARG_NULL 0x16 42 | #define MDERR_USBMUX_FAILED 0xffffffff 43 | 44 | /* Messages passed to device notification callbacks: passed as part of 45 | * am_device_notification_callback_info. */ 46 | #define ADNCI_MSG_CONNECTED 1 47 | #define ADNCI_MSG_DISCONNECTED 2 48 | #define ADNCI_MSG_UNKNOWN 3 49 | 50 | #define AMD_IPHONE_PRODUCT_ID 0x1290 51 | #define AMD_IPHONE_SERIAL "3391002d9c804d105e2c8c7d94fc35b6f3d214a3" 52 | 53 | /* Services, found in /System/Library/Lockdown/Services.plist */ 54 | #define AMSVC_AFC CFSTR("com.apple.afc") 55 | #define AMSVC_BACKUP CFSTR("com.apple.mobilebackup") 56 | #define AMSVC_CRASH_REPORT_COPY CFSTR("com.apple.crashreportcopy") 57 | #define AMSVC_DEBUG_IMAGE_MOUNT CFSTR("com.apple.mobile.debug_image_mount") 58 | #define AMSVC_NOTIFICATION_PROXY CFSTR("com.apple.mobile.notification_proxy") 59 | #define AMSVC_PURPLE_TEST CFSTR("com.apple.purpletestr") 60 | #define AMSVC_SOFTWARE_UPDATE CFSTR("com.apple.mobile.software_update") 61 | #define AMSVC_SYNC CFSTR("com.apple.mobilesync") 62 | #define AMSVC_SCREENSHOT CFSTR("com.apple.screenshotr") 63 | #define AMSVC_SYSLOG_RELAY CFSTR("com.apple.syslog_relay") 64 | #define AMSVC_SYSTEM_PROFILER CFSTR("com.apple.mobile.system_profiler") 65 | 66 | typedef unsigned int afc_error_t; 67 | typedef unsigned int usbmux_error_t; 68 | typedef unsigned int service_conn_t; 69 | 70 | struct am_recovery_device; 71 | 72 | typedef struct am_device_notification_callback_info { 73 | struct am_device *dev; /* 0 device */ 74 | unsigned int msg; /* 4 one of ADNCI_MSG_* */ 75 | } __attribute__ ((packed)) am_device_notification_callback_info; 76 | 77 | typedef void (*am_restore_device_notification_callback)(struct 78 | am_recovery_device *); 79 | 80 | /* This is a CoreFoundation object of class AMRecoveryModeDevice. */ 81 | typedef struct am_recovery_device { 82 | unsigned char unknown0[8]; /* 0 */ 83 | am_restore_device_notification_callback callback; /* 8 */ 84 | void *user_info; /* 12 */ 85 | unsigned char unknown1[12]; /* 16 */ 86 | unsigned int readwrite_pipe; /* 28 */ 87 | unsigned char read_pipe; /* 32 */ 88 | unsigned char write_ctrl_pipe; /* 33 */ 89 | unsigned char read_unknown_pipe; /* 34 */ 90 | unsigned char write_file_pipe; /* 35 */ 91 | unsigned char write_input_pipe; /* 36 */ 92 | } __attribute__ ((packed)) am_recovery_device; 93 | 94 | /* A CoreFoundation object of class AMRestoreModeDevice. */ 95 | typedef struct am_restore_device { 96 | unsigned char unknown[32]; 97 | int port; 98 | } __attribute__ ((packed)) am_restore_device; 99 | 100 | /* The type of the device notification callback function. */ 101 | typedef void(*am_device_notification_callback)(struct 102 | am_device_notification_callback_info *, void* arg); 103 | 104 | typedef void *amd_device_attached_callback; 105 | 106 | 107 | typedef struct am_device { 108 | unsigned char unknown0[16]; /* 0 - zero */ 109 | unsigned int device_id; /* 16 */ 110 | unsigned int product_id; /* 20 - set to AMD_IPHONE_PRODUCT_ID */ 111 | char *serial; /* 24 - set to AMD_IPHONE_SERIAL */ 112 | unsigned int unknown1; /* 28 */ 113 | unsigned char unknown2[4]; /* 32 */ 114 | unsigned int lockdown_conn; /* 36 */ 115 | unsigned char unknown3[8]; /* 40 */ 116 | } __attribute__ ((packed)) am_device; 117 | 118 | typedef struct am_device_notification { 119 | unsigned int unknown0; /* 0 */ 120 | unsigned int unknown1; /* 4 */ 121 | unsigned int unknown2; /* 8 */ 122 | am_device_notification_callback callback; /* 12 */ 123 | unsigned int unknown3; /* 16 */ 124 | } __attribute__ ((packed)) am_device_notification; 125 | 126 | typedef struct afc_connection { 127 | unsigned int handle; /* 0 */ 128 | unsigned int unknown0; /* 4 */ 129 | unsigned char unknown1; /* 8 */ 130 | unsigned char padding[3]; /* 9 */ 131 | unsigned int unknown2; /* 12 */ 132 | unsigned int unknown3; /* 16 */ 133 | unsigned int unknown4; /* 20 */ 134 | unsigned int fs_block_size; /* 24 */ 135 | unsigned int sock_block_size; /* 28: always 0x3c */ 136 | unsigned int io_timeout; /* 32: from AFCConnectionOpen, usu. 0 */ 137 | void *afc_lock; /* 36 */ 138 | unsigned int context; /* 40 */ 139 | } __attribute__ ((packed)) afc_connection; 140 | 141 | typedef struct afc_directory { 142 | unsigned char unknown[0]; /* size unknown */ 143 | } __attribute__ ((packed)) afc_directory; 144 | 145 | typedef struct afc_dictionary { 146 | unsigned char unknown[0]; /* size unknown */ 147 | } __attribute__ ((packed)) afc_dictionary; 148 | 149 | typedef unsigned long long afc_file_ref; 150 | 151 | typedef struct usbmux_listener_1 { /* offset value in iTunes */ 152 | unsigned int unknown0; /* 0 1 */ 153 | unsigned char *unknown1; /* 4 ptr, maybe device? */ 154 | amd_device_attached_callback callback; /* 8 _AMDDeviceAttached */ 155 | unsigned int unknown3; /* 12 */ 156 | unsigned int unknown4; /* 16 */ 157 | unsigned int unknown5; /* 20 */ 158 | } __attribute__ ((packed)) usbmux_listener_1; 159 | 160 | typedef struct usbmux_listener_2 { 161 | unsigned char unknown0[4144]; 162 | } __attribute__ ((packed)) usbmux_listener_2; 163 | 164 | typedef struct am_bootloader_control_packet { 165 | unsigned char opcode; /* 0 */ 166 | unsigned char length; /* 1 */ 167 | unsigned char magic[2]; /* 2: 0x34, 0x12 */ 168 | unsigned char payload[0]; /* 4 */ 169 | } __attribute__ ((packed)) am_bootloader_control_packet; 170 | 171 | /* ---------------------------------------------------------------------------- 172 | * Public routines 173 | * ------------------------------------------------------------------------- */ 174 | 175 | void AMDSetLogLevel(int level); 176 | 177 | /* Registers a notification with the current run loop. The callback gets 178 | * copied into the notification struct, as well as being registered with the 179 | * current run loop. dn_unknown3 gets copied into unknown3 in the same. 180 | * (Maybe dn_unknown3 is a user info parameter that gets passed as an arg to 181 | * the callback?) unused0 and unused1 are both 0 when iTunes calls this. 182 | * In iTunes the callback is located from $3db78e-$3dbbaf. 183 | * 184 | * Returns: 185 | * MDERR_OK if successful 186 | * MDERR_SYSCALL if CFRunLoopAddSource() failed 187 | * MDERR_OUT_OF_MEMORY if we ran out of memory 188 | */ 189 | 190 | mach_error_t AMDeviceNotificationSubscribe(am_device_notification_callback 191 | callback, unsigned int unused0, unsigned int unused1, void* //unsigned int 192 | dn_unknown3, struct am_device_notification **notification); 193 | 194 | /* Connects to the iPhone. Pass in the am_device structure that the 195 | * notification callback will give to you. 196 | * 197 | * Returns: 198 | * MDERR_OK if successfully connected 199 | * MDERR_SYSCALL if setsockopt() failed 200 | * MDERR_QUERY_FAILED if the daemon query failed 201 | * MDERR_INVALID_ARGUMENT if USBMuxConnectByPort returned 0xffffffff 202 | */ 203 | 204 | mach_error_t AMDeviceConnect(struct am_device *device); 205 | 206 | /* Calls PairingRecordPath() on the given device, than tests whether the path 207 | * which that function returns exists. During the initial connect, the path 208 | * returned by that function is '/', and so this returns 1. 209 | * 210 | * Returns: 211 | * 0 if the path did not exist 212 | * 1 if it did 213 | */ 214 | 215 | int AMDeviceIsPaired(struct am_device *device); 216 | 217 | /* iTunes calls this function immediately after testing whether the device is 218 | * paired. It creates a pairing file and establishes a Lockdown connection. 219 | * 220 | * Returns: 221 | * MDERR_OK if successful 222 | * MDERR_INVALID_ARGUMENT if the supplied device is null 223 | * MDERR_DICT_NOT_LOADED if the load_dict() call failed 224 | */ 225 | 226 | mach_error_t AMDeviceValidatePairing(struct am_device *device); 227 | 228 | /* Creates a Lockdown session and adjusts the device structure appropriately 229 | * to indicate that the session has been started. iTunes calls this function 230 | * after validating pairing. 231 | * 232 | * Returns: 233 | * MDERR_OK if successful 234 | * MDERR_INVALID_ARGUMENT if the Lockdown conn has not been established 235 | * MDERR_DICT_NOT_LOADED if the load_dict() call failed 236 | */ 237 | 238 | mach_error_t AMDeviceStartSession(struct am_device *device); 239 | 240 | /* Starts a service and returns a handle that can be used in order to further 241 | * access the service. You should stop the session and disconnect before using 242 | * the service. iTunes calls this function after starting a session. It starts 243 | * the service and the SSL connection. unknown may safely be 244 | * NULL (it is when iTunes calls this), but if it is not, then it will be 245 | * filled upon function exit. service_name should be one of the AMSVC_* 246 | * constants. If the service is AFC (AMSVC_AFC), then the handle is the handle 247 | * that will be used for further AFC* calls. 248 | * 249 | * Returns: 250 | * MDERR_OK if successful 251 | * MDERR_SYSCALL if the setsockopt() call failed 252 | * MDERR_INVALID_ARGUMENT if the Lockdown conn has not been established 253 | */ 254 | 255 | mach_error_t AMDeviceStartService(struct am_device *device, CFStringRef 256 | service_name, service_conn_t *handle, unsigned int * 257 | unknown); 258 | 259 | mach_error_t AMDeviceStartHouseArrestService(struct am_device *device, CFStringRef identifier, void *unknown, service_conn_t *handle, unsigned int *what); 260 | 261 | /* Stops a session. You should do this before accessing services. 262 | * 263 | * Returns: 264 | * MDERR_OK if successful 265 | * MDERR_INVALID_ARGUMENT if the Lockdown conn has not been established 266 | */ 267 | 268 | mach_error_t AMDeviceStopSession(struct am_device *device); 269 | 270 | /* Opens an Apple File Connection. You must start the appropriate service 271 | * first with AMDeviceStartService(). In iTunes, io_timeout is 0. 272 | * 273 | * Returns: 274 | * MDERR_OK if successful 275 | * MDERR_AFC_OUT_OF_MEMORY if malloc() failed 276 | */ 277 | 278 | afc_error_t AFCConnectionOpen(service_conn_t handle, unsigned int io_timeout, 279 | struct afc_connection **conn); 280 | 281 | /* Pass in a pointer to an afc_device_info structure. It will be filled. */ 282 | afc_error_t AFCDeviceInfoOpen(afc_connection *conn, struct 283 | afc_dictionary **info); 284 | 285 | /* Turns debug mode on if the environment variable AFCDEBUG is set to a numeric 286 | * value, or if the file '/AFCDEBUG' is present and contains a value. */ 287 | void AFCPlatformInit(); 288 | 289 | /* Opens a directory on the iPhone. Pass in a pointer in dir to be filled in. 290 | * Note that this normally only accesses the iTunes sandbox/partition as the 291 | * root, which is /var/root/Media. Pathnames are specified with '/' delimiters 292 | * as in Unix style. 293 | * 294 | * Returns: 295 | * MDERR_OK if successful 296 | */ 297 | 298 | afc_error_t AFCDirectoryOpen(afc_connection *conn, const char *path, 299 | struct afc_directory **dir); 300 | 301 | /* Acquires the next entry in a directory previously opened with 302 | * AFCDirectoryOpen(). When dirent is filled with a NULL value, then the end 303 | * of the directory has been reached. '.' and '..' will be returned as the 304 | * first two entries in each directory except the root; you may want to skip 305 | * over them. 306 | * 307 | * Returns: 308 | * MDERR_OK if successful, even if no entries remain 309 | */ 310 | 311 | afc_error_t AFCDirectoryRead(afc_connection *conn/*unsigned int unused*/, struct afc_directory *dir, 312 | char **dirent); 313 | 314 | afc_error_t AFCDirectoryClose(afc_connection *conn, struct afc_directory *dir); 315 | afc_error_t AFCDirectoryCreate(afc_connection *conn, const char *dirname); 316 | afc_error_t AFCRemovePath(afc_connection *conn, const char *dirname); 317 | afc_error_t AFCRenamePath(afc_connection *conn, const char *from, const char *to); 318 | afc_error_t AFCLinkPath(afc_connection *conn, long long int linktype, const char *target, const char *linkname); 319 | 320 | /* Returns the context field of the given AFC connection. */ 321 | unsigned int AFCConnectionGetContext(afc_connection *conn); 322 | 323 | /* Returns the fs_block_size field of the given AFC connection. */ 324 | unsigned int AFCConnectionGetFSBlockSize(afc_connection *conn); 325 | 326 | /* Returns the io_timeout field of the given AFC connection. In iTunes this is 327 | * 0. */ 328 | unsigned int AFCConnectionGetIOTimeout(afc_connection *conn); 329 | 330 | /* Returns the sock_block_size field of the given AFC connection. */ 331 | unsigned int AFCConnectionGetSocketBlockSize(afc_connection *conn); 332 | 333 | /* Closes the given AFC connection. */ 334 | afc_error_t AFCConnectionClose(afc_connection *conn); 335 | 336 | /* Registers for device notifications related to the restore process. unknown0 337 | * is zero when iTunes calls this. In iTunes, 338 | * the callbacks are located at: 339 | * 1: $3ac68e-$3ac6b1, calls $3ac542(unknown1, arg, 0) 340 | * 2: $3ac66a-$3ac68d, calls $3ac542(unknown1, 0, arg) 341 | * 3: $3ac762-$3ac785, calls $3ac6b2(unknown1, arg, 0) 342 | * 4: $3ac73e-$3ac761, calls $3ac6b2(unknown1, 0, arg) 343 | */ 344 | 345 | unsigned int AMRestoreRegisterForDeviceNotifications( 346 | am_restore_device_notification_callback dfu_connect_callback, 347 | am_restore_device_notification_callback recovery_connect_callback, 348 | am_restore_device_notification_callback dfu_disconnect_callback, 349 | am_restore_device_notification_callback recovery_disconnect_callback, 350 | unsigned int unknown0, 351 | void *user_info); 352 | 353 | /* Causes the restore functions to spit out (unhelpful) progress messages to 354 | * the file specified by the given path. iTunes always calls this right before 355 | * restoring with a path of 356 | * "$HOME/Library/Logs/iPhone Updater Logs/iPhoneUpdater X.log", where X is an 357 | * unused number. 358 | */ 359 | 360 | unsigned int AMRestoreEnableFileLogging(char *path); 361 | 362 | /* Initializes a new option dictionary to default values. Pass the constant 363 | * kCFAllocatorDefault as the allocator. The option dictionary looks as 364 | * follows: 365 | * { 366 | * NORImageType => 'production', 367 | * AutoBootDelay => 0, 368 | * KernelCacheType => 'Release', 369 | * UpdateBaseband => true, 370 | * DFUFileType => 'RELEASE', 371 | * SystemImageType => 'User', 372 | * CreateFilesystemPartitions => true, 373 | * FlashNOR => true, 374 | * RestoreBootArgs => 'rd=md0 nand-enable-reformat=1 -progress' 375 | * BootImageType => 'User' 376 | * } 377 | * 378 | * Returns: 379 | * the option dictionary if successful 380 | * NULL if out of memory 381 | */ 382 | 383 | CFMutableDictionaryRef AMRestoreCreateDefaultOptions(CFAllocatorRef allocator); 384 | 385 | /* ---------------------------------------------------------------------------- 386 | * Less-documented public routines 387 | * ------------------------------------------------------------------------- */ 388 | 389 | /* mode 2 = read, mode 3 = write */ 390 | afc_error_t AFCFileRefOpen(afc_connection *conn, const char *path, 391 | unsigned long long mode, afc_file_ref *ref); 392 | afc_error_t AFCFileRefSeek(afc_connection *conn, afc_file_ref ref, 393 | unsigned long long offset1, unsigned long long offset2); 394 | afc_error_t AFCFileRefRead(afc_connection *conn, afc_file_ref ref, 395 | void *buf, unsigned int *len); 396 | afc_error_t AFCFileRefSetFileSize(afc_connection *conn, afc_file_ref ref, 397 | unsigned long long offset); 398 | afc_error_t AFCFileRefWrite(afc_connection *conn, afc_file_ref ref, 399 | const void *buf, unsigned int len); 400 | afc_error_t AFCFileRefClose(afc_connection *conn, afc_file_ref ref); 401 | 402 | afc_error_t AFCFileInfoOpen(afc_connection *conn, const char *path, struct 403 | afc_dictionary **info); 404 | afc_error_t AFCKeyValueRead(struct afc_dictionary *dict, char **key, char ** 405 | val); 406 | afc_error_t AFCKeyValueClose(struct afc_dictionary *dict); 407 | 408 | unsigned int AMRestorePerformRecoveryModeRestore(struct am_recovery_device * 409 | rdev, CFDictionaryRef opts, void *callback, void *user_info); 410 | unsigned int AMRestorePerformRestoreModeRestore(struct am_restore_device * 411 | rdev, CFDictionaryRef opts, void *callback, void *user_info); 412 | 413 | struct am_restore_device *AMRestoreModeDeviceCreate(unsigned int unknown0, 414 | unsigned int connection_id, unsigned int unknown1); 415 | 416 | unsigned int AMRestoreCreatePathsForBundle(CFStringRef restore_bundle_path, 417 | CFStringRef kernel_cache_type, CFStringRef boot_image_type, unsigned int 418 | unknown0, CFStringRef *firmware_dir_path, CFStringRef * 419 | kernelcache_restore_path, unsigned int unknown1, CFStringRef * 420 | ramdisk_path); 421 | 422 | unsigned int AMDeviceGetConnectionID(struct am_device *device); 423 | mach_error_t AMDeviceEnterRecovery(struct am_device *device); 424 | mach_error_t AMDeviceDisconnect(struct am_device *device); 425 | mach_error_t AMDeviceRetain(struct am_device *device); 426 | mach_error_t AMDeviceRelease(struct am_device *device); 427 | CFStringRef AMDeviceCopyValue(struct am_device *device, unsigned int, CFStringRef cfstring); 428 | CFStringRef AMDeviceCopyDeviceIdentifier(struct am_device *device); 429 | 430 | typedef void (*notify_callback)(CFStringRef notification, void *data); 431 | 432 | mach_error_t AMDPostNotification(service_conn_t socket, CFStringRef notification, CFStringRef userinfo); 433 | mach_error_t AMDObserveNotification(void *socket, CFStringRef notification); 434 | mach_error_t AMDListenForNotifications(void *socket, notify_callback cb, void *data); 435 | mach_error_t AMDShutdownNotificationProxy(void *socket); 436 | 437 | /*edits by geohot*/ 438 | mach_error_t AMDeviceDeactivate(struct am_device *device); 439 | mach_error_t AMDeviceActivate(struct am_device *device, CFMutableDictionaryRef); 440 | /*end*/ 441 | 442 | void *AMDeviceSerialize(struct am_device *device); 443 | void AMDAddLogFileDescriptor(int fd); 444 | //kern_return_t AMDeviceSendMessage(service_conn_t socket, void *unused, CFPropertyListRef plist); 445 | //kern_return_t AMDeviceReceiveMessage(service_conn_t socket, CFDictionaryRef options, CFPropertyListRef * result); 446 | 447 | /* ---------------------------------------------------------------------------- 448 | * Semi-private routines 449 | * ------------------------------------------------------------------------- */ 450 | 451 | /* Pass in a usbmux_listener_1 structure and a usbmux_listener_2 structure 452 | * pointer, which will be filled with the resulting usbmux_listener_2. 453 | * 454 | * Returns: 455 | * MDERR_OK if completed successfully 456 | * MDERR_USBMUX_ARG_NULL if one of the arguments was NULL 457 | * MDERR_USBMUX_FAILED if the listener was not created successfully 458 | */ 459 | 460 | usbmux_error_t USBMuxListenerCreate(struct usbmux_listener_1 *esi_fp8, struct 461 | usbmux_listener_2 **eax_fp12); 462 | 463 | /* ---------------------------------------------------------------------------- 464 | * Less-documented semi-private routines 465 | * ------------------------------------------------------------------------- */ 466 | 467 | usbmux_error_t USBMuxListenerHandleData(void *); 468 | 469 | /* ---------------------------------------------------------------------------- 470 | * Private routines - here be dragons 471 | * ------------------------------------------------------------------------- */ 472 | 473 | /* AMRestorePerformRestoreModeRestore() calls this function with a dictionary 474 | * in order to perform certain special restore operations 475 | * (RESTORED_OPERATION_*). It is thought that this function might enable 476 | * significant access to the phone. */ 477 | 478 | typedef unsigned int (*t_performOperation)(struct am_restore_device *rdev, 479 | CFDictionaryRef op); // __attribute__ ((regparm(2))); 480 | 481 | #ifdef __cplusplus 482 | } 483 | #endif 484 | 485 | #endif 486 | -------------------------------------------------------------------------------- /LogGuru/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // LogGuru 4 | // 5 | // Created by Travis Wang on 2016/10/20. 6 | // Copyright © 2016年 im.fir.logguru. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /LogGuruTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LogGuruTests/LogGuruTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // LogGuruTests.m 3 | // LogGuruTests 4 | // 5 | // Created by Travis Wang on 2016/10/20. 6 | // Copyright © 2016年 im.fir.logguru. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LogGuruTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation LogGuruTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 只支持 Mac 10.9 以上版本 2 | 3 | 1、点击下载 [Log Guru](https://github.com/FIRHQ/LogGuru/releases/download/v1.0/LogGuru-Mac-1.0.zip) 4 | 5 | 2、解压打开 Log Guru 6 | 7 | 3、将不能安装应用的设备用数据线连接到电脑上 8 | 9 | 4、查看不能安装的原因,如下图: ( [查看常见的错误日志](http://blog.fir.im/logs/) ) 10 | 11 | ![Screenshot1](http://firclub.qiniudn.com/FoTw_wa9SEIqYLV3crZKikzzMz5u) --------------------------------------------------------------------------------