├── .gitignore
├── pause.png
├── play.png
├── InjectionDemo
├── InjectionDemo
│ ├── en.lproj
│ │ ├── InfoPlist.strings
│ │ └── INViewController.xib
│ ├── Icon.png
│ ├── INViewController.h
│ ├── INRoseView.h
│ ├── InjectionDemo-Prefix.pch
│ ├── INAppDelegate.h
│ ├── main.m
│ ├── INViewController.m
│ ├── InjectionDemo-Info.plist
│ ├── INAppDelegate.m
│ └── INRoseView.m
├── InjectionDemo.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── project.pbxproj
└── InjectionDemo.approj
│ ├── targets
│ └── InjectionDemo
│ │ ├── Release.generated
│ │ ├── Release.final
│ │ └── Release.overrides.json
│ └── configuration.json
├── ApportablePlugin.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── ApportablePlugin.xccheckout
└── project.pbxproj
├── Classes
├── APDebugController.h
├── APTextView.h
├── APLogController.h
├── APPluginMenuController.h
├── APLiveCoding.h
├── APConsoleController.h
├── APTextView.m
├── APDebugController.m
├── APLogController.m
├── APDebugController.xib
├── APPluginMenuController.xib
├── APLiveCoding.m
├── APConsoleWindow.xib
├── APPluginMenuController.m
├── APLogWindow.xib
└── APConsoleController.m
├── prepare.py
├── Info.plist
├── README.md
└── inject.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *xcuserdata*
2 |
--------------------------------------------------------------------------------
/pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnno1962/ApportablePlugin/HEAD/pause.png
--------------------------------------------------------------------------------
/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnno1962/ApportablePlugin/HEAD/play.png
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnno1962/ApportablePlugin/HEAD/InjectionDemo/InjectionDemo/Icon.png
--------------------------------------------------------------------------------
/ApportablePlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Classes/APDebugController.h:
--------------------------------------------------------------------------------
1 | //
2 | // APDebugController.h
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/06/2014.
6 | //
7 | //
8 |
9 | #import "APConsoleController.h"
10 |
11 | @interface APDebugController : APConsoleController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Classes/APTextView.h:
--------------------------------------------------------------------------------
1 | //
2 | // APTextView.h
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface APTextView : NSTextView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Classes/APLogController.h:
--------------------------------------------------------------------------------
1 | //
2 | // APLogController.h
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #import "APConsoleController.h"
10 |
11 | @interface APLogController : APConsoleController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/INViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // INViewController.h
3 | // InjectionDemo
4 | //
5 | // Created by John Holdsworth on 22/05/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface INViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/INRoseView.h:
--------------------------------------------------------------------------------
1 | //
2 | // INRoseView.h
3 | // InjectionDemo
4 | //
5 | // Created by John Holdsworth on 12/05/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | // $Id$
8 | //
9 |
10 | #import
11 |
12 | @interface INRoseView : UIView
13 |
14 | @property (strong, nonatomic) IBOutlet UIButton *button;
15 |
16 | - (IBAction)animate:sender;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/InjectionDemo-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'InjectionDemo' target in the 'InjectionDemo' project
3 | //
4 |
5 | #import
6 |
7 | #ifndef __IPHONE_4_0
8 | #warning "This project uses features only available in iOS SDK 4.0 and later."
9 | #endif
10 |
11 | #ifdef __OBJC__
12 | #import
13 | #import
14 | #endif
15 |
--------------------------------------------------------------------------------
/Classes/APPluginMenuController.h:
--------------------------------------------------------------------------------
1 | //
2 | // APPluginMenuController.h
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface APPluginMenuController : NSObject
12 |
13 | @property (nonatomic,strong) NSWindow *lastKeyWindow;
14 |
15 | + (APPluginMenuController *)sharedPlugin;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/INAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // INAppDelegate.h
3 | // InjectionDemo
4 | //
5 | // Created by John Holdsworth on 22/05/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class INViewController;
12 |
13 | @interface INAppDelegate : UIResponder
14 |
15 | @property (strong, nonatomic) UIWindow *window;
16 | @property (strong, nonatomic) INViewController *viewController;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // InjectionDemo
4 | //
5 | // Created by John Holdsworth on 22/05/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "INAppDelegate.h"
12 |
13 | int main(int argc, char *argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([INAppDelegate class]));
17 | }
18 | }
19 |
20 | #ifdef ANDROID
21 | #import "../../APLiveCoding.m"
22 | #endif
23 |
--------------------------------------------------------------------------------
/prepare.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | # prepare.py
4 | # ApportablePlugin
5 | #
6 | # Created by John Holdsworth on 11/05/2014.
7 | #
8 |
9 | import sys
10 | from subprocess import Popen, PIPE, call
11 |
12 | implementation = sys.argv[1]
13 |
14 | main_m = Popen(["find", ".", "-name", "main.m*", "-print"],
15 | stdout=PIPE).stdout.read().split( "\n" )[0]
16 |
17 | call(["chmod", "+w", main_m])
18 |
19 | open(main_m, "a").write("""
20 | //#ifdef DEBUG
21 | #import "%s"
22 | //#endif
23 | """ % implementation)
24 |
25 | call(["open", main_m])
26 |
--------------------------------------------------------------------------------
/Classes/APLiveCoding.h:
--------------------------------------------------------------------------------
1 | //
2 | // APLiveCoding.h
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 03/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #ifndef _APLiveCoding_h_
10 | #define _APLiveCoding_h_
11 |
12 | #import
13 |
14 | #define kINNotification @"INJECTION_BUNDLE_NOTIFICATION"
15 |
16 | #ifdef DEBUG
17 | #define _instatic
18 | #else
19 | #define _instatic static
20 | #endif
21 |
22 | #define _inglobal
23 |
24 | #define _inval( _val... ) = _val
25 |
26 | @interface APLiveCoding : NSObject
27 |
28 | + (void)loadedClass:(Class)newClass notify:(BOOL)notify;
29 | + (void)loadedNotify:(BOOL)notify hook:(void *)hook;
30 |
31 | @end
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/Classes/APConsoleController.h:
--------------------------------------------------------------------------------
1 | //
2 | // APConsoleController.h
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface APConsoleController : NSObject
12 |
13 | @property (nonatomic,assign) IBOutlet NSTextView *console;
14 | @property (nonatomic,strong) NSTask *task;
15 |
16 | - (instancetype)initNib:(NSString *)nibName project:(NSString *)projectRoot command:(NSString *)command;
17 | - (void)runTask:(NSTask *)task sendOnCompletetion:(NSString *)gdbCommand;
18 | - (BOOL)handleTextViewInput:(NSString *)characters;
19 | - (void)insertText:(NSString *)output;
20 | - (void)sendTask:(NSString *)input;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/Classes/APTextView.m:
--------------------------------------------------------------------------------
1 | //
2 | // APTextView.m
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #import "APTextView.h"
10 | #import "APConsoleController.h"
11 |
12 | @implementation APTextView
13 |
14 | - (void)keyDown:(NSEvent *)theEvent
15 | {
16 | if ( ![(APConsoleController *)self.delegate handleTextViewInput:[theEvent characters]] )
17 | [super keyDown:theEvent];
18 | }
19 |
20 | - (void)paste:(id)sender
21 | {
22 | NSPasteboard *pb = [NSPasteboard generalPasteboard];
23 | NSString *input = [pb stringForType:NSPasteboardTypeString];
24 | if ( ![(APConsoleController *)self.delegate handleTextViewInput:input] )
25 | [super paste:sender];
26 | }
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/INViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // INViewController.m
3 | // InjectionDemo
4 | //
5 | // Created by John Holdsworth on 22/05/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "INViewController.h"
10 |
11 | @interface INViewController ()
12 |
13 | @end
14 |
15 | @implementation INViewController
16 |
17 | - (void)viewDidLoad
18 | {
19 | [super viewDidLoad];
20 | // Do any additional setup after loading the view, typically from a nib.
21 | }
22 |
23 | - (void)viewDidUnload
24 | {
25 | [super viewDidUnload];
26 | // Release any retained subviews of the main view.
27 | }
28 |
29 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
30 | {
31 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
32 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
33 | } else {
34 | return YES;
35 | }
36 | }
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | com.johnholdsworth.ApportablePlugin
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | ${CURRENT_PROJECT_VERSION}
19 | CFBundleVersion
20 | ${CURRENT_PROJECT_VERSION}
21 | NSPrincipalClass
22 | APPluginMenuController
23 | XCGCReady
24 |
25 | XCPluginHasUI
26 |
27 | XC4Compatible
28 |
29 | DVTPlugInCompatibilityUUIDs
30 |
31 | 63FC1C47-140D-42B0-BB4D-A10B2D225574
32 | 37B30044-3B14-46BA-ABAA-F01000C27B63
33 | A2E4D43F-41F4-4FB9-BB94-7177011C9AED
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/InjectionDemo-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.johnholdsworth.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleIconFile
14 | Icon.png
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | ${PRODUCT_NAME}
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | 1.0
23 | CFBundleSignature
24 | ????
25 | CFBundleVersion
26 | 1.0
27 | LSRequiresIPhoneOS
28 |
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/ApportablePlugin.xcodeproj/project.xcworkspace/xcshareddata/ApportablePlugin.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | E29DE24F-1B66-402E-9381-A192C6AFF340
9 | IDESourceControlProjectName
10 | ApportablePlugin
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 896251A8-7A25-4B0E-93A8-C5EA4AC48D94
14 | https://github.com/johnno1962/ApportablePlugin.git
15 |
16 | IDESourceControlProjectPath
17 | ApportablePlugin.xcodeproj/project.xcworkspace
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | 896251A8-7A25-4B0E-93A8-C5EA4AC48D94
21 | ../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/johnno1962/ApportablePlugin.git
25 | IDESourceControlProjectVersion
26 | 110
27 | IDESourceControlProjectWCCIdentifier
28 | 896251A8-7A25-4B0E-93A8-C5EA4AC48D94
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | 896251A8-7A25-4B0E-93A8-C5EA4AC48D94
36 | IDESourceControlWCCName
37 | ApportablePlugin
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/INAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // INAppDelegate.m
3 | // InjectionDemo
4 | //
5 | // Created by John Holdsworth on 22/05/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "INAppDelegate.h"
10 |
11 | #import "INViewController.h"
12 |
13 | @implementation INAppDelegate
14 |
15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
16 | {
17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
18 | // Override point for customization after application launch.
19 | self.viewController = [[INViewController alloc] initWithNibName:@"INViewController" bundle:nil];
20 | self.window.rootViewController = self.viewController;
21 | [self.window makeKeyAndVisible];
22 | return YES;
23 | }
24 |
25 | - (void)applicationWillResignActive:(UIApplication *)application
26 | {
27 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
28 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
29 | }
30 |
31 | - (void)applicationDidEnterBackground:(UIApplication *)application
32 | {
33 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
35 | }
36 |
37 | - (void)applicationWillEnterForeground:(UIApplication *)application
38 | {
39 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
40 | }
41 |
42 | - (void)applicationDidBecomeActive:(UIApplication *)application
43 | {
44 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
45 | }
46 |
47 | - (void)applicationWillTerminate:(UIApplication *)application
48 | {
49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
50 | }
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/Classes/APDebugController.m:
--------------------------------------------------------------------------------
1 | //
2 | // APDebugController.m
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/06/2014.
6 | //
7 | //
8 |
9 | #import "APDebugController.h"
10 |
11 | #import "APPluginMenuController.h"
12 |
13 | @interface NSObject(APMethodsUsed)
14 | + (NSImage *)iconImage_pause;
15 | + (NSImage *)iconImage_resume;
16 | @end
17 |
18 | @interface APDebugController()
19 |
20 | @property (nonatomic,retain) IBOutlet NSView *scrollView;
21 |
22 | @property (nonatomic,retain) NSButton *pauseResume;
23 | @property (nonatomic,retain) NSTextView *debugger;
24 |
25 | @end
26 |
27 | static id pauseTarget;
28 |
29 | @implementation APDebugController
30 |
31 | - (instancetype)initNib:(NSString *)nibName project:(NSString *)projectRoot command:(NSString *)command
32 | {
33 | self = [super initNib:nibName project:projectRoot command:command];
34 |
35 | [self findConsole:[[APPluginMenuController sharedPlugin].lastKeyWindow contentView]];
36 | NSView *splitView = self.debugger;
37 | for ( int i=0 ; i<8 ; i++ )
38 | splitView = [splitView superview];
39 | self.scrollView.frame = splitView.frame;
40 | [[splitView superview] addSubview:self.scrollView];
41 |
42 | if ( [[[self.pauseResume target] class] respondsToSelector:@selector(iconImage_pause)] )
43 | pauseTarget = [self.pauseResume target];
44 | self.pauseResume.enabled = TRUE;
45 | self.pauseResume.target = self;
46 | return self;
47 | }
48 |
49 | - (void)findConsole:(NSView *)view
50 | {
51 | for ( NSView *subview in [view subviews] ) {
52 | if ( [subview isKindOfClass:[NSButton class]] &&
53 | [(NSButton *)subview action] == @selector(pauseOrResume:) )
54 | self.pauseResume = (NSButton *)subview;
55 | if ( [subview class] == NSClassFromString(@"IDEConsoleTextView") )
56 | self.debugger = (NSTextView *)subview;
57 | [self findConsole:subview];
58 | }
59 | }
60 |
61 | - (void)pauseOrResume:sender
62 | {
63 | if ( [self.pauseResume image] == [[pauseTarget class] iconImage_pause] ) {
64 | self.pauseResume.image = [[pauseTarget class] iconImage_resume];
65 | [self.task interrupt];
66 | }
67 | else {
68 | self.pauseResume.image = [[pauseTarget class] iconImage_pause];
69 | [self sendTask:@"c\n"];
70 | }
71 | }
72 |
73 | - (void)windowWillClose:(NSNotification *)notification
74 | {
75 | self.pauseResume.image = [[pauseTarget class] iconImage_pause];
76 | self.pauseResume.target = pauseTarget;
77 | [self.scrollView removeFromSuperview];
78 | [super windowWillClose:notification];
79 | }
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # An ApportablePlugin
2 |
3 | A simple plugin to run apportable commands from inside Xcode as a starting point. To use, build the project
4 | which will linstall to the correct directory and then restart Xcode. Open an apportable project and use
5 | the new menu at the end of Xcode's "Product" menu to run the apportable debug/load/log/kill commands.
6 | You can type into the console windows opened or type control-c to interrupt the command. The "apportable
7 | log" window can be filtered by entering a regular expression. Windows close automatically on sucess.
8 |
9 | ### Live Coding
10 |
11 | The plugin now also supports live coding where you can make changes to the implementation any class in a
12 | running program. The main.m of the project project must first have been slightly patched by using the
13 | menu item "Product/Apportable/Prepare". After this, when the program is running or being debugged,
14 | changes to the current selected file can be applied using the "Apportable/Patch" command. As this
15 | requires a debugging connection, if one is not already open the plugin will attach to the program.
16 |
17 | Live Coding works by #importing the changed class into a small stub of code which lists the classes
18 | being loaded which is compiled and the resulting shared library copied to phone. gdb is then messaged
19 | by the plugin to call [APLiveCoding inject:"/data/local/tmp/APLiveCodingN.so"] which loads and calls the
20 | stub in the shared library. This registers any selector references and "swizzles" the new implementations
21 | onto the original class. Remember to "Apportable/Prepare" your project to make APLiveCoding available.
22 |
23 | ### Demo App
24 |
25 | A small demo app is included in the plugin which can be opened using the "Apportable/Demo" menu item.
26 | Run the applpication using "Apportable/Load" and edit the file "INRoseView.m" and type ^X to see how
27 | changing the various hard coded values affects the displayed appearance. This will open a window to
28 | "just_attach" to the process to load the changes using gdb commands. Do not close this window if
29 | you want to make subseqent changes as patching only works in the first debug/attach window opened.
30 |
31 | ### MIT License
32 |
33 | Copyright (C) 2014 John Holdsworth
34 |
35 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
36 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation
37 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
38 | and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
39 |
40 | The above copyright notice and this permission notice shall be included in all copies or substantial
41 | portions of the Software.
42 |
43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
44 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
46 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
47 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48 |
--------------------------------------------------------------------------------
/Classes/APLogController.m:
--------------------------------------------------------------------------------
1 | //
2 | // APLogController.m
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #import "APLogController.h"
10 |
11 | @interface APLogController()
12 |
13 | @property (nonatomic,assign) IBOutlet NSSearchField *filter;
14 | @property (nonatomic,assign) IBOutlet NSButton *paused;
15 |
16 | @property (nonatomic,strong) NSMutableArray *lineBuffer;
17 | @property (atomic,strong) NSMutableString *incoming;
18 | @property (atomic,strong) NSLock *lock;
19 |
20 | @end
21 |
22 | @implementation APLogController
23 |
24 | - (NSString *)filterLinesByCurrentRegularExpression:(NSArray *)lines
25 | {
26 | NSMutableString *out = [[NSMutableString alloc] init];
27 | NSRegularExpression *filterRegexp = [NSRegularExpression regularExpressionWithPattern:self.filter.stringValue
28 | options:0 error:NULL];
29 | for ( NSString *line in lines ) {
30 | if ( !filterRegexp ||
31 | [filterRegexp rangeOfFirstMatchInString:line options:0
32 | range:NSMakeRange(0, [line length])].location != NSNotFound ) {
33 | [out appendString:line];
34 | [out appendString:@"\n"];
35 | }
36 | }
37 |
38 | return out;
39 | }
40 |
41 | - (IBAction)filterChange:sender
42 | {
43 | self.console.string = [self filterLinesByCurrentRegularExpression:self.lineBuffer];
44 | }
45 |
46 | - (void)insertText:(NSString *)output
47 | {
48 | if ( !self.lock )
49 | self.lock = [[NSLock alloc] init];
50 |
51 | [self.lock lock];
52 | if ( !self.incoming )
53 | self.incoming = [[NSMutableString alloc] init];
54 | [self.incoming appendString:output];
55 | [self.lock unlock];
56 |
57 | dispatch_async(dispatch_get_main_queue(), ^{
58 | [self insertIncoming];
59 | });
60 |
61 | }
62 |
63 | - (void)insertIncoming
64 | {
65 | if ( !self.incoming )
66 | return;
67 |
68 | [self.lock lock];
69 | NSMutableArray *newLlines = [[self.incoming componentsSeparatedByString:@"\n"] mutableCopy];
70 | self.incoming = nil;
71 | [self.lock unlock];
72 |
73 | NSUInteger lineCount = [newLlines count];
74 | if ( lineCount && [newLlines[lineCount-1] length] == 0 )
75 | [newLlines removeObjectAtIndex:lineCount-1];
76 |
77 | if ( !self.lineBuffer )
78 | self.lineBuffer = [[NSMutableArray alloc] init];
79 | [self.lineBuffer addObjectsFromArray:newLlines];
80 |
81 | if ( ![self.paused state] ) {
82 | NSString *filtered = [self filterLinesByCurrentRegularExpression:newLlines];
83 | if ( [filtered length] )
84 | [super insertText:filtered];
85 | }
86 |
87 | }
88 |
89 | - (IBAction)pausePlay:sender
90 | {
91 | if ( [self.paused state] ) {
92 | [self.paused setImage:[self imageNamed:@"play"]];
93 | }
94 | else {
95 | [self.paused setImage:[self imageNamed:@"pause"]];
96 | [self filterChange:self];
97 | }
98 | }
99 |
100 | - (NSImage *)imageNamed:(NSString *)name
101 | {
102 | return [[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]]
103 | pathForResource:name ofType:@"png"]];
104 | }
105 |
106 | @end
107 |
--------------------------------------------------------------------------------
/Classes/APDebugController.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 |
--------------------------------------------------------------------------------
/inject.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | # inject.py
4 | # ApportablePlugin
5 | #
6 | # Created by John Holdsworth on 11/05/2014.
7 | #
8 |
9 | import sys
10 | from sys import argv, exit
11 | from os import environ, chdir, unlink, fdopen
12 | from subprocess import call
13 | import re
14 |
15 | sys.stdout = fdopen(sys.stdout.fileno(), 'w', 0)
16 |
17 | projectRoot = argv[1]
18 | shlib = argv[2]
19 | selectedFile= argv[3]
20 | flags = 0
21 |
22 | projName = re.search(r'/([^/]+)/?$', projectRoot).group(1);
23 |
24 | classes = list(set(re.findall(r'@implementation\s+(\w+)\b',open(selectedFile).read())))
25 | injection = "".join(map(lambda cl:' [APLiveCoding loadedClass:[%s class] notify:%s];\n' % (cl, flags), classes))
26 |
27 | changesFile = re.sub( r'(\.\w+)$', r'_\1', selectedFile )
28 |
29 | open( changesFile, "w" ).write( """\
30 | /*
31 | Generated for Injection of class implementations
32 | */
33 |
34 | #import
35 |
36 | @interface APLiveCoding
37 | + (void)loadedClass:(Class)newClass notify:(BOOL)notify;
38 | + (void)loadedNotify:(BOOL)notify hook:(void *)hook;
39 | @end
40 |
41 | #define INJECTION_BUNDLE
42 |
43 | #undef _instatic
44 | #define _instatic extern
45 |
46 | #undef _inglobal
47 | #define _inglobal extern
48 |
49 | #undef _inval
50 | #define _inval( _val... ) /* = _val */
51 |
52 | #import "%s"
53 |
54 | #if __cplusplus
55 | extern "C" int injectionHook();
56 | #endif
57 |
58 | int injectionHook() {
59 | NSLog( @"injectionHook( %s ):" );
60 | dispatch_async(dispatch_get_main_queue(), ^{
61 | %s [APLiveCoding loadedNotify:%s hook:(void *)injectionHook];
62 | });
63 | return YES;
64 | }
65 |
66 | """ % (selectedFile, " ".join(classes), injection, flags))
67 |
68 |
69 | print "\nBuilding "+changesFile
70 | chdir( environ['HOME']+"/.apportable/SDK" )
71 |
72 | ninja = open( "Build/build.ninja" ).read();
73 | rule = "compile_c"
74 | if ( re.match( r'\.mm$', selectedFile ) ):
75 | rule = "compile_cxx"
76 |
77 | command = re.search( r'rule %s_.*\n command = ((?:.*\$\n)*.*)' % rule, ninja ).group(1)
78 | per_file_flags = re.search( r'per_file_flags = (.*)', ninja ).group(1)
79 | tmpobj = "/tmp/injection_"+environ['USER']
80 |
81 | command = re.sub( r'\$per_file_flags\b', per_file_flags, command );
82 | command = re.sub( r'\$in\b', '"%s"' % changesFile, command );
83 | command = re.sub( r'\$out\b', '"%s.o"' % tmpobj, command );
84 |
85 | command = re.sub( r'\$\n\s+', r'', command )
86 | command = re.sub( r'\$(.)', r'\1', command )
87 |
88 | prjName = re.sub( r' ', r'', projName )
89 | syslibs = "android c m v z dl log cxx stdc++ System SystemConfiguration Security CFNetwork "\
90 | "Foundation CoreFoundation CoreGraphics CoreText BridgeKit OpenAL GLESv1_CM GLESv2 EGL xml2".split(" ")
91 |
92 | command = command + ' && ./toolchain/macosx/android-ndk/toolchains/arm-linux-androideabi-*/prebuilt/darwin-x86*/arm-linux-androideabi/bin/ld "%s.o" "Build/android-armeabi-debug/%s/apk/lib/armeabi/libverde.so" %s -shared -o "%s.so"' % \
93 | (tmpobj, prjName, " ".join(map(lambda lib:'"sysroot/usr/lib/armeabi/lib%s.so"' % lib, syslibs)), tmpobj)
94 |
95 | if ( call( ["/bin/bash", "-c", command] ) ):
96 | print argv[0]+": *** Compile failed: "+changesFile
97 | exit(1)
98 |
99 | unlink( changesFile )
100 |
101 | print "\nPushing to device.."
102 | if ( call( ["/bin/bash", "-c", "./bin/adb push %s.so %s 2>&1" % (tmpobj, shlib)] ) ):
103 | print argv[0]+": *** Could not push to device"
104 | exit(1)
105 |
106 | print "Injecting code changes"
107 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/INRoseView.m:
--------------------------------------------------------------------------------
1 | //
2 | // INRoseView.m
3 | // InjectionDemo
4 | //
5 | // Created by John Holdsworth on 12/05/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | // $Id: $
8 | //
9 |
10 | #import "INRoseView.h"
11 |
12 | static float power, radius;
13 |
14 | static float psin( float phi ) {
15 | float s = sin( phi );
16 | return (s<0?-1:1) * powf( fabs( s ), power ) * radius;
17 | }
18 |
19 | static float pcos( float phi ) {
20 | return psin( phi + M_PI_2 );
21 | }
22 |
23 | @interface INRoseView ()
24 |
25 | @property (assign, nonatomic) IBOutlet UISlider *slider;
26 |
27 | @property (assign, nonatomic) float roseOffset;
28 | @property (assign, nonatomic) float colorOffset;
29 | @property (assign, nonatomic) BOOL animating;
30 |
31 | @end
32 |
33 | @implementation INRoseView
34 |
35 | - (void)awakeFromNib
36 | {
37 | [self animate:self];
38 | [[NSNotificationCenter defaultCenter]
39 | addObserver:self selector:@selector(injectionBundleLoaded:) name:@"INJECTION_BUNDLE_NOTIFICATION" object:nil];
40 | }
41 |
42 | - (void)injectionBundleLoaded:(NSNotification *)notification
43 | {
44 | NSLog( @"Injection Bundle has been loaded with code changes." );
45 | [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
46 | }
47 |
48 | - (IBAction)sliderChange:(id)sender
49 | {
50 | [self setNeedsDisplay];
51 | }
52 |
53 | // edit method and save to see your changes take effect //
54 | - (void)drawRect:(CGRect)rect
55 | {
56 | // affects "squareness" of the spiral
57 | // reference to control panel parameter
58 | power = [self.slider value];
59 |
60 | // spacing between lines
61 | float dphi = .1;
62 |
63 | // spacing between circuits
64 | float rphi = .9;
65 |
66 | // Drawing code
67 | CGContextRef cg = UIGraphicsGetCurrentContext();
68 | CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
69 |
70 | radius = rect.size.width/2.;
71 |
72 | // initial parameters for the spiral
73 | float x0 = radius, y0 = radius+12, phi0 = self.roseOffset, phi1 = self.roseOffset + M_PI,
74 | colorphi = self.colorOffset;
75 |
76 |
77 | // draw lines until angle phi0 catches up with phi1
78 | while ( phi0 < phi1 ) {
79 |
80 | // color rotates around color circle as lines are drawn
81 | CGFloat Y = .5, U = sin(colorphi), V = cos(colorphi);
82 | CGFloat R = Y + 1.4075 * V;
83 | CGFloat G = Y - 0.3455 * U - 0.7169 * V;
84 | CGFloat B = Y + 1.7790 * U;
85 |
86 | CGFloat cols[4] = {R,G,B,1.};
87 | CGColorRef cgc = CGColorCreate( cs, cols );
88 | CGContextSetStrokeColorWithColor( cg, cgc );
89 | CGColorRelease(cgc);
90 |
91 | // draw colored line across circle
92 | CGContextMoveToPoint( cg, x0 + psin( phi0 ), y0 + pcos( phi0 ) );
93 | CGContextAddLineToPoint( cg, x0 + psin( phi1 ), y0 + pcos( phi1 ) );
94 | CGContextDrawPath( cg, kCGPathStroke );
95 |
96 | // move line and color phase on.
97 | phi0 += dphi;
98 | phi1 += dphi * rphi;
99 |
100 | colorphi += dphi * 01.;
101 | }
102 |
103 | CGColorSpaceRelease(cs);
104 | }
105 |
106 | - (void)animate
107 | {
108 | if ( !self.animating )
109 | return;
110 |
111 | // edit and save to see changes
112 | self.roseOffset -= .09; // rotate rose
113 | self.colorOffset -= .13; // rotate colors
114 |
115 | [self setNeedsDisplay];
116 |
117 | // object oriented parameter reference
118 | float delay = 01.;
119 | [self performSelector:@selector(animate) withObject:nil afterDelay:.05*delay];
120 | }
121 |
122 | - (IBAction)animate:sender
123 | {
124 | if ( (self.animating = !self.animating) )
125 | [self animate];
126 | }
127 |
128 | @end
129 |
--------------------------------------------------------------------------------
/Classes/APPluginMenuController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo/en.lproj/INViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
30 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Classes/APLiveCoding.m:
--------------------------------------------------------------------------------
1 | //
2 | // APLiveCoding.m
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 03/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #ifdef ANDROID
10 |
11 | #ifndef _APLiveCoding_m_
12 | #define _APLiveCoding_m_
13 |
14 | #import "APLiveCoding.h"
15 |
16 | #import
17 | #import
18 | #import
19 | #import
20 | #import
21 |
22 | #define INLog NSLog
23 |
24 | @implementation UIAlertView(Injection)
25 |
26 | - (void)injectionDismiss
27 | {
28 | [self dismissWithClickedButtonIndex:0 animated:YES];
29 | }
30 |
31 | @end
32 |
33 | @implementation APLiveCoding
34 |
35 | + (BOOL)inject:(const char *)path {
36 | NSLog( @"Loading shared library: %s", path );
37 | void *library = dlopen( path, RTLD_NOW);
38 | if ( !library )
39 | NSLog( @"APLiveCoding: %s", dlerror() );
40 | else {
41 | int (*hook)() = dlsym( library, "injectionHook" );
42 | if ( !hook )
43 | NSLog( @"APLiveCoding: Unable to locate injectionHook() in: %s", path );
44 | else {
45 | NSString *err = [self registerSelectorsInLibrary:path containing:hook];
46 | if ( err )
47 | NSLog( @"APLiveCoding: registerSelectorsInLibrary: %@", err );
48 | return hook( path );
49 | }
50 | }
51 |
52 | return FALSE;
53 | }
54 |
55 | + (void)loadedClass:(Class)newClass notify:(BOOL)notify
56 | {
57 | const char *className = class_getName(newClass);
58 | Class oldClass = objc_getClass(className);
59 |
60 | if ( newClass != oldClass && newClass != [self class] ) {
61 | // replace implementations for class and instance methods
62 | [self swizzle:'+' className:className onto:object_getClass(oldClass) from:object_getClass(newClass)];
63 | [self swizzle:'-' className:className onto:oldClass from:newClass];
64 | }
65 |
66 | NSString *msg = [[NSString alloc] initWithFormat:@"Class '%s' injected.", className];
67 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Bundle Loaded"
68 | message:msg delegate:nil
69 | cancelButtonTitle:@"OK" otherButtonTitles:nil];
70 | [alert show];
71 |
72 | [alert performSelector:@selector(injectionDismiss) withObject:nil afterDelay:1.];
73 | }
74 |
75 | + (void)loadedNotify:(BOOL)notify hook:(void *)hook
76 | {
77 | INLog( @"Bundle loaded successfully." );
78 | [[NSNotificationCenter defaultCenter] postNotificationName:kINNotification
79 | object:nil];
80 | }
81 |
82 | + (void)swizzle:(char)which className:(const char *)className onto:(Class)oldClass from:(Class)newClass
83 | {
84 | unsigned i, mc = 0;
85 | Method *methods = class_copyMethodList(newClass, &mc);
86 |
87 | for( i=0; ie_shoff > st.st_size )
116 | return @"Bad segment header offset";
117 |
118 | Elf32_Shdr *sections = (Elf32_Shdr *)(buffer+hdr->e_shoff);
119 |
120 | // assumes names section is last...
121 | const char *names = buffer+sections[hdr->e_shnum-1].sh_offset;
122 | if ( names > buffer + st.st_size )
123 | return @"Bad section name table offset";
124 |
125 | unsigned offset = 0, nsels = 0;
126 |
127 | for ( int i=0 ; ie_shnum ; i++ ) {
128 | Elf32_Shdr *sect = §ions[i];
129 | const char *name = names+sect->sh_name;
130 | if ( strcmp( name, "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" ) == 0 ) {
131 | offset = sect->sh_addr;
132 | nsels = sect->sh_size;
133 | }
134 | }
135 |
136 | if ( !offset )
137 | return @"Unable to locate selrefs section";
138 |
139 | Dl_info info;
140 | if ( !dladdr( hook, &info ) )
141 | return @"Could not find load address";
142 |
143 | SEL *sels = (SEL *)((char *)info.dli_fbase+offset);
144 | for ( unsigned i=0 ; i
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 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo.approj/targets/InjectionDemo/Release.generated:
--------------------------------------------------------------------------------
1 | {
2 | "assets": [
3 | {
4 | "asset": "InjectionDemo/en.lproj/InfoPlist.strings",
5 | "target": "en.lproj/InfoPlist.strings"
6 | },
7 | {
8 | "asset": "InjectionDemo/Icon.png",
9 | "target": "Icon.png"
10 | }
11 | ],
12 | "config": {
13 | "APPLICATION_FULL_NAME": "InjectionDemo",
14 | "APPLICATION_IDENTIFIER": "com.johnholdsworth.InjectionDemo",
15 | "APPLICATION_NAME": "InjectionDemo",
16 | "LONG_VERSION": "1.0",
17 | "SHORT_VERSION": "1.0",
18 | "TEMPLATE_VALUES": {
19 | "EXECUTABLE_NAME": "InjectionDemo",
20 | "PRODUCT_NAME": "InjectionDemo"
21 | }
22 | },
23 | "defines": {
24 | "NS_BLOCK_ASSERTIONS": 1,
25 | "__IPHONE_OS_VERSION_MIN_REQUIRED": 50000
26 | },
27 | "deps": [
28 | "UIKit",
29 | "UIKit",
30 | "Foundation",
31 | "CoreGraphics"
32 | ],
33 | "flags": [
34 | "-DNS_BLOCK_ASSERTIONS=1",
35 | {
36 | "flag": "-DNS_BLOCK_ASSERTIONS=1",
37 | "type": "c++"
38 | },
39 | "-fobjc-arc",
40 | "-fasm-blocks",
41 | {
42 | "flag": "-std=gnu99",
43 | "not_type": "c++"
44 | },
45 | {
46 | "flag": "-fgnu-keywords",
47 | "not_type": "c++"
48 | },
49 | "-fno-asm",
50 | "-fpascal-strings",
51 | "-Wno-deprecated-declarations",
52 | "-Wreturn-type",
53 | "-Wswitch",
54 | "-Wparentheses",
55 | "-Wformat",
56 | "-Wuninitialized",
57 | "-Wunused-value",
58 | "-Wunused-variable",
59 | {
60 | "flag": "-Winvalid-offsetof",
61 | "type": "c++"
62 | },
63 | {
64 | "flag": "-Wprotocol",
65 | "type": "objc"
66 | }
67 | ],
68 | "header_paths": [
69 | {
70 | "header_path": "InjectionDemo-generated-files.hmap",
71 | "hmap": {},
72 | "type": "iquote"
73 | },
74 | {
75 | "header_path": "InjectionDemo-own-target-headers.hmap",
76 | "hmap": {},
77 | "type": "I"
78 | },
79 | {
80 | "header_path": "InjectionDemo-all-target-headers.hmap",
81 | "hmap": {},
82 | "type": "I"
83 | },
84 | {
85 | "header_path": "InjectionDemo-project-headers.hmap",
86 | "hmap": {
87 | "INAppDelegate.h": {
88 | "key": "INAppDelegate.h",
89 | "prefix": "InjectionDemo/",
90 | "suffix": "INAppDelegate.h"
91 | },
92 | "INRoseView.h": {
93 | "key": "INRoseView.h",
94 | "prefix": "InjectionDemo/",
95 | "suffix": "INRoseView.h"
96 | },
97 | "INViewController.h": {
98 | "key": "INViewController.h",
99 | "prefix": "InjectionDemo/",
100 | "suffix": "INViewController.h"
101 | },
102 | "InjectionDemo-Prefix.pch": {
103 | "key": "InjectionDemo-Prefix.pch",
104 | "prefix": "InjectionDemo/",
105 | "suffix": "InjectionDemo-Prefix.pch"
106 | }
107 | },
108 | "type": "iquote"
109 | },
110 | {
111 | "header_path": "/var/folders/nh/gqmp6jxn4tn2tyhwqdcwcpkc0000gn/T/tmpI1QPpl/BUILT_PRODUCTS_DIR/include",
112 | "type": "I"
113 | },
114 | {
115 | "header_path": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
116 | "type": "I"
117 | },
118 | {
119 | "header_path": "/var/folders/nh/gqmp6jxn4tn2tyhwqdcwcpkc0000gn/T/tmpI1QPpl/DERIVED_FILE_DIR/armv7",
120 | "type": "I"
121 | },
122 | {
123 | "header_path": "/var/folders/nh/gqmp6jxn4tn2tyhwqdcwcpkc0000gn/T/tmpI1QPpl/DERIVED_FILE_DIR",
124 | "type": "I"
125 | }
126 | ],
127 | "infoplists": [
128 | "./InjectionDemo/InjectionDemo-Info.plist"
129 | ],
130 | "libs": [],
131 | "modules": [],
132 | "pchs": [
133 | "./InjectionDemo/InjectionDemo-Prefix.pch"
134 | ],
135 | "sources": [
136 | {
137 | "defines": {},
138 | "flags": [],
139 | "header_paths": [],
140 | "language": "objc",
141 | "source": "InjectionDemo/INAppDelegate.m"
142 | },
143 | {
144 | "defines": {},
145 | "flags": [],
146 | "header_paths": [],
147 | "language": "objc",
148 | "source": "InjectionDemo/INRoseView.m"
149 | },
150 | {
151 | "defines": {},
152 | "flags": [],
153 | "header_paths": [],
154 | "language": "objc",
155 | "source": "InjectionDemo/INViewController.m"
156 | },
157 | {
158 | "defines": {},
159 | "flags": [],
160 | "header_paths": [],
161 | "language": "objc",
162 | "source": "InjectionDemo/main.m"
163 | }
164 | ],
165 | "storyboards": [],
166 | "type": "app",
167 | "version": "3",
168 | "xcdatamodels": [],
169 | "xcode_project": "InjectionDemo.xcodeproj",
170 | "xibs": [
171 | {
172 | "target": null,
173 | "xib": "InjectionDemo/en.lproj/INViewController.xib"
174 | }
175 | ]
176 | }
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo.approj/targets/InjectionDemo/Release.final:
--------------------------------------------------------------------------------
1 | {
2 | "assets": [
3 | {
4 | "asset": "InjectionDemo/en.lproj/InfoPlist.strings",
5 | "target": "en.lproj/InfoPlist.strings"
6 | },
7 | {
8 | "asset": "InjectionDemo/Icon.png",
9 | "target": "Icon.png"
10 | }
11 | ],
12 | "config": {
13 | "APPLICATION_FULL_NAME": "InjectionDemo",
14 | "APPLICATION_IDENTIFIER": "com.johnholdsworth.InjectionDemo",
15 | "APPLICATION_NAME": "InjectionDemo",
16 | "FEATURES": [
17 | "portrait"
18 | ],
19 | "ICU_CONFIG": "normal",
20 | "LONG_VERSION": "1.0",
21 | "SHORT_VERSION": "1.0",
22 | "TEMPLATE_VALUES": {
23 | "EXECUTABLE_NAME": "InjectionDemo",
24 | "PRODUCT_NAME": "InjectionDemo"
25 | }
26 | },
27 | "defines": {
28 | "NS_BLOCK_ASSERTIONS": 1,
29 | "__IPHONE_OS_VERSION_MIN_REQUIRED": 50000
30 | },
31 | "deps": [
32 | "UIKit",
33 | "UIKit",
34 | "Foundation",
35 | "CoreGraphics"
36 | ],
37 | "flags": [
38 | "-DNS_BLOCK_ASSERTIONS=1",
39 | {
40 | "flag": "-DNS_BLOCK_ASSERTIONS=1",
41 | "type": "c++"
42 | },
43 | "-fobjc-arc",
44 | "-fasm-blocks",
45 | {
46 | "flag": "-std=gnu99",
47 | "not_type": "c++"
48 | },
49 | {
50 | "flag": "-fgnu-keywords",
51 | "not_type": "c++"
52 | },
53 | "-fno-asm",
54 | "-fpascal-strings",
55 | "-Wno-deprecated-declarations",
56 | "-Wreturn-type",
57 | "-Wswitch",
58 | "-Wparentheses",
59 | "-Wformat",
60 | "-Wuninitialized",
61 | "-Wunused-value",
62 | "-Wunused-variable",
63 | {
64 | "flag": "-Winvalid-offsetof",
65 | "type": "c++"
66 | },
67 | {
68 | "flag": "-Wprotocol",
69 | "type": "objc"
70 | }
71 | ],
72 | "header_paths": [
73 | {
74 | "header_path": "InjectionDemo-generated-files.hmap",
75 | "hmap": {},
76 | "type": "iquote"
77 | },
78 | {
79 | "header_path": "InjectionDemo-own-target-headers.hmap",
80 | "hmap": {},
81 | "type": "I"
82 | },
83 | {
84 | "header_path": "InjectionDemo-all-target-headers.hmap",
85 | "hmap": {},
86 | "type": "I"
87 | },
88 | {
89 | "header_path": "InjectionDemo-project-headers.hmap",
90 | "hmap": {
91 | "INAppDelegate.h": {
92 | "key": "INAppDelegate.h",
93 | "prefix": "InjectionDemo/",
94 | "suffix": "INAppDelegate.h"
95 | },
96 | "INRoseView.h": {
97 | "key": "INRoseView.h",
98 | "prefix": "InjectionDemo/",
99 | "suffix": "INRoseView.h"
100 | },
101 | "INViewController.h": {
102 | "key": "INViewController.h",
103 | "prefix": "InjectionDemo/",
104 | "suffix": "INViewController.h"
105 | },
106 | "InjectionDemo-Prefix.pch": {
107 | "key": "InjectionDemo-Prefix.pch",
108 | "prefix": "InjectionDemo/",
109 | "suffix": "InjectionDemo-Prefix.pch"
110 | }
111 | },
112 | "type": "iquote"
113 | },
114 | {
115 | "header_path": "/var/folders/nh/gqmp6jxn4tn2tyhwqdcwcpkc0000gn/T/tmpI1QPpl/BUILT_PRODUCTS_DIR/include",
116 | "type": "I"
117 | },
118 | {
119 | "header_path": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
120 | "type": "I"
121 | },
122 | {
123 | "header_path": "/var/folders/nh/gqmp6jxn4tn2tyhwqdcwcpkc0000gn/T/tmpI1QPpl/DERIVED_FILE_DIR/armv7",
124 | "type": "I"
125 | },
126 | {
127 | "header_path": "/var/folders/nh/gqmp6jxn4tn2tyhwqdcwcpkc0000gn/T/tmpI1QPpl/DERIVED_FILE_DIR",
128 | "type": "I"
129 | }
130 | ],
131 | "infoplists": [
132 | "./InjectionDemo/InjectionDemo-Info.plist"
133 | ],
134 | "java_libs": [],
135 | "java_res_dirs": [],
136 | "java_sourcepaths": [],
137 | "java_sources": [],
138 | "libs": [],
139 | "link_flags": [],
140 | "modules": [],
141 | "pchs": [
142 | "./InjectionDemo/InjectionDemo-Prefix.pch"
143 | ],
144 | "sources": [
145 | {
146 | "defines": {},
147 | "flags": [],
148 | "header_paths": [],
149 | "language": "objc",
150 | "source": "InjectionDemo/INAppDelegate.m"
151 | },
152 | {
153 | "defines": {},
154 | "flags": [],
155 | "header_paths": [],
156 | "language": "objc",
157 | "source": "InjectionDemo/INRoseView.m"
158 | },
159 | {
160 | "defines": {},
161 | "flags": [],
162 | "header_paths": [],
163 | "language": "objc",
164 | "source": "InjectionDemo/INViewController.m"
165 | },
166 | {
167 | "defines": {},
168 | "flags": [],
169 | "header_paths": [],
170 | "language": "objc",
171 | "source": "InjectionDemo/main.m"
172 | }
173 | ],
174 | "storyboards": [],
175 | "type": "app",
176 | "version": "3",
177 | "xcdatamodels": [],
178 | "xcode_project": "InjectionDemo.xcodeproj",
179 | "xibs": [
180 | {
181 | "target": null,
182 | "xib": "InjectionDemo/en.lproj/INViewController.xib"
183 | }
184 | ]
185 | }
--------------------------------------------------------------------------------
/Classes/APPluginMenuController.m:
--------------------------------------------------------------------------------
1 | //
2 | // APPluginMenuController.m
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #import "APPluginMenuController.h"
10 |
11 | #import "APDebugController.h"
12 | #import "APLogController.h"
13 |
14 | static APPluginMenuController *apportablePlugin;
15 |
16 | @interface APPluginMenuController()
17 |
18 | @property (nonatomic,strong) IBOutlet NSMenuItem *apportableMenu;
19 | @property (nonatomic,strong) NSTextView *lastTextView;
20 |
21 | @end
22 |
23 | @implementation APPluginMenuController
24 |
25 | + (void)pluginDidLoad:(NSBundle *)plugin
26 | {
27 | static dispatch_once_t onceToken;
28 | dispatch_once(&onceToken, ^{
29 | apportablePlugin = [[self alloc] init];
30 | [[NSNotificationCenter defaultCenter] addObserver:apportablePlugin
31 | selector:@selector(applicationDidFinishLaunching:)
32 | name:NSApplicationDidFinishLaunchingNotification object:nil];
33 | });
34 | }
35 |
36 | + (APPluginMenuController *)sharedPlugin
37 | {
38 | return apportablePlugin;
39 | }
40 |
41 | - (void)applicationDidFinishLaunching:(NSNotification *)notification
42 | {
43 | if ( ![[NSBundle bundleForClass:[self class]] loadNibNamed:@"APPluginMenuController" owner:self topLevelObjects:NULL] )
44 | NSLog( @"APPluginMenuController: Could not load interface." );
45 |
46 | NSMenu *productMenu = [[[NSApp mainMenu] itemWithTitle:@"Product"] submenu];
47 | [productMenu addItem:[NSMenuItem separatorItem]];
48 | [productMenu addItem:self.apportableMenu];
49 |
50 | [[NSNotificationCenter defaultCenter] addObserver:self
51 | selector:@selector(selectionDidChange:)
52 | name:NSTextViewDidChangeSelectionNotification object:nil];
53 | }
54 |
55 | - (void)selectionDidChange:(NSNotification *)notification
56 | {
57 | id object = [notification object];
58 | if ([object isKindOfClass:NSClassFromString(@"DVTSourceTextView")] &&
59 | [[object delegate] respondsToSelector:@selector(document)])
60 | self.lastTextView = object;
61 | }
62 |
63 | - (NSString *)selectedFileSaving:(BOOL)save
64 | {
65 | NSDocument *doc = [(id)[self.lastTextView delegate] document];
66 | if ( save )
67 | [doc saveDocument:self];
68 | return [[doc fileURL] path];
69 | }
70 |
71 | - (NSString *)projectRoot
72 | {
73 | NSWindow *keyWindow = [NSApp keyWindow];
74 | if ( ![keyWindow respondsToSelector:@selector(document)] )
75 | keyWindow = self.lastKeyWindow;
76 | else
77 | self.lastKeyWindow = keyWindow;
78 |
79 | NSDocument *workspace = [(id)[self.lastKeyWindow delegate] document];
80 | if ( ![workspace isKindOfClass:NSClassFromString(@"IDEWorkspaceDocument")] )
81 | return nil;
82 |
83 | NSString *documentPath = [[workspace fileURL] path];
84 | static NSRegularExpression *projRootRegexp;
85 | if ( !projRootRegexp )
86 | projRootRegexp = [NSRegularExpression regularExpressionWithPattern:@"^(.*?)/([^/]+)\\.(xcodeproj|xcworkspace)"
87 | options:0 error:NULL];
88 |
89 | NSArray *matches = [projRootRegexp matchesInString:documentPath options:0 range:NSMakeRange(0, [documentPath length])];
90 | return [matches count] ? [documentPath substringWithRange:[matches[0] rangeAtIndex:1]] : nil;
91 | }
92 |
93 | static __weak APConsoleController *debugger;
94 | static NSString *debugProjectRoot;
95 | static int revision;
96 |
97 | - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
98 | {
99 | if ( [menuItem action] == @selector(demo:) )
100 | return YES;
101 | else if ( [menuItem action] == @selector(patch:) ) {
102 | NSString *selectedFile = [self selectedFileSaving:NO];
103 | return ([selectedFile hasSuffix:@".m"] || [selectedFile hasSuffix:@".mm"]) && debugProjectRoot;
104 | }
105 | else
106 | return [self projectRoot] != nil;
107 | }
108 |
109 | - (void)startDebugger:(NSString *)command
110 | {
111 | #pragma clang diagnostic push
112 | #pragma clang diagnostic ignored "-Warc-unsafe-retained-assign"
113 | debugger = [[APDebugController alloc] initNib:@"APDebugController"
114 | project:debugProjectRoot
115 | command:command];
116 | #pragma clang diagnostic pop
117 | }
118 |
119 | - (IBAction)prepare:sender
120 | {
121 | NSBundle *bundle = [NSBundle bundleForClass:[self class]];
122 | (void)[[APConsoleController alloc] initNib:@"APConsoleWindow" project:[self projectRoot]
123 | command:[NSString stringWithFormat:@"\"%@\" \"%@\" 2>&1",
124 | [bundle pathForResource:@"prepare" ofType:@"py"],
125 | [bundle pathForResource:@"APLiveCoding" ofType:@"m"]]];
126 | }
127 |
128 | - (IBAction)debug:sender
129 | {
130 | debugProjectRoot = [self projectRoot];
131 | [self startDebugger:@"apportable debug"];
132 | [debugger sendTask:@"c\n"];
133 | }
134 |
135 | - (IBAction)attach:sender
136 | {
137 | if ( !debugProjectRoot )
138 | debugProjectRoot = [self projectRoot];
139 | [self startDebugger:@"apportable just_attach"];
140 | }
141 |
142 | - (IBAction)patch:sender
143 | {
144 | if ( !debugger && sender )
145 | [self attach:sender];
146 |
147 | if ( debugger.task && [debugger.console.string rangeOfString:@"(gdb)"].location == NSNotFound ) {
148 | [self performSelector:@selector(patch:) withObject:nil afterDelay:.5];
149 | return;
150 | }
151 |
152 | if ( !debugProjectRoot )
153 | debugProjectRoot = [self projectRoot];
154 |
155 | NSString *shlib = [NSString stringWithFormat:@"/data/local/tmp/APLiveCoding%d.so", revision++];
156 | NSTask *task = [[NSTask alloc] init];
157 |
158 | task.launchPath = @"/bin/bash";
159 | task.currentDirectoryPath = debugProjectRoot;
160 | task.arguments = @[@"-c", [NSString stringWithFormat:@"\"%@\" \"%@\" \"%@\" \"%@\" 2>&1",
161 | [[NSBundle bundleForClass:[self class]] pathForResource:@"inject" ofType:@"py"],
162 | debugProjectRoot, shlib, [self selectedFileSaving:YES]]];
163 |
164 | task.standardInput = [[NSPipe alloc] init];
165 | task.standardOutput = [[NSPipe alloc] init];
166 |
167 | NSString *gdbLoadCommand = [NSString stringWithFormat:@"p [APLiveCoding inject:\"%@\"]\nc\n", shlib];
168 | [debugger runTask:task sendOnCompletetion:gdbLoadCommand];
169 | }
170 |
171 | - (IBAction)load:sender
172 | {
173 | debugProjectRoot = [self projectRoot];
174 | (void)[[APConsoleController alloc] initNib:@"APConsoleWindow" project:[self projectRoot]
175 | command:@"apportable load"];
176 | }
177 |
178 | - (IBAction)kill:sender
179 | {
180 | (void)[[APDebugController alloc] initNib:@"APDebugController" project:[self projectRoot]
181 | command:@"apportable kill"];
182 | }
183 |
184 | - (IBAction)log:sender
185 | {
186 | (void)[[APLogController alloc] initNib:@"APLogWindow" project:[self projectRoot]
187 | command:@"apportable log"];
188 | }
189 |
190 | - (IBAction)demo:(id)sender
191 | {
192 | [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:[[NSBundle bundleForClass:[self class]] pathForResource:@"InjectionDemo/InjectionDemo" ofType:@"xcodeproj"]]];
193 | }
194 |
195 | @end
196 |
--------------------------------------------------------------------------------
/Classes/APLogWindow.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 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/Classes/APConsoleController.m:
--------------------------------------------------------------------------------
1 | //
2 | // APConsoleController.m
3 | // ApportablePlugin
4 | //
5 | // Created by John Holdsworth on 01/05/2014.
6 | // Copyright (c) 2014 John Holdsworth. All rights reserved.
7 | //
8 |
9 | #import "APConsoleController.h"
10 |
11 | static NSMutableArray *visibleControllers;
12 |
13 | @interface APConsoleController()
14 |
15 | @property (nonatomic,strong) IBOutlet NSWindow *window;
16 | @property (nonatomic,strong) IBOutlet NSMenuItem *separator;
17 | @property (nonatomic,strong) IBOutlet NSMenuItem *menuItem;
18 |
19 | @property (nonatomic,strong) NSMutableArray *inputHistory;
20 | @property (nonatomic,assign) NSUInteger historyPointer;
21 | @property (nonatomic,assign) NSUInteger startBuffered;
22 |
23 | @end
24 |
25 | @implementation APConsoleController
26 |
27 | - (instancetype)initNib:(NSString *)nibName project:(NSString *)projectRoot command:(NSString *)command
28 | {
29 | if ( (self = [super init]) && projectRoot ) {
30 | if ( !visibleControllers )
31 | visibleControllers = [[NSMutableArray alloc] init];
32 | [visibleControllers addObject:self];
33 |
34 | if ( ![[NSBundle bundleForClass:[self class]] loadNibNamed:nibName owner:self topLevelObjects:NULL] )
35 | NSLog( @"APConsoleController: Could not load interface '%@'", nibName );
36 |
37 | if ( self.window ) {
38 | // need to add to Windows menu manually
39 | // for some reason this is not reliable
40 | self.menuItem.title = command;
41 |
42 | NSMenu *windowMenu = [self windowMenu];
43 | NSInteger where = [windowMenu indexOfItemWithTitle:@"Bring All to Front"];
44 | if ( where <= 0 )
45 | NSLog( @"AppportablePlugin: Could not locate Window menu item" );
46 | else
47 | {
48 | [windowMenu insertItem:self.separator atIndex:where+1];
49 | [windowMenu insertItem:self.menuItem atIndex:where+2];
50 | }
51 |
52 | self.window.title = command;
53 | self.window.representedFilename = projectRoot;
54 | [self.window makeKeyAndOrderFront:self];
55 | }
56 |
57 | self.task = [[NSTask alloc] init];
58 | self.task.launchPath = @"/bin/bash";
59 | self.task.currentDirectoryPath = projectRoot;
60 | self.task.arguments = @[@"-c", [NSString stringWithFormat:@"export PATH="
61 | "\"~/.apportable/SDK/bin:$PATH\" && exec %@ 2>&1", command]];
62 |
63 | self.task.standardInput = [[NSPipe alloc] init];
64 | self.task.standardOutput = [[NSPipe alloc] init];
65 |
66 | [self runTask:self.task sendOnCompletetion:nil];
67 | }
68 |
69 | return self;
70 | }
71 |
72 | - (NSMenu *)windowMenu {
73 | return [[[NSApp mainMenu] itemWithTitle:@"Window"] submenu];
74 | }
75 |
76 | /*
77 | * Thanks to NSTask tutorial by Andy Pereira: http://www.raywenderlich.com/36537/nstask-tutorial
78 | */
79 |
80 | - (void)runTask:(NSTask *)aTask sendOnCompletetion:(NSString *)gdbCommand
81 | {
82 | dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
83 | dispatch_async(backgroundQueue, ^{
84 |
85 | @try {
86 | NSFileHandle *readHandle = [aTask.standardOutput fileHandleForReading];
87 | [readHandle waitForDataInBackgroundAndNotify];
88 |
89 | id observer = [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
90 | object:readHandle queue:nil
91 | usingBlock:^(NSNotification *notification) {
92 |
93 | NSData *outputData = [readHandle availableData];
94 | NSString *output = [[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding];
95 |
96 | if ( output )
97 | [self insertText:output];
98 |
99 | [readHandle waitForDataInBackgroundAndNotify];
100 | }];
101 |
102 | [aTask launch];
103 | [aTask waitUntilExit];
104 |
105 | dispatch_sync(dispatch_get_main_queue(), ^{
106 | BOOL succeeded = [aTask terminationStatus] == EXIT_SUCCESS;
107 | if ( !self.window && !gdbCommand )
108 | [self performSelector:@selector(windowWillClose:) withObject:nil afterDelay:succeeded?0.:5.];
109 | else if ( succeeded ) {
110 | if ( !gdbCommand ) {
111 | [self.window performSelector:@selector(close) withObject:nil afterDelay:3.];
112 | self.task = nil;
113 | }
114 | else {
115 | [self.task interrupt];
116 | [self performSelector:@selector(handleTextViewInput:) withObject:gdbCommand afterDelay:.1];
117 | }
118 | }
119 | });
120 |
121 | [[NSNotificationCenter defaultCenter] removeObserver:observer];
122 | }
123 | @catch (NSException *exception) {
124 | self.console.string = [NSString stringWithFormat:@"Problem Running Task: %@", [exception description]];
125 | }
126 | });
127 | }
128 |
129 | /*
130 | * insert text into text view, overridden for filtering in APLogController.m
131 | */
132 | - (void)insertText:(NSString *)output
133 | {
134 | dispatch_async(dispatch_get_main_queue(), ^{
135 | [self.console setSelectedRange:NSMakeRange([self.console.string length], 0)];
136 | [self.console insertText:output];
137 | });
138 | }
139 |
140 | /*
141 | * key down event in TextView, relay to running command
142 | */
143 | - (BOOL)handleTextViewInput:(NSString *)characters
144 | {
145 | NSString *input = [characters stringByReplacingOccurrencesOfString:@"\r" withString:@"\n"];
146 |
147 | if ( !self.inputHistory )
148 | self.inputHistory = [[NSMutableArray alloc] init];
149 |
150 | if ( !self.startBuffered )
151 | self.startBuffered = [[self.console selectedRanges][0] rangeValue].location;
152 |
153 | switch ( [input characterAtIndex:0] ) {
154 |
155 | // contrl-a
156 | case 0x01:
157 | [self.console setSelectedRange:NSMakeRange(self.startBuffered, 0)];
158 | return TRUE;
159 |
160 | // control-c
161 | case 0x03:
162 | [self.task interrupt];
163 | self.startBuffered = 0;
164 | return TRUE;
165 |
166 | // up arrow
167 | case 0xF700:
168 | if ( self.historyPointer > 0 ) {
169 | if ( self.historyPointer == [self.inputHistory count] )
170 | [self.inputHistory addObject:[self bufferedInput]];
171 | self.historyPointer--;
172 | [self useHistory];
173 | }
174 | return TRUE;
175 |
176 | // down arrow
177 | case 0xF701:
178 | if ( self.historyPointer+1 < [self.inputHistory count] ) {
179 | self.historyPointer++;
180 | [self useHistory];
181 | }
182 | return TRUE;
183 |
184 | default:
185 | if ( [input characterAtIndex:[input length]-1] != '\n' )
186 | return FALSE;
187 | else {
188 | [self sendTask:[[self bufferedInput] stringByAppendingString:input]];
189 | if ( [[self bufferedInput] length] )
190 | [self.inputHistory addObject:[self bufferedInput]];
191 | self.historyPointer = [self.inputHistory count];
192 | [self insertText:input];
193 | self.startBuffered = 0;
194 | return TRUE;
195 | }
196 | }
197 | }
198 |
199 | - (NSString *)bufferedInput
200 | {
201 | return [self.console.string substringWithRange:[self bufferedRange]];
202 | }
203 |
204 | - (NSRange)bufferedRange
205 | {
206 | NSUInteger end = [self.console.string length], start = MIN(self.startBuffered, end);
207 | return NSMakeRange(start, end>start ? end-start : 0);
208 | }
209 |
210 | - (void)useHistory
211 | {
212 | [self.console replaceCharactersInRange:[self bufferedRange]
213 | withString:self.inputHistory[self.historyPointer]];
214 | [self.console setSelectedRange:NSMakeRange([self.console.string length], 0)];
215 | }
216 |
217 | - (void)sendTask:(NSString *)input
218 | {
219 | @try {
220 | NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding];
221 | [[self.task.standardInput fileHandleForWriting] writeData:data];
222 | }
223 | @catch (NSException *exception) {
224 | NSLog( @"Problem writing to task: %@", [exception description] );
225 | }
226 | }
227 |
228 | - (void)windowWillClose:(NSNotification *)notification
229 | {
230 | [self.task terminate];
231 |
232 | NSMenu *windowMenu = [self windowMenu];
233 | if ( [windowMenu indexOfItem:self.separator] != -1 )
234 | [windowMenu removeItem:self.separator];
235 | if ( [windowMenu indexOfItem:self.menuItem] != -1 )
236 | [windowMenu removeItem:self.menuItem];
237 |
238 | [visibleControllers removeObject:self];
239 | }
240 |
241 | @end
242 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | BB3FC289155F2D5F007AA89B /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = BB3FC288155F2D5F007AA89B /* Icon.png */; };
11 | BB82EB41156C367E00E7A6FB /* INViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BB82EB3F156C367E00E7A6FB /* INViewController.xib */; };
12 | BBBA5B22155EB59000421DA4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBBA5B21155EB59000421DA4 /* UIKit.framework */; };
13 | BBBA5B24155EB59000421DA4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBBA5B23155EB59000421DA4 /* Foundation.framework */; };
14 | BBBA5B26155EB59000421DA4 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBBA5B25155EB59000421DA4 /* CoreGraphics.framework */; };
15 | BBBA5B2C155EB59000421DA4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BBBA5B2A155EB59000421DA4 /* InfoPlist.strings */; };
16 | BBBA5B2E155EB59000421DA4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BBBA5B2D155EB59000421DA4 /* main.m */; };
17 | BBBA5B32155EB59000421DA4 /* INAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BBBA5B31155EB59000421DA4 /* INAppDelegate.m */; };
18 | BBBA5B3B155EB59000421DA4 /* INViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BBBA5B3A155EB59000421DA4 /* INViewController.m */; };
19 | BBBA5B43155EB5D300421DA4 /* INRoseView.m in Sources */ = {isa = PBXBuildFile; fileRef = BBBA5B42155EB5D300421DA4 /* INRoseView.m */; };
20 | /* End PBXBuildFile section */
21 |
22 | /* Begin PBXFileReference section */
23 | BB3FC288155F2D5F007AA89B /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; };
24 | BB82EB40156C367E00E7A6FB /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/INViewController.xib; sourceTree = ""; };
25 | BBBA5B1D155EB59000421DA4 /* InjectionDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InjectionDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
26 | BBBA5B21155EB59000421DA4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
27 | BBBA5B23155EB59000421DA4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
28 | BBBA5B25155EB59000421DA4 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
29 | BBBA5B29155EB59000421DA4 /* InjectionDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "InjectionDemo-Info.plist"; sourceTree = ""; };
30 | BBBA5B2B155EB59000421DA4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
31 | BBBA5B2D155EB59000421DA4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
32 | BBBA5B2F155EB59000421DA4 /* InjectionDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "InjectionDemo-Prefix.pch"; sourceTree = ""; };
33 | BBBA5B30155EB59000421DA4 /* INAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = INAppDelegate.h; sourceTree = ""; };
34 | BBBA5B31155EB59000421DA4 /* INAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = INAppDelegate.m; sourceTree = ""; };
35 | BBBA5B39155EB59000421DA4 /* INViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = INViewController.h; sourceTree = ""; };
36 | BBBA5B3A155EB59000421DA4 /* INViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = INViewController.m; sourceTree = ""; };
37 | BBBA5B41155EB5D300421DA4 /* INRoseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INRoseView.h; sourceTree = ""; };
38 | BBBA5B42155EB5D300421DA4 /* INRoseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = INRoseView.m; sourceTree = ""; };
39 | /* End PBXFileReference section */
40 |
41 | /* Begin PBXFrameworksBuildPhase section */
42 | BBBA5B1A155EB59000421DA4 /* Frameworks */ = {
43 | isa = PBXFrameworksBuildPhase;
44 | buildActionMask = 2147483647;
45 | files = (
46 | BBBA5B22155EB59000421DA4 /* UIKit.framework in Frameworks */,
47 | BBBA5B24155EB59000421DA4 /* Foundation.framework in Frameworks */,
48 | BBBA5B26155EB59000421DA4 /* CoreGraphics.framework in Frameworks */,
49 | );
50 | runOnlyForDeploymentPostprocessing = 0;
51 | };
52 | /* End PBXFrameworksBuildPhase section */
53 |
54 | /* Begin PBXGroup section */
55 | BBBA5B12155EB59000421DA4 = {
56 | isa = PBXGroup;
57 | children = (
58 | BBBA5B27155EB59000421DA4 /* InjectionDemo */,
59 | BBBA5B20155EB59000421DA4 /* Frameworks */,
60 | BBBA5B1E155EB59000421DA4 /* Products */,
61 | );
62 | sourceTree = "";
63 | };
64 | BBBA5B1E155EB59000421DA4 /* Products */ = {
65 | isa = PBXGroup;
66 | children = (
67 | BBBA5B1D155EB59000421DA4 /* InjectionDemo.app */,
68 | );
69 | name = Products;
70 | sourceTree = "";
71 | };
72 | BBBA5B20155EB59000421DA4 /* Frameworks */ = {
73 | isa = PBXGroup;
74 | children = (
75 | BBBA5B21155EB59000421DA4 /* UIKit.framework */,
76 | BBBA5B23155EB59000421DA4 /* Foundation.framework */,
77 | BBBA5B25155EB59000421DA4 /* CoreGraphics.framework */,
78 | );
79 | name = Frameworks;
80 | sourceTree = "";
81 | };
82 | BBBA5B27155EB59000421DA4 /* InjectionDemo */ = {
83 | isa = PBXGroup;
84 | children = (
85 | BBBA5B41155EB5D300421DA4 /* INRoseView.h */,
86 | BBBA5B42155EB5D300421DA4 /* INRoseView.m */,
87 | BBBA5B30155EB59000421DA4 /* INAppDelegate.h */,
88 | BBBA5B31155EB59000421DA4 /* INAppDelegate.m */,
89 | BBBA5B39155EB59000421DA4 /* INViewController.h */,
90 | BBBA5B3A155EB59000421DA4 /* INViewController.m */,
91 | BB82EB3F156C367E00E7A6FB /* INViewController.xib */,
92 | BBBA5B28155EB59000421DA4 /* Supporting Files */,
93 | );
94 | path = InjectionDemo;
95 | sourceTree = "";
96 | };
97 | BBBA5B28155EB59000421DA4 /* Supporting Files */ = {
98 | isa = PBXGroup;
99 | children = (
100 | BBBA5B2F155EB59000421DA4 /* InjectionDemo-Prefix.pch */,
101 | BBBA5B29155EB59000421DA4 /* InjectionDemo-Info.plist */,
102 | BBBA5B2A155EB59000421DA4 /* InfoPlist.strings */,
103 | BBBA5B2D155EB59000421DA4 /* main.m */,
104 | BB3FC288155F2D5F007AA89B /* Icon.png */,
105 | );
106 | name = "Supporting Files";
107 | sourceTree = "";
108 | };
109 | /* End PBXGroup section */
110 |
111 | /* Begin PBXNativeTarget section */
112 | BBBA5B1C155EB59000421DA4 /* InjectionDemo */ = {
113 | isa = PBXNativeTarget;
114 | buildConfigurationList = BBBA5B3E155EB59000421DA4 /* Build configuration list for PBXNativeTarget "InjectionDemo" */;
115 | buildPhases = (
116 | BBBA5B19155EB59000421DA4 /* Sources */,
117 | BBBA5B1A155EB59000421DA4 /* Frameworks */,
118 | BBBA5B1B155EB59000421DA4 /* Resources */,
119 | );
120 | buildRules = (
121 | );
122 | dependencies = (
123 | );
124 | name = InjectionDemo;
125 | productName = InjectionDemo;
126 | productReference = BBBA5B1D155EB59000421DA4 /* InjectionDemo.app */;
127 | productType = "com.apple.product-type.application";
128 | };
129 | /* End PBXNativeTarget section */
130 |
131 | /* Begin PBXProject section */
132 | BBBA5B14155EB59000421DA4 /* Project object */ = {
133 | isa = PBXProject;
134 | attributes = {
135 | CLASSPREFIX = IN;
136 | LastUpgradeCheck = 0430;
137 | };
138 | buildConfigurationList = BBBA5B17155EB59000421DA4 /* Build configuration list for PBXProject "InjectionDemo" */;
139 | compatibilityVersion = "Xcode 3.2";
140 | developmentRegion = English;
141 | hasScannedForEncodings = 0;
142 | knownRegions = (
143 | en,
144 | );
145 | mainGroup = BBBA5B12155EB59000421DA4;
146 | productRefGroup = BBBA5B1E155EB59000421DA4 /* Products */;
147 | projectDirPath = "";
148 | projectRoot = "";
149 | targets = (
150 | BBBA5B1C155EB59000421DA4 /* InjectionDemo */,
151 | );
152 | };
153 | /* End PBXProject section */
154 |
155 | /* Begin PBXResourcesBuildPhase section */
156 | BBBA5B1B155EB59000421DA4 /* Resources */ = {
157 | isa = PBXResourcesBuildPhase;
158 | buildActionMask = 2147483647;
159 | files = (
160 | BBBA5B2C155EB59000421DA4 /* InfoPlist.strings in Resources */,
161 | BB3FC289155F2D5F007AA89B /* Icon.png in Resources */,
162 | BB82EB41156C367E00E7A6FB /* INViewController.xib in Resources */,
163 | );
164 | runOnlyForDeploymentPostprocessing = 0;
165 | };
166 | /* End PBXResourcesBuildPhase section */
167 |
168 | /* Begin PBXSourcesBuildPhase section */
169 | BBBA5B19155EB59000421DA4 /* Sources */ = {
170 | isa = PBXSourcesBuildPhase;
171 | buildActionMask = 2147483647;
172 | files = (
173 | BBBA5B2E155EB59000421DA4 /* main.m in Sources */,
174 | BBBA5B32155EB59000421DA4 /* INAppDelegate.m in Sources */,
175 | BBBA5B3B155EB59000421DA4 /* INViewController.m in Sources */,
176 | BBBA5B43155EB5D300421DA4 /* INRoseView.m in Sources */,
177 | );
178 | runOnlyForDeploymentPostprocessing = 0;
179 | };
180 | /* End PBXSourcesBuildPhase section */
181 |
182 | /* Begin PBXVariantGroup section */
183 | BB82EB3F156C367E00E7A6FB /* INViewController.xib */ = {
184 | isa = PBXVariantGroup;
185 | children = (
186 | BB82EB40156C367E00E7A6FB /* en */,
187 | );
188 | name = INViewController.xib;
189 | sourceTree = "";
190 | };
191 | BBBA5B2A155EB59000421DA4 /* InfoPlist.strings */ = {
192 | isa = PBXVariantGroup;
193 | children = (
194 | BBBA5B2B155EB59000421DA4 /* en */,
195 | );
196 | name = InfoPlist.strings;
197 | sourceTree = "";
198 | };
199 | /* End PBXVariantGroup section */
200 |
201 | /* Begin XCBuildConfiguration section */
202 | BBBA5B3C155EB59000421DA4 /* Debug */ = {
203 | isa = XCBuildConfiguration;
204 | buildSettings = {
205 | ALWAYS_SEARCH_USER_PATHS = NO;
206 | ARCHS = "$(ARCHS_STANDARD_32_BIT)";
207 | CLANG_ENABLE_OBJC_ARC = YES;
208 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
209 | COPY_PHASE_STRIP = NO;
210 | GCC_C_LANGUAGE_STANDARD = gnu99;
211 | GCC_DYNAMIC_NO_PIC = NO;
212 | GCC_OPTIMIZATION_LEVEL = 0;
213 | GCC_PREPROCESSOR_DEFINITIONS = (
214 | "DEBUG=1",
215 | "$(inherited)",
216 | );
217 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
218 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
219 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
220 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
221 | GCC_WARN_UNUSED_VARIABLE = YES;
222 | SDKROOT = iphoneos;
223 | TARGETED_DEVICE_FAMILY = "1,2";
224 | };
225 | name = Debug;
226 | };
227 | BBBA5B3D155EB59000421DA4 /* Release */ = {
228 | isa = XCBuildConfiguration;
229 | buildSettings = {
230 | ALWAYS_SEARCH_USER_PATHS = NO;
231 | ARCHS = "$(ARCHS_STANDARD_32_BIT)";
232 | CLANG_ENABLE_OBJC_ARC = YES;
233 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
234 | COPY_PHASE_STRIP = YES;
235 | GCC_C_LANGUAGE_STANDARD = gnu99;
236 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
237 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
238 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
239 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
240 | GCC_WARN_UNUSED_VARIABLE = YES;
241 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
242 | SDKROOT = iphoneos;
243 | TARGETED_DEVICE_FAMILY = "1,2";
244 | VALIDATE_PRODUCT = YES;
245 | };
246 | name = Release;
247 | };
248 | BBBA5B3F155EB59000421DA4 /* Debug */ = {
249 | isa = XCBuildConfiguration;
250 | buildSettings = {
251 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
252 | GCC_PREFIX_HEADER = "InjectionDemo/InjectionDemo-Prefix.pch";
253 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
254 | INFOPLIST_FILE = "InjectionDemo/InjectionDemo-Info.plist";
255 | PRODUCT_NAME = "$(TARGET_NAME)";
256 | WRAPPER_EXTENSION = app;
257 | };
258 | name = Debug;
259 | };
260 | BBBA5B40155EB59000421DA4 /* Release */ = {
261 | isa = XCBuildConfiguration;
262 | buildSettings = {
263 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
264 | GCC_PREFIX_HEADER = "InjectionDemo/InjectionDemo-Prefix.pch";
265 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
266 | INFOPLIST_FILE = "InjectionDemo/InjectionDemo-Info.plist";
267 | PRODUCT_NAME = "$(TARGET_NAME)";
268 | WRAPPER_EXTENSION = app;
269 | };
270 | name = Release;
271 | };
272 | /* End XCBuildConfiguration section */
273 |
274 | /* Begin XCConfigurationList section */
275 | BBBA5B17155EB59000421DA4 /* Build configuration list for PBXProject "InjectionDemo" */ = {
276 | isa = XCConfigurationList;
277 | buildConfigurations = (
278 | BBBA5B3C155EB59000421DA4 /* Debug */,
279 | BBBA5B3D155EB59000421DA4 /* Release */,
280 | );
281 | defaultConfigurationIsVisible = 0;
282 | defaultConfigurationName = Release;
283 | };
284 | BBBA5B3E155EB59000421DA4 /* Build configuration list for PBXNativeTarget "InjectionDemo" */ = {
285 | isa = XCConfigurationList;
286 | buildConfigurations = (
287 | BBBA5B3F155EB59000421DA4 /* Debug */,
288 | BBBA5B40155EB59000421DA4 /* Release */,
289 | );
290 | defaultConfigurationIsVisible = 0;
291 | defaultConfigurationName = Release;
292 | };
293 | /* End XCConfigurationList section */
294 | };
295 | rootObject = BBBA5B14155EB59000421DA4 /* Project object */;
296 | }
297 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo.approj/targets/InjectionDemo/Release.overrides.json:
--------------------------------------------------------------------------------
1 | {
2 | "configuration_format_version": 2,
3 |
4 |
5 |
6 | // Dictionary of global configuration parameters.
7 | // These parameters are not taken from the xcode project,
8 | // so they need to be supplied by the user.
9 | "config": {
10 |
11 | // A short name to identify the application.
12 | // Used to decide the APK filename, but not shown
13 | // anywhere in the app.
14 | // "APPLICATION_NAME": "",
15 |
16 | // The name of the application to display in the launcher
17 | // "APPLICATION_FULL_NAME": "",
18 |
19 | // The unique identifier for the application.
20 | // Normally this is in reverse DNS notation, e.g.,
21 | // "com.apportable.Spin"
22 | // "APPLICATION_IDENTIFIER": "",
23 |
24 | // Short version name for the app, e.g., "1.0"
25 | // "SHORT_VERSION": "",
26 |
27 | // If you're using Google Play Game Services, put in the client id (a numerical value)
28 | // "GOOGLE_PLAY_CLIENT_ID": "1234567"
29 |
30 | // A list of features needed on the target platform.
31 | // Common features include:
32 | // "accelerometer"
33 | // "access_network_state"
34 | // "access_wifi_state"
35 | // "atc_slow_surface"
36 | // "billing"
37 | // "c2dm_receive"
38 | // "check_license"
39 | // "get_accounts"
40 | // "large_heap"
41 | // "live_wallpaper"
42 | // "multitouch"
43 | // "multitouch_distinct"
44 | // "multitouch_jazzhand"
45 | // "NFC"
46 | // "no_internet"
47 | // "notifications"
48 | // "opengles2"
49 | // "portrait"
50 | // "prefer_external_storage"
51 | // "read_phone_state"
52 | // "stencil_buffer"
53 | // "touch_filter_move"
54 | // "touchscreen"
55 | // "true_color"
56 | // "vibrate"
57 | // "wake_lock"
58 | // "write_external_storage"
59 | // "write_settings"
60 | // "xperia"
61 | //"FEATURES": []
62 |
63 | // Preferred way of handling URLs in the code.
64 | // Leave it null for most cases.
65 | //"URL_SCHEME": null,
66 |
67 | // Key to receive remote notifications on the device.
68 | //"REMOTE_NOTIFICATION_KEY": "",
69 |
70 | // The method for adjusting the splash screen (Default.png)
71 | // to fit the native device resolution. Options are:
72 | // "aspect_fill"
73 | // "aspect_fit"
74 | // "letterbox" (the default)
75 | // "native"
76 | // "stretch"
77 | //"SPLASH_SCREEN_TYPE": "letterbox",
78 |
79 | // Path to the image to use for the app's icon.
80 | // Usually something like "./Icon.png".
81 | // "ICON": "",
82 |
83 | // A regular expression to determine which assets
84 | // should be compressed when building the final app.
85 | // By default, text assets are not compressed. Use
86 | // this to compress certain text assets. For example,
87 | // ".*.plist$" will cause all files ending in ".plist"
88 | // to be compressed.
89 | //"COMPRESSED_ASSETS_PATTERN": "",
90 | //"UNCOMPRESSED_ASSETS_PATTERN": "",
91 |
92 | // Automatically convert audio to oggs. Defaults to true.
93 | // Can be configured per file with add params and "convert"
94 | // field or with the "CONVERTABLE_AUDIO_EXTENSIONS" flag.
95 | //"CONVERT_AUDIO": false,
96 |
97 | // Comma-separated list of file extensions that are safe to convert to OGGs
98 | //"CONVERTABLE_AUDIO_EXTENSIONS": ".mp3,.wav,.caf,.m4a",
99 |
100 | // Compress PNGs with pngcrush. Defaults to true.
101 | //"COMPRESS_PNGS": false,
102 |
103 | // This will cache all converted assets (pngs, oggs, etc)
104 | // into the approj directory. This is useful if you want to
105 | // persist the changes across builds or check them in source
106 | // control so they are uses by Linux based builders. Note that
107 | // if you disable this, your final build params file will contain
108 | // absolute paths and should not be checked in.
109 | // Defaults to true.
110 | //"STORE_ASSESTS_IN_APPROJ": false,
111 |
112 | // ICU_CONFIGS specifies the ICU (International Components for Unicode) database for the project
113 | // The default is "normal" which meets the needs of most apps using NS Format classes and/or localization
114 | // "full" will specify a complete database
115 | // "none" will specify no database. Be careful - It's not always intutitive when Foundation depends upon ICU
116 |
117 | // The normal table is 2762244 bytes compressed and 8622768 uncompressed
118 | // The full table is 8396438 bytes compressed and 20775168 uncompressed
119 |
120 | // You can also configure and build your own ICU table at http://apps.icu-project.org/datacustom/ICUData50.html
121 | // Add it to the "add_params" "assets" section and specify the path to ICU_CONFIG
122 | // For example TBD
123 |
124 | "ICU_CONFIG" : "normal",
125 |
126 | //Manifest extras
127 | //A list of .xml files that contain snippets to be included in AndroidManifest.xml
128 | //inside the , and tags respectively.
129 | //"MANIFEST_EXTRAS": [],
130 | //"ACTIVITY_MANIFEST_EXTRAS": [],
131 | //"APPLICATION_MANIFEST_EXTRAS": [],
132 |
133 | // Advanced Options
134 | //"NOTIFICATION_ICON":"",
135 | //"TEMPLATE_VALUES":{},
136 | //"OGGENC_OPTIONS":"",
137 | //"AFCONVERT_OPTIONS":"",
138 | //"PNGCRUSH_OPTIONS":"",
139 | //"MIN_SDK": 9,
140 | //"C2DM_SENDER": "",
141 | //"HARDWARE_ACCELERATED": "",
142 | //"NFC_SCHEME": "",
143 | //"MPMETRICS_API_KEY": "",
144 | //"RENAME_TARGET": true,
145 |
146 | },
147 |
148 | // Sometimes header include path ordering matters. If so, put the ordering constraints into this
149 | // array. For example, if "./foo" has to come before "./bar", you would put:
150 | // ["./foo", "./bar"]
151 | // Note that "./some_other_include_path" doesn't appear in the list, since its order doesn't matter.
152 | // You can also specify "*", which matches everything not already constrained. This lets you put
153 | // particular paths at the beginning or end of the list. For example, ["./foo", "*", "./bar"].
154 | "header_ordering_constraints": [],
155 |
156 | // Edit this section to add and replace files and parameters to the generated settings for this project.
157 | // If the generated settings for a particular file are incorrect, simply add it here with the settings
158 | // you need and the final build parameters will only included the version specified here.
159 | "add_params": {
160 | // A list of pch files to -include.
161 | // PCH files can be either a string, e.g., "./MyApp-Prefix.pch",
162 | // or a dictionary specifying the pch and the environment where
163 | // it should be used, e.g.,
164 | // {"pch": "./prefix-android.pch", "env": {"TARGET_OS": "android"}}
165 | "pchs": [],
166 |
167 | // A list of header search paths
168 | // e.g. "./External/facebook-sdk/include"
169 | "header_paths": [],
170 |
171 | // A list of global compile flags for the project.
172 | // Flags can be either a string, e.g. "-Werror-shadow",
173 | // or a dictionary specifying the flag and the environment
174 | // that it should be used in, e.g.,
175 | // {"flag": "-fstack-protector", "env": {"TARGET_OS": "android"}}
176 | "flags": [],
177 |
178 | // A dictionary of global compiler definitions for the project.
179 | // Defines can be a simple key-value pair, e.g., "DEBUG": 1,
180 | // or the value can be a dictionary specifying the value and the
181 | // environment that it should be used in, e.g.,
182 | // "SOME_DEFINE": {"value": "\"yep its building on android\"", "env": {"TARGET_OS": "android"}}
183 | "defines": {},
184 |
185 | // A list of dependencies. Typically these correspond to
186 | // frameworks in the xcode project.
187 | "deps": [],
188 |
189 | // A list of source files (e.g. .m, .mm, .c, .cc, and .cpp) files to build.
190 | // Source files can be a string, e.g. "./main.c", or a dictionary specifying
191 | // the file, any special flags, any defines, and the environment
192 | // where it should be compiled, e.g.,
193 | // {"source": "./PngImageLoader.m", "flags": ["-fstack-protector"], "defines": {"PNG": 1}, "env": {"TARGET_TEXTURE_FMT": "png"}}
194 | "sources": [],
195 |
196 | // A list of glob inclusion filters for additional files.
197 | // This can also be used to replace flags on multiple files.
198 | // e.g. {"source":"./Server/Level_[0-9].m","flags": ["-fno-objc-arc"], "defines": {"NDEBUG": 1}}
199 | "sources_glob":[],
200 |
201 | // A list of assets to package with the application.
202 | // Assets can be either a string, e.g., "./Info.plist",
203 | // or a dictionary specifying the asset and the target path it should be written to
204 | // in the app, and the environment it should be included with, e.g.,
205 | // {"asset": "./Resources/cube_texture.pvr.ccz", "target": "Bundled Resources/", "env": {"TARGET_TEXTURE_FMT": "pvr"}}
206 | // or a dictionary like above, but instead specifying the full target file name
207 | // for the asset, e.g.,
208 | // {"asset": "./Resources/cube_texture.pvr.ccz", "target": "Bundled Resources/cube_texture.pvr.gz", "env": {"TARGET_TEXTURE_FMT": "pvr"}}
209 | "assets": [],
210 |
211 | // A list of Info.plist files. The first one in the list will be the one we consider the main Info.plist.
212 | "infoplists": [],
213 |
214 | //A list of specific java sources file to compile
215 | "java_sources": [],
216 |
217 | //A list of the java root source directories
218 | "java_sourcepaths": [],
219 |
220 | //A list of java Librarys (jars)
221 | "java_libs": [],
222 |
223 | //A list of java resource directories
224 | "java_res_dirs": [],
225 |
226 | //A list of libs to include with the APK
227 | "libs":[],
228 |
229 | //Additional linker (ld) flags.
230 | "link_flags":[],
231 |
232 | // A list of XIBs to compile into NIBs.
233 | "xibs": [],
234 |
235 | // A list of storyboards to compile into storyboardc bundles
236 | "storyboards": [],
237 |
238 | // A list of xcdatamodels to compile into momc bundles
239 | "xcdatamodels": [],
240 |
241 | //Sub projects. Example : SomeSubProject.xcodeproj should be listed as "SomeSubProject"
242 | "modules": [],
243 | },
244 |
245 | // Edit this section to remove files and parameters from the generated #{$build_params_file} for this project.
246 | // For this section, only specify the file name as a string in the cases where you could normally
247 | // also specify an array or a dictionary. To override the generated settings for a particular
248 | // file, simply add it to the "add_params" list above with the settings you want.
249 | "remove_params": {
250 | // A list of pch files to remove from -include.
251 | // PCH files can be either a string, e.g., "./MyApp-Prefix.pch",
252 | // or a dictionary specifying the pch and the environment where
253 | // it should be used, e.g.,
254 | // {"pch": "./prefix-android.pch", "env": {"TARGET_OS": "android"}}
255 | "pchs": [],
256 |
257 | // A list of header search paths.
258 | // e.g. "./External/facebook-sdk/include"
259 | "header_paths": [],
260 |
261 | // A list of global compile flags for the project.
262 | // Flags can be either a string, e.g. "-Werror-shadow",
263 | // or a dictionary specifying the flag and the environment
264 | // that it should be used in, e.g.,
265 | // {"flag": "-fstack-protector", "env": {"TARGET_OS": "android"}}
266 | "flags": [],
267 |
268 | // A dictionary of global compiler definitions for the project.
269 | // Defines can be a simple key-value pair, e.g., "DEBUG": 1,
270 | // or the value can be a dictionary specifying the value and the
271 | // environment that it should be used in, e.g.,
272 | // "SOME_DEFINE": {"value": "\"yep its building on android\"", "env": {"TARGET_OS": "android"}}
273 | "defines": {},
274 |
275 | // A list of dependencies. Typically these correspond to
276 | // frameworks in the xcode project.
277 | "deps": [],
278 |
279 | // A list of source files (e.g. .m, .mm, .c, .cc, and .cpp) files to remove from the build.
280 | // e.g. "./External/Reachabilty/Reachability.m"
281 | "sources": [],
282 |
283 | // A list of glob removal filters to filter out source files.
284 | // e.g. "./Server/Level_[0-9].m"
285 | "sources_glob":[],
286 |
287 | // A list of assets to package with the application.
288 | // Assets can be either a string, e.g., "./Info.plist",
289 | // a dictionary specifying the asset, the target path it should be written to
290 | // in the app, and the environment it should be included with, e.g.,
291 | // {"asset": "./Resources/cube_texture.pvr.ccz", "target_path": "Bundled Resources/", "env": {"TARGET_TEXTURE_FMT": "pvr"}}
292 | // or a dictionary like above, but instead specifying the full target file name
293 | // for the asset, e.g.,
294 | // {"asset": "./Resources/cube_texture.pvr.ccz", "target_file": "Bundled Resources/cube_texture.pvr.gz", "env": {"TARGET_TEXTURE_FMT": "pvr"}}
295 | "assets": [],
296 |
297 | // A list of Info.plist files. The first one in the list will be the one we consider the main Info.plist.
298 | "infoplists": [],
299 |
300 | //A list of specific java sources file to compile
301 | "java_sources": [],
302 |
303 | //A list of the java root source directories
304 | "java_sourcepaths": [],
305 |
306 | //A list of java Librarys (jars)
307 | "java_libs": [],
308 |
309 | //A list of java resource directories
310 | "java_res_dirs": [],
311 |
312 | //A list of libs to include with the APK
313 | "libs":[],
314 |
315 | //Additional linker (ld) flags.
316 | "link_flags":[],
317 |
318 | // A list of XIBs to compile into NIBs.
319 | "xibs": [],
320 |
321 | // A list of storyboards to compile into storyboardc bundles
322 | "storyboards": [],
323 |
324 | // A list of xcdatamodels to compile into momc bundles
325 | "xcdatamodels": [],
326 |
327 | //Sub projects. Example : SomeSubProject.xcodeproj should be listed as "SomeSubProject"
328 | "modules": [],
329 | }
330 | }
331 |
--------------------------------------------------------------------------------
/InjectionDemo/InjectionDemo.approj/configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "configuration_format_version": 2,
3 |
4 | "default_target": {"project": "InjectionDemo", "project_config": "Release", "target": "InjectionDemo"},
5 |
6 |
7 | // Dictionary of global configuration parameters.
8 | // These parameters are not taken from the xcode project,
9 | // so they need to be supplied by the user.
10 | "config": {
11 |
12 | // A short name to identify the application.
13 | // Used to decide the APK filename, but not shown
14 | // anywhere in the app.
15 | // "APPLICATION_NAME": "",
16 |
17 | // The name of the application to display in the launcher
18 | // "APPLICATION_FULL_NAME": "",
19 |
20 | // The unique identifier for the application.
21 | // Normally this is in reverse DNS notation, e.g.,
22 | // "com.apportable.Spin"
23 | // "APPLICATION_IDENTIFIER": "",
24 |
25 | // Short version name for the app, e.g., "1.0"
26 | // "SHORT_VERSION": "",
27 |
28 | // If you're using Google Play Game Services, put in the client id (a numerical value)
29 | // "GOOGLE_PLAY_CLIENT_ID": "1234567"
30 |
31 | // A list of features needed on the target platform.
32 | // Common features include:
33 | // "accelerometer"
34 | // "access_network_state"
35 | // "access_wifi_state"
36 | // "atc_slow_surface"
37 | // "billing"
38 | // "c2dm_receive"
39 | // "check_license"
40 | // "get_accounts"
41 | // "large_heap"
42 | // "live_wallpaper"
43 | // "multitouch"
44 | // "multitouch_distinct"
45 | // "multitouch_jazzhand"
46 | // "NFC"
47 | // "no_internet"
48 | // "notifications"
49 | // "opengles2"
50 | // "portrait"
51 | // "prefer_external_storage"
52 | // "read_phone_state"
53 | // "stencil_buffer"
54 | // "touch_filter_move"
55 | // "touchscreen"
56 | // "true_color"
57 | // "vibrate"
58 | // "wake_lock"
59 | // "write_external_storage"
60 | // "write_settings"
61 | // "xperia"
62 | "FEATURES": ["portrait"],
63 |
64 | // Preferred way of handling URLs in the code.
65 | // Leave it null for most cases.
66 | //"URL_SCHEME": null,
67 |
68 | // Key to receive remote notifications on the device.
69 | //"REMOTE_NOTIFICATION_KEY": "",
70 |
71 | // The method for adjusting the splash screen (Default.png)
72 | // to fit the native device resolution. Options are:
73 | // "aspect_fill"
74 | // "aspect_fit"
75 | // "letterbox" (the default)
76 | // "native"
77 | // "stretch"
78 | //"SPLASH_SCREEN_TYPE": "letterbox",
79 |
80 | // Path to the image to use for the app's icon.
81 | // Usually something like "./Icon.png".
82 | // "ICON": "",
83 |
84 | // A regular expression to determine which assets
85 | // should be compressed when building the final app.
86 | // By default, text assets are not compressed. Use
87 | // this to compress certain text assets. For example,
88 | // ".*.plist$" will cause all files ending in ".plist"
89 | // to be compressed.
90 | //"COMPRESSED_ASSETS_PATTERN": "",
91 | //"UNCOMPRESSED_ASSETS_PATTERN": "",
92 |
93 | // Automatically convert audio to oggs. Defaults to true.
94 | // Can be configured per file with add params and "convert"
95 | // field or with the "CONVERTABLE_AUDIO_EXTENSIONS" flag.
96 | //"CONVERT_AUDIO": false,
97 |
98 | // Comma-separated list of file extensions that are safe to convert to OGGs
99 | //"CONVERTABLE_AUDIO_EXTENSIONS": ".mp3,.wav,.caf,.m4a",
100 |
101 | // Compress PNGs with pngcrush. Defaults to true.
102 | //"COMPRESS_PNGS": false,
103 |
104 | // This will cache all converted assets (pngs, oggs, etc)
105 | // into the approj directory. This is useful if you want to
106 | // persist the changes across builds or check them in source
107 | // control so they are uses by Linux based builders. Note that
108 | // if you disable this, your final build params file will contain
109 | // absolute paths and should not be checked in.
110 | // Defaults to true.
111 | //"STORE_ASSESTS_IN_APPROJ": false,
112 |
113 | // ICU_CONFIGS specifies the ICU (International Components for Unicode) database for the project
114 | // The default is "normal" which meets the needs of most apps using NS Format classes and/or localization
115 | // "full" will specify a complete database
116 | // "none" will specify no database. Be careful - It's not always intutitive when Foundation depends upon ICU
117 |
118 | // The normal table is 2762244 bytes compressed and 8622768 uncompressed
119 | // The full table is 8396438 bytes compressed and 20775168 uncompressed
120 |
121 | // You can also configure and build your own ICU table at http://apps.icu-project.org/datacustom/ICUData50.html
122 | // Add it to the "add_params" "assets" section and specify the path to ICU_CONFIG
123 | // For example TBD
124 |
125 | "ICU_CONFIG" : "normal",
126 |
127 | //Manifest extras
128 | //A list of .xml files that contain snippets to be included in AndroidManifest.xml
129 | //inside the , and tags respectively.
130 | //"MANIFEST_EXTRAS": [],
131 | //"ACTIVITY_MANIFEST_EXTRAS": [],
132 | //"APPLICATION_MANIFEST_EXTRAS": [],
133 |
134 | // Advanced Options
135 | //"NOTIFICATION_ICON":"",
136 | //"TEMPLATE_VALUES":{},
137 | //"OGGENC_OPTIONS":"",
138 | //"AFCONVERT_OPTIONS":"",
139 | //"PNGCRUSH_OPTIONS":"",
140 | //"MIN_SDK": 9,
141 | //"C2DM_SENDER": "",
142 | //"HARDWARE_ACCELERATED": "",
143 | //"NFC_SCHEME": "",
144 | //"MPMETRICS_API_KEY": "",
145 | //"RENAME_TARGET": true,
146 |
147 | },
148 |
149 | // Sometimes header include path ordering matters. If so, put the ordering constraints into this
150 | // array. For example, if "./foo" has to come before "./bar", you would put:
151 | // ["./foo", "./bar"]
152 | // Note that "./some_other_include_path" doesn't appear in the list, since its order doesn't matter.
153 | // You can also specify "*", which matches everything not already constrained. This lets you put
154 | // particular paths at the beginning or end of the list. For example, ["./foo", "*", "./bar"].
155 | "header_ordering_constraints": [],
156 |
157 | // Edit this section to add and replace files and parameters to the generated settings for this project.
158 | // If the generated settings for a particular file are incorrect, simply add it here with the settings
159 | // you need and the final build parameters will only included the version specified here.
160 | "add_params": {
161 | // A list of pch files to -include.
162 | // PCH files can be either a string, e.g., "./MyApp-Prefix.pch",
163 | // or a dictionary specifying the pch and the environment where
164 | // it should be used, e.g.,
165 | // {"pch": "./prefix-android.pch", "env": {"TARGET_OS": "android"}}
166 | "pchs": [],
167 |
168 | // A list of header search paths
169 | // e.g. "./External/facebook-sdk/include"
170 | "header_paths": [],
171 |
172 | // A list of global compile flags for the project.
173 | // Flags can be either a string, e.g. "-Werror-shadow",
174 | // or a dictionary specifying the flag and the environment
175 | // that it should be used in, e.g.,
176 | // {"flag": "-fstack-protector", "env": {"TARGET_OS": "android"}}
177 | "flags": [],
178 |
179 | // A dictionary of global compiler definitions for the project.
180 | // Defines can be a simple key-value pair, e.g., "DEBUG": 1,
181 | // or the value can be a dictionary specifying the value and the
182 | // environment that it should be used in, e.g.,
183 | // "SOME_DEFINE": {"value": "\"yep its building on android\"", "env": {"TARGET_OS": "android"}}
184 | "defines": {},
185 |
186 | // A list of dependencies. Typically these correspond to
187 | // frameworks in the xcode project.
188 | "deps": [],
189 |
190 | // A list of source files (e.g. .m, .mm, .c, .cc, and .cpp) files to build.
191 | // Source files can be a string, e.g. "./main.c", or a dictionary specifying
192 | // the file, any special flags, any defines, and the environment
193 | // where it should be compiled, e.g.,
194 | // {"source": "./PngImageLoader.m", "flags": ["-fstack-protector"], "defines": {"PNG": 1}, "env": {"TARGET_TEXTURE_FMT": "png"}}
195 | "sources": [],
196 |
197 | // A list of glob inclusion filters for additional files.
198 | // This can also be used to replace flags on multiple files.
199 | // e.g. {"source":"./Server/Level_[0-9].m","flags": ["-fno-objc-arc"], "defines": {"NDEBUG": 1}}
200 | "sources_glob":[],
201 |
202 | // A list of assets to package with the application.
203 | // Assets can be either a string, e.g., "./Info.plist",
204 | // or a dictionary specifying the asset and the target path it should be written to
205 | // in the app, and the environment it should be included with, e.g.,
206 | // {"asset": "./Resources/cube_texture.pvr.ccz", "target": "Bundled Resources/", "env": {"TARGET_TEXTURE_FMT": "pvr"}}
207 | // or a dictionary like above, but instead specifying the full target file name
208 | // for the asset, e.g.,
209 | // {"asset": "./Resources/cube_texture.pvr.ccz", "target": "Bundled Resources/cube_texture.pvr.gz", "env": {"TARGET_TEXTURE_FMT": "pvr"}}
210 | "assets": [],
211 |
212 | // A list of Info.plist files. The first one in the list will be the one we consider the main Info.plist.
213 | "infoplists": [],
214 |
215 | //A list of specific java sources file to compile
216 | "java_sources": [],
217 |
218 | //A list of the java root source directories
219 | "java_sourcepaths": [],
220 |
221 | //A list of java Librarys (jars)
222 | "java_libs": [],
223 |
224 | //A list of java resource directories
225 | "java_res_dirs": [],
226 |
227 | //A list of libs to include with the APK
228 | "libs":[],
229 |
230 | //Additional linker (ld) flags.
231 | "link_flags":[],
232 |
233 | // A list of XIBs to compile into NIBs.
234 | "xibs": [],
235 |
236 | // A list of storyboards to compile into storyboardc bundles
237 | "storyboards": [],
238 |
239 | // A list of xcdatamodels to compile into momc bundles
240 | "xcdatamodels": [],
241 |
242 | //Sub projects. Example : SomeSubProject.xcodeproj should be listed as "SomeSubProject"
243 | "modules": [],
244 | },
245 |
246 | // Edit this section to remove files and parameters from the generated #{$build_params_file} for this project.
247 | // For this section, only specify the file name as a string in the cases where you could normally
248 | // also specify an array or a dictionary. To override the generated settings for a particular
249 | // file, simply add it to the "add_params" list above with the settings you want.
250 | "remove_params": {
251 | // A list of pch files to remove from -include.
252 | // PCH files can be either a string, e.g., "./MyApp-Prefix.pch",
253 | // or a dictionary specifying the pch and the environment where
254 | // it should be used, e.g.,
255 | // {"pch": "./prefix-android.pch", "env": {"TARGET_OS": "android"}}
256 | "pchs": [],
257 |
258 | // A list of header search paths.
259 | // e.g. "./External/facebook-sdk/include"
260 | "header_paths": [],
261 |
262 | // A list of global compile flags for the project.
263 | // Flags can be either a string, e.g. "-Werror-shadow",
264 | // or a dictionary specifying the flag and the environment
265 | // that it should be used in, e.g.,
266 | // {"flag": "-fstack-protector", "env": {"TARGET_OS": "android"}}
267 | "flags": [],
268 |
269 | // A dictionary of global compiler definitions for the project.
270 | // Defines can be a simple key-value pair, e.g., "DEBUG": 1,
271 | // or the value can be a dictionary specifying the value and the
272 | // environment that it should be used in, e.g.,
273 | // "SOME_DEFINE": {"value": "\"yep its building on android\"", "env": {"TARGET_OS": "android"}}
274 | "defines": {},
275 |
276 | // A list of dependencies. Typically these correspond to
277 | // frameworks in the xcode project.
278 | "deps": [],
279 |
280 | // A list of source files (e.g. .m, .mm, .c, .cc, and .cpp) files to remove from the build.
281 | // e.g. "./External/Reachabilty/Reachability.m"
282 | "sources": [],
283 |
284 | // A list of glob removal filters to filter out source files.
285 | // e.g. "./Server/Level_[0-9].m"
286 | "sources_glob":[],
287 |
288 | // A list of assets to package with the application.
289 | // Assets can be either a string, e.g., "./Info.plist",
290 | // a dictionary specifying the asset, the target path it should be written to
291 | // in the app, and the environment it should be included with, e.g.,
292 | // {"asset": "./Resources/cube_texture.pvr.ccz", "target_path": "Bundled Resources/", "env": {"TARGET_TEXTURE_FMT": "pvr"}}
293 | // or a dictionary like above, but instead specifying the full target file name
294 | // for the asset, e.g.,
295 | // {"asset": "./Resources/cube_texture.pvr.ccz", "target_file": "Bundled Resources/cube_texture.pvr.gz", "env": {"TARGET_TEXTURE_FMT": "pvr"}}
296 | "assets": [],
297 |
298 | // A list of Info.plist files. The first one in the list will be the one we consider the main Info.plist.
299 | "infoplists": [],
300 |
301 | //A list of specific java sources file to compile
302 | "java_sources": [],
303 |
304 | //A list of the java root source directories
305 | "java_sourcepaths": [],
306 |
307 | //A list of java Librarys (jars)
308 | "java_libs": [],
309 |
310 | //A list of java resource directories
311 | "java_res_dirs": [],
312 |
313 | //A list of libs to include with the APK
314 | "libs":[],
315 |
316 | //Additional linker (ld) flags.
317 | "link_flags":[],
318 |
319 | // A list of XIBs to compile into NIBs.
320 | "xibs": [],
321 |
322 | // A list of storyboards to compile into storyboardc bundles
323 | "storyboards": [],
324 |
325 | // A list of xcdatamodels to compile into momc bundles
326 | "xcdatamodels": [],
327 |
328 | //Sub projects. Example : SomeSubProject.xcodeproj should be listed as "SomeSubProject"
329 | "modules": [],
330 | }
331 | }
332 |
--------------------------------------------------------------------------------
/ApportablePlugin.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7F2EB89C145057F200E97A87 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F2EB899145057EA00E97A87 /* AppKit.framework */; };
11 | BB26AE9F191FF6DF00702773 /* prepare.py in Resources */ = {isa = PBXBuildFile; fileRef = BB26AE9E191FF4FD00702773 /* prepare.py */; };
12 | BB26AEA0191FF6E300702773 /* inject.py in Resources */ = {isa = PBXBuildFile; fileRef = BB26AE9D191FF4E200702773 /* inject.py */; };
13 | BB5CF6321912DBD00052E10B /* APConsoleController.m in Sources */ = {isa = PBXBuildFile; fileRef = BB5CF6281912DBD00052E10B /* APConsoleController.m */; };
14 | BB5CF6331912DBD00052E10B /* APConsoleWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = BB5CF6291912DBD00052E10B /* APConsoleWindow.xib */; };
15 | BB5CF6341912DBD00052E10B /* APLogController.m in Sources */ = {isa = PBXBuildFile; fileRef = BB5CF62B1912DBD00052E10B /* APLogController.m */; };
16 | BB5CF6351912DBD00052E10B /* APLogWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = BB5CF62C1912DBD00052E10B /* APLogWindow.xib */; };
17 | BB5CF6371912DBD00052E10B /* APTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = BB5CF6301912DBD00052E10B /* APTextView.m */; };
18 | BB5CF63A1912DCC50052E10B /* APPluginMenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = BB5CF6391912DCC50052E10B /* APPluginMenuController.m */; };
19 | BB82F0CD1913D15F0015AE7A /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = BB82F0CC1913D15F0015AE7A /* README.md */; };
20 | BB9D655F19194D9E00ECF4B3 /* pause.png in Resources */ = {isa = PBXBuildFile; fileRef = BB9D655D19194D9E00ECF4B3 /* pause.png */; };
21 | BB9D656019194D9E00ECF4B3 /* play.png in Resources */ = {isa = PBXBuildFile; fileRef = BB9D655E19194D9E00ECF4B3 /* play.png */; };
22 | BBB0DB26193B505200B5C0D8 /* APDebugController.m in Sources */ = {isa = PBXBuildFile; fileRef = BBB0DB25193B505200B5C0D8 /* APDebugController.m */; };
23 | BBB0DB28193B506D00B5C0D8 /* APDebugController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BBB0DB27193B506D00B5C0D8 /* APDebugController.xib */; };
24 | BBF5D8E31912DFCA0037CE2E /* APPluginMenuController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BBF5D8E21912DFCA0037CE2E /* APPluginMenuController.xib */; };
25 | DA1B5D020E64686800921439 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 089C1672FE841209C02AAC07 /* Foundation.framework */; };
26 | /* End PBXBuildFile section */
27 |
28 | /* Begin PBXFileReference section */
29 | 089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; };
30 | 7F2EB899145057EA00E97A87 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
31 | 8D5B49B6048680CD000E48DA /* ApportablePlugin.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ApportablePlugin.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; };
32 | 8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
33 | BB26AE9D191FF4E200702773 /* inject.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = inject.py; sourceTree = ""; };
34 | BB26AE9E191FF4FD00702773 /* prepare.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = prepare.py; sourceTree = ""; };
35 | BB4E31041915943D00CC72EB /* APLiveCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APLiveCoding.h; sourceTree = ""; };
36 | BB4E31051915943D00CC72EB /* APLiveCoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APLiveCoding.m; sourceTree = ""; };
37 | BB5CF6271912DBD00052E10B /* APConsoleController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APConsoleController.h; sourceTree = ""; };
38 | BB5CF6281912DBD00052E10B /* APConsoleController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APConsoleController.m; sourceTree = ""; };
39 | BB5CF6291912DBD00052E10B /* APConsoleWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = APConsoleWindow.xib; sourceTree = ""; };
40 | BB5CF62A1912DBD00052E10B /* APLogController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APLogController.h; sourceTree = ""; };
41 | BB5CF62B1912DBD00052E10B /* APLogController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APLogController.m; sourceTree = ""; };
42 | BB5CF62C1912DBD00052E10B /* APLogWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = APLogWindow.xib; sourceTree = ""; };
43 | BB5CF62F1912DBD00052E10B /* APTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APTextView.h; sourceTree = ""; };
44 | BB5CF6301912DBD00052E10B /* APTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APTextView.m; sourceTree = ""; };
45 | BB5CF6381912DCC50052E10B /* APPluginMenuController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APPluginMenuController.h; sourceTree = ""; };
46 | BB5CF6391912DCC50052E10B /* APPluginMenuController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APPluginMenuController.m; sourceTree = ""; };
47 | BB63E0F8160CA89800E95F5D /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
48 | BB82F0CC1913D15F0015AE7A /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.md; sourceTree = ""; };
49 | BB9D655D19194D9E00ECF4B3 /* pause.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pause.png; sourceTree = ""; };
50 | BB9D655E19194D9E00ECF4B3 /* play.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = play.png; sourceTree = ""; };
51 | BBB0DB24193B505200B5C0D8 /* APDebugController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APDebugController.h; sourceTree = ""; };
52 | BBB0DB25193B505200B5C0D8 /* APDebugController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APDebugController.m; sourceTree = ""; };
53 | BBB0DB27193B506D00B5C0D8 /* APDebugController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = APDebugController.xib; sourceTree = ""; };
54 | BBF5D8E21912DFCA0037CE2E /* APPluginMenuController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = APPluginMenuController.xib; sourceTree = ""; };
55 | /* End PBXFileReference section */
56 |
57 | /* Begin PBXFrameworksBuildPhase section */
58 | 8D5B49B3048680CD000E48DA /* Frameworks */ = {
59 | isa = PBXFrameworksBuildPhase;
60 | buildActionMask = 2147483647;
61 | files = (
62 | DA1B5D020E64686800921439 /* Foundation.framework in Frameworks */,
63 | 7F2EB89C145057F200E97A87 /* AppKit.framework in Frameworks */,
64 | );
65 | runOnlyForDeploymentPostprocessing = 0;
66 | };
67 | /* End PBXFrameworksBuildPhase section */
68 |
69 | /* Begin PBXGroup section */
70 | 089C166AFE841209C02AAC07 /* QuietXcode */ = {
71 | isa = PBXGroup;
72 | children = (
73 | 7F411B0C15FABAC6002F77B6 /* Classes */,
74 | 089C167CFE841241C02AAC07 /* Resources */,
75 | 089C1671FE841209C02AAC07 /* Frameworks and Libraries */,
76 | 19C28FB8FE9D52D311CA2CBB /* Products */,
77 | );
78 | name = QuietXcode;
79 | sourceTree = "";
80 | };
81 | 089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = {
82 | isa = PBXGroup;
83 | children = (
84 | 089C1672FE841209C02AAC07 /* Foundation.framework */,
85 | 7F2EB899145057EA00E97A87 /* AppKit.framework */,
86 | BB63E0F8160CA89800E95F5D /* IOKit.framework */,
87 | );
88 | name = "Frameworks and Libraries";
89 | sourceTree = "";
90 | };
91 | 089C167CFE841241C02AAC07 /* Resources */ = {
92 | isa = PBXGroup;
93 | children = (
94 | BB9D655D19194D9E00ECF4B3 /* pause.png */,
95 | BB9D655E19194D9E00ECF4B3 /* play.png */,
96 | BB82F0CC1913D15F0015AE7A /* README.md */,
97 | 8D5B49B7048680CD000E48DA /* Info.plist */,
98 | BB26AE9E191FF4FD00702773 /* prepare.py */,
99 | BB26AE9D191FF4E200702773 /* inject.py */,
100 | );
101 | name = Resources;
102 | sourceTree = "";
103 | };
104 | 19C28FB8FE9D52D311CA2CBB /* Products */ = {
105 | isa = PBXGroup;
106 | children = (
107 | 8D5B49B6048680CD000E48DA /* ApportablePlugin.xcplugin */,
108 | );
109 | name = Products;
110 | sourceTree = "";
111 | };
112 | 7F411B0C15FABAC6002F77B6 /* Classes */ = {
113 | isa = PBXGroup;
114 | children = (
115 | BB5CF6381912DCC50052E10B /* APPluginMenuController.h */,
116 | BB5CF6391912DCC50052E10B /* APPluginMenuController.m */,
117 | BBF5D8E21912DFCA0037CE2E /* APPluginMenuController.xib */,
118 | BB5CF6271912DBD00052E10B /* APConsoleController.h */,
119 | BB5CF6281912DBD00052E10B /* APConsoleController.m */,
120 | BB5CF6291912DBD00052E10B /* APConsoleWindow.xib */,
121 | BBB0DB24193B505200B5C0D8 /* APDebugController.h */,
122 | BBB0DB25193B505200B5C0D8 /* APDebugController.m */,
123 | BBB0DB27193B506D00B5C0D8 /* APDebugController.xib */,
124 | BB5CF62A1912DBD00052E10B /* APLogController.h */,
125 | BB5CF62B1912DBD00052E10B /* APLogController.m */,
126 | BB5CF62C1912DBD00052E10B /* APLogWindow.xib */,
127 | BB4E31041915943D00CC72EB /* APLiveCoding.h */,
128 | BB4E31051915943D00CC72EB /* APLiveCoding.m */,
129 | BB5CF62F1912DBD00052E10B /* APTextView.h */,
130 | BB5CF6301912DBD00052E10B /* APTextView.m */,
131 | );
132 | path = Classes;
133 | sourceTree = "";
134 | };
135 | /* End PBXGroup section */
136 |
137 | /* Begin PBXNativeTarget section */
138 | 8D5B49AC048680CD000E48DA /* ApportablePlugin */ = {
139 | isa = PBXNativeTarget;
140 | buildConfigurationList = 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "ApportablePlugin" */;
141 | buildPhases = (
142 | 8D5B49B1048680CD000E48DA /* Sources */,
143 | 8D5B49B3048680CD000E48DA /* Frameworks */,
144 | BB5251F8160A2EF700276EB3 /* Resources */,
145 | BB553A6D19167A020005E800 /* ShellScript */,
146 | );
147 | buildRules = (
148 | );
149 | dependencies = (
150 | );
151 | name = ApportablePlugin;
152 | productInstallPath = "$(HOME)/Library/Bundles";
153 | productName = QuietXcode;
154 | productReference = 8D5B49B6048680CD000E48DA /* ApportablePlugin.xcplugin */;
155 | productType = "com.apple.product-type.bundle";
156 | };
157 | /* End PBXNativeTarget section */
158 |
159 | /* Begin PBXProject section */
160 | 089C1669FE841209C02AAC07 /* Project object */ = {
161 | isa = PBXProject;
162 | attributes = {
163 | LastUpgradeCheck = 0440;
164 | };
165 | buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "ApportablePlugin" */;
166 | compatibilityVersion = "Xcode 3.2";
167 | developmentRegion = English;
168 | hasScannedForEncodings = 1;
169 | knownRegions = (
170 | English,
171 | Japanese,
172 | French,
173 | German,
174 | en,
175 | );
176 | mainGroup = 089C166AFE841209C02AAC07 /* QuietXcode */;
177 | projectDirPath = "";
178 | projectRoot = "";
179 | targets = (
180 | 8D5B49AC048680CD000E48DA /* ApportablePlugin */,
181 | );
182 | };
183 | /* End PBXProject section */
184 |
185 | /* Begin PBXResourcesBuildPhase section */
186 | BB5251F8160A2EF700276EB3 /* Resources */ = {
187 | isa = PBXResourcesBuildPhase;
188 | buildActionMask = 2147483647;
189 | files = (
190 | BB5CF6331912DBD00052E10B /* APConsoleWindow.xib in Resources */,
191 | BB9D656019194D9E00ECF4B3 /* play.png in Resources */,
192 | BBB0DB28193B506D00B5C0D8 /* APDebugController.xib in Resources */,
193 | BB5CF6351912DBD00052E10B /* APLogWindow.xib in Resources */,
194 | BB82F0CD1913D15F0015AE7A /* README.md in Resources */,
195 | BB26AE9F191FF6DF00702773 /* prepare.py in Resources */,
196 | BB9D655F19194D9E00ECF4B3 /* pause.png in Resources */,
197 | BB26AEA0191FF6E300702773 /* inject.py in Resources */,
198 | BBF5D8E31912DFCA0037CE2E /* APPluginMenuController.xib in Resources */,
199 | );
200 | runOnlyForDeploymentPostprocessing = 0;
201 | };
202 | /* End PBXResourcesBuildPhase section */
203 |
204 | /* Begin PBXShellScriptBuildPhase section */
205 | BB553A6D19167A020005E800 /* ShellScript */ = {
206 | isa = PBXShellScriptBuildPhase;
207 | buildActionMask = 2147483647;
208 | files = (
209 | );
210 | inputPaths = (
211 | );
212 | outputPaths = (
213 | );
214 | runOnlyForDeploymentPostprocessing = 0;
215 | shellPath = /bin/sh;
216 | shellScript = "rm -rf InjectionDemo/build\ncp -r Classes/APLiveCoding.* InjectionDemo \"$INSTALL_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH\"\n";
217 | showEnvVarsInLog = 0;
218 | };
219 | /* End PBXShellScriptBuildPhase section */
220 |
221 | /* Begin PBXSourcesBuildPhase section */
222 | 8D5B49B1048680CD000E48DA /* Sources */ = {
223 | isa = PBXSourcesBuildPhase;
224 | buildActionMask = 2147483647;
225 | files = (
226 | BB5CF6371912DBD00052E10B /* APTextView.m in Sources */,
227 | BB5CF63A1912DCC50052E10B /* APPluginMenuController.m in Sources */,
228 | BB5CF6321912DBD00052E10B /* APConsoleController.m in Sources */,
229 | BBB0DB26193B505200B5C0D8 /* APDebugController.m in Sources */,
230 | BB5CF6341912DBD00052E10B /* APLogController.m in Sources */,
231 | );
232 | runOnlyForDeploymentPostprocessing = 0;
233 | };
234 | /* End PBXSourcesBuildPhase section */
235 |
236 | /* Begin XCBuildConfiguration section */
237 | 1DEB913B08733D840010E9CD /* Debug */ = {
238 | isa = XCBuildConfiguration;
239 | buildSettings = {
240 | ALWAYS_SEARCH_USER_PATHS = NO;
241 | CLANG_ENABLE_OBJC_ARC = YES;
242 | CODE_SIGN_ENTITLEMENTS = "";
243 | CODE_SIGN_IDENTITY = "";
244 | COMBINE_HIDPI_IMAGES = YES;
245 | COPY_PHASE_STRIP = NO;
246 | DEPLOYMENT_LOCATION = YES;
247 | DEPLOYMENT_POSTPROCESSING = YES;
248 | DSTROOT = "$(HOME)";
249 | GCC_DYNAMIC_NO_PIC = NO;
250 | GCC_ENABLE_OBJC_GC = unsupported;
251 | GCC_MODEL_TUNING = G5;
252 | GCC_OPTIMIZATION_LEVEL = 0;
253 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
254 | INFOPLIST_FILE = Info.plist;
255 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
256 | LD_RUNPATH_SEARCH_PATHS = /Developer;
257 | PRODUCT_NAME = ApportablePlugin;
258 | STRIP_INSTALLED_PRODUCT = NO;
259 | WRAPPER_EXTENSION = xcplugin;
260 | };
261 | name = Debug;
262 | };
263 | 1DEB913F08733D840010E9CD /* Debug */ = {
264 | isa = XCBuildConfiguration;
265 | buildSettings = {
266 | ARCHS = "$(ARCHS_STANDARD_64_BIT)";
267 | CURRENT_PROJECT_VERSION = 3.5;
268 | GCC_C_LANGUAGE_STANDARD = c99;
269 | GCC_OPTIMIZATION_LEVEL = 0;
270 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
271 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
272 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
273 | GCC_WARN_UNUSED_VARIABLE = YES;
274 | INFOPLIST_PREPROCESSOR_DEFINITIONS = "";
275 | INSTALL_PATH = "$(HOME)/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
276 | MACOSX_DEPLOYMENT_TARGET = 10.7;
277 | SDKROOT = macosx;
278 | };
279 | name = Debug;
280 | };
281 | /* End XCBuildConfiguration section */
282 |
283 | /* Begin XCConfigurationList section */
284 | 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "ApportablePlugin" */ = {
285 | isa = XCConfigurationList;
286 | buildConfigurations = (
287 | 1DEB913B08733D840010E9CD /* Debug */,
288 | );
289 | defaultConfigurationIsVisible = 0;
290 | defaultConfigurationName = Debug;
291 | };
292 | 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "ApportablePlugin" */ = {
293 | isa = XCConfigurationList;
294 | buildConfigurations = (
295 | 1DEB913F08733D840010E9CD /* Debug */,
296 | );
297 | defaultConfigurationIsVisible = 0;
298 | defaultConfigurationName = Debug;
299 | };
300 | /* End XCConfigurationList section */
301 | };
302 | rootObject = 089C1669FE841209C02AAC07 /* Project object */;
303 | }
304 |
--------------------------------------------------------------------------------