rubyosa19 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright (c) 2006-2007, Apple Inc. All rights reserved.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions
6
+ * are met:
7
+ * 1. Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * 2. Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13
+ * its contributors may be used to endorse or promote products derived
14
+ * from this software without specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
17
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
20
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #ifndef __RBOSA_H_
30
+ #define __RBOSA_H_
31
+
32
+ #include "osx_ruby.h"
33
+ #include <Carbon/Carbon.h>
34
+ #include <sys/param.h>
35
+
36
+ /* rbosa_sdef.c */
37
+ VALUE rbosa_scripting_info (VALUE self, VALUE hash);
38
+ VALUE rbosa_remote_processes (VALUE self, VALUE machine);
39
+
40
+ /* rbosa_conv.c */
41
+ FourCharCode rbobj_to_fourchar (VALUE obj);
42
+ VALUE rbosa_four_char_code (VALUE self, VALUE val);
43
+ void rbobj_to_alias_handle (VALUE obj, AliasHandle *alias);
44
+
45
+ /* rbosa_err.c */
46
+ const char *error_code_to_string (const int code);
47
+
48
+ /* helper macros */
49
+ #define RVAL2CSTR(x) (StringValueCStr (x))
50
+ #define CSTR2RVAL(x) (rb_str_new2 (x))
51
+ #define RVAL2CBOOL(x) (RTEST(x))
52
+ #define CBOOL2RVAL(x) (x ? Qtrue : Qfalse)
53
+ #define RVAL2FOURCHAR(x) (rbobj_to_fourchar(x))
54
+
55
+ #endif /* __RBOSA_H_ */
@@ -0,0 +1,97 @@
1
+ /*
2
+ * Copyright (c) 2006-2007, Apple Inc. All rights reserved.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions
6
+ * are met:
7
+ * 1. Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * 2. Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13
+ * its contributors may be used to endorse or promote products derived
14
+ * from this software without specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
17
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
20
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #include "rbosa.h"
30
+
31
+ FourCharCode
32
+ rbobj_to_fourchar (VALUE obj)
33
+ {
34
+ FourCharCode result = 0;
35
+
36
+ #define USAGE_MSG "requires 4 length size string/symbol or integer"
37
+
38
+ if (rb_obj_is_kind_of (obj, rb_cInteger)) {
39
+ result = NUM2UINT (obj);
40
+ }
41
+ else {
42
+ if (rb_obj_is_kind_of (obj, rb_cSymbol))
43
+ obj = rb_obj_as_string (obj);
44
+
45
+ if (rb_obj_is_kind_of (obj, rb_cString)) {
46
+ if (RSTRING_LEN(obj) != 4)
47
+ rb_raise (rb_eArgError, USAGE_MSG);
48
+ result = *(FourCharCode*)(RSTRING_PTR(obj));
49
+ result = CFSwapInt32HostToBig (result);
50
+ }
51
+ else {
52
+ rb_raise (rb_eArgError, USAGE_MSG);
53
+ }
54
+ }
55
+
56
+ #undef USAGE_MSG
57
+
58
+ return result;
59
+ }
60
+
61
+ VALUE
62
+ rbosa_four_char_code (VALUE self, VALUE val)
63
+ {
64
+ return INT2NUM (RVAL2FOURCHAR (val));
65
+ }
66
+
67
+ void
68
+ rbobj_to_alias_handle (VALUE obj, AliasHandle *alias)
69
+ {
70
+ FSRef ref;
71
+ CFURLRef URL;
72
+ Boolean ok;
73
+ OSErr error;
74
+
75
+ Check_Type (obj, T_STRING);
76
+ *alias = NULL;
77
+
78
+ URL = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault,
79
+ (const UInt8 *)RSTRING_PTR (obj),
80
+ RSTRING_LEN(obj),
81
+ 0 /* XXX: normally passing 0 even if it's a directory should
82
+ not hurt, as we are just getting the FSRef. */);
83
+ if (URL == NULL)
84
+ rb_raise (rb_eArgError, "Invalid path given");
85
+ ok = CFURLGetFSRef (URL, &ref);
86
+ CFRelease (URL);
87
+ if (ok) {
88
+ error = FSNewAlias (NULL, &ref, alias);
89
+ if (error != noErr)
90
+ rb_raise (rb_eArgError, "Cannot create alias handle for given filename '%s' : %s (%d)",
91
+ RSTRING_PTR(obj), GetMacOSStatusErrorString (error), error);
92
+ }
93
+ else {
94
+ rb_raise (rb_eArgError, "Cannot obtain the filesystem reference for given filename '%s'",
95
+ RSTRING_PTR(obj));
96
+ }
97
+ }
@@ -0,0 +1,105 @@
1
+ /*
2
+ * Copyright (c) 2006-2007, Apple Inc. All rights reserved.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions
6
+ * are met:
7
+ * 1. Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * 2. Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13
+ * its contributors may be used to endorse or promote products derived
14
+ * from this software without specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
17
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
20
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #include <CoreServices/CoreServices.h>
30
+
31
+ const char *
32
+ error_code_to_string (const int code)
33
+ {
34
+ switch (code) {
35
+ case noPortErr: return "Client hasn't set 'SIZE' resource to indicate awareness of high-level events";
36
+ case destPortErr: return "Server hasn't set 'SIZE' resource to indicate awareness of high-level events, or else is not present";
37
+ case sessClosedErr: return "The kAEDontReconnect flag in the sendMode parameter was set and the server quit, then restarted";
38
+ case errAECoercionFail: return "Data could not be coerced to the requested descriptor type";
39
+ case errAEDescNotFound: return "Descriptor was not found";
40
+ case errAECorruptData: return "Data in an Apple event could not be read";
41
+ case errAEWrongDataType: return "Wrong descriptor type";
42
+ case errAENotAEDesc: return "Not a valid descriptor";
43
+ case errAEBadListItem: return "Operation involving a list item failed";
44
+ case errAENewerVersion: return "Need a newer version of the Apple Event Manager";
45
+ case errAENotAppleEvent: return "The event is not in AppleEvent format.";
46
+ case errAEEventNotHandled: return "Event wasn't handled by an Apple event handler";
47
+ case errAEReplyNotValid: return "AEResetTimer was passed an invalid repl";
48
+ case errAEUnknownSendMode: return "Invalid sending mode was passed";
49
+ case errAEWaitCanceled: return "User canceled out of wait loop for reply or receipt";
50
+ case errAETimeout: return "Apple event timed out";
51
+ case errAENoUserInteraction: return "No user interaction allowed";
52
+ case errAENotASpecialFunction: return "Wrong keyword for a special function";
53
+ case errAEParamMissed: return "A required parameter was not accessed.";
54
+ case errAEUnknownAddressType: return "Unknown Apple event address type";
55
+ case errAEHandlerNotFound: return "No handler found for an Apple event";
56
+ case errAEReplyNotArrived: return "Reply has not yet arrived";
57
+ case errAEIllegalIndex: return "Not a valid list index";
58
+ case errAEImpossibleRange: return "The range is not valid because it is impossible for a range to include the first and last objects that were specified; an example is a range in which the offset of the first object is greater than the offset of the last object";
59
+ case errAEWrongNumberArgs: return "The number of operands provided for the kAENOT logical operator is not 1";
60
+ case errAEAccessorNotFound: return "There is no object accessor function for the specified object class and container type";
61
+ case errAENoSuchLogical: return "The logical operator in a logical descriptor is not kAEAND, kAEOR, or kAENOT";
62
+ case errAEBadTestKey: return "The descriptor in a test key is neither a comparison descriptor nor a logical descriptor";
63
+ case errAENotAnObjSpec: return "The objSpecifier parameter of AEResolve is not an object specifier";
64
+ case errAENoSuchObject: return "Runtime resolution of an object failed.";
65
+ case errAENegativeCount: return "An object-counting function returned a negative result";
66
+ case errAEEmptyListContainer: return "The container for an Apple event object is specified by an empty list";
67
+ case errAEUnknownObjectType: return "The object type isn't recognized";
68
+ case errAERecordingIsAlreadyOn: return "Recording is already on";
69
+ case errAEReceiveTerminate: return "Break out of all levels of AEReceive to the topmost (1.1 or greater)";
70
+ case errAEReceiveEscapeCurrent: return "Break out of lowest level only of AEReceive (1.1 or greater)";
71
+ case errAEEventFiltered: return "Event has been filtered and should not be propagated (1.1 or greater)";
72
+ case errAEDuplicateHandler: return "Attempt to install handler in table for identical class and ID (1.1 or greater)";
73
+ case errAEStreamBadNesting: return "Nesting violation while streaming";
74
+ case errAEStreamAlreadyConverted: return "Attempt to convert a stream that has already been converted";
75
+ case errAEDescIsNull: return "Attempt to perform an invalid operation on a null descriptor";
76
+ case errAEBuildSyntaxError: return "AEBuildDesc and related functions detected a syntax error";
77
+ case errAEBufferTooSmall: return "Buffer for AEFlattenDesc too small";
78
+ case errASCantConsiderAndIgnore: return "Can't both consider and ignore <attribute>.";
79
+ case errASCantCompareMoreThan32k: return "Can't perform operation on text longer than 32K bytes.";
80
+ case errASTerminologyNestingTooDeep: return "Tell statements are nested too deeply.";
81
+ case errASIllegalFormalParameter: return "<name> is illegal as a formal parameter.";
82
+ case errASParameterNotForEvent: return "<name> is not a parameter name for the event <event>.";
83
+ case errASNoResultReturned: return "No result was returned for some argument of this expression.";
84
+ case errAEEventFailed: return "Apple event handler failed.";
85
+ case errAETypeError: return "A descriptor type mismatch occurred.";
86
+ case errAEBadKeyForm: return "Invalid key form.";
87
+ case errAENotModifiable: return "Can't set <object or data> to <object or data>. Access not allowed.";
88
+ case errAEPrivilegeError: return "A privilege violation occurred.";
89
+ case errAEReadDenied: return "The read operation was not allowed.";
90
+ case errAEWriteDenied: return "Can't set <object or data> to <object or data>.";
91
+ case errAEIndexTooLarge: return "The index of the event is too large to be valid.";
92
+ case errAENotAnElement: return "The specified object is a property, not an element.";
93
+ case errAECantSupplyType: return "Can't supply the requested descriptor type for the data.";
94
+ case errAECantHandleClass: return "The Apple event handler can't handle objects of this class.";
95
+ case errAEInTransaction: return "Couldn't handle this command because it wasn't part of the current transaction.";
96
+ case errAENoSuchTransaction: return "The transaction to which this command belonged isn't a valid transaction.";
97
+ case errAENoUserSelection: return "There is no user selection.";
98
+ case errAENotASingleObject: return "Handler only handles single objects.";
99
+ case errAECantUndo: return "Can't undo the previous Apple event or user action.";
100
+ case errAENotAnEnumMember: return "Enumerated value in SetData is not allowed for this property";
101
+ case errAECantPutThatThere: return "In make new, duplicate, etc. class can't be an element of container";
102
+ case errAEPropertiesClash: return "Illegal combination of properties settings for SetData, make new, or duplicate";
103
+ }
104
+ return GetMacOSStatusErrorString (code);
105
+ }
@@ -0,0 +1,441 @@
1
+ /*
2
+ * Copyright (c) 2006-2007, Apple Inc. All rights reserved.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions
6
+ * are met:
7
+ * 1. Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * 2. Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13
+ * its contributors may be used to endorse or promote products derived
14
+ * from this software without specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
17
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
20
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #include <ApplicationServices/ApplicationServices.h>
30
+ #include <CoreFoundation/CoreFoundation.h>
31
+ #include <unistd.h>
32
+ #include <st.h>
33
+ #include "rbosa.h"
34
+
35
+ static void
36
+ rbosa_app_name_signature (CFURLRef URL, VALUE *name, VALUE *signature)
37
+ {
38
+ CFBundleRef bundle;
39
+ CFDictionaryRef info;
40
+ CFStringRef str;
41
+
42
+ bundle = CFBundleCreate (kCFAllocatorDefault, URL);
43
+ info = CFBundleGetInfoDictionary (bundle);
44
+
45
+ if (NIL_P(*name)) {
46
+ str = CFDictionaryGetValue (info, CFSTR ("CFBundleName"));
47
+ if (str == NULL) {
48
+ /* Try 'CFBundleExecutable' if 'CFBundleName' does not exist (which is a bug). */
49
+ str = CFDictionaryGetValue (info, CFSTR ("CFBundleExecutable"));
50
+ }
51
+ *name = str != NULL ? CSTR2RVAL (CFStringGetCStringPtr (str, CFStringGetFastestEncoding (str))) : Qnil;
52
+ }
53
+ if (NIL_P(*signature)) {
54
+ str = CFDictionaryGetValue (info, CFSTR ("CFBundleSignature"));
55
+ *signature = str != NULL ? CSTR2RVAL (CFStringGetCStringPtr (str, CFStringGetFastestEncoding (str))) : Qnil;
56
+ }
57
+
58
+ CFRelease (bundle);
59
+ }
60
+
61
+ static bool
62
+ rbosa_translate_app (VALUE criterion, VALUE value, VALUE *app_signature, VALUE *app_name, FSRef *fs_ref, const char **error)
63
+ {
64
+ OSStatus err;
65
+ CFURLRef URL;
66
+
67
+ *app_name = Qnil;
68
+ *app_signature = Qnil;
69
+ err = noErr;
70
+
71
+ if (criterion == ID2SYM (rb_intern ("signature"))) {
72
+ err = LSFindApplicationForInfo (RVAL2FOURCHAR (value), NULL, NULL, fs_ref, &URL);
73
+ *app_signature = value; /* Don't need to get the app signature, we already have it. */
74
+ }
75
+ else {
76
+ CFMutableStringRef str;
77
+
78
+ str = CFStringCreateMutable (kCFAllocatorDefault, 0);
79
+ CFStringAppendCString (str, RVAL2CSTR (value), kCFStringEncodingUTF8);
80
+
81
+ if (criterion == ID2SYM (rb_intern ("path"))) {
82
+ err = FSPathMakeRef ((const UInt8 *)RVAL2CSTR (value), fs_ref, NULL);
83
+ if (err == noErr) {
84
+ URL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, str, kCFURLPOSIXPathStyle, FALSE);
85
+ }
86
+ }
87
+ else if (criterion == ID2SYM (rb_intern ("name"))) {
88
+ CFStringRef dot_app;
89
+
90
+ dot_app = CFSTR (".app");
91
+ if (!CFStringHasSuffix (str, dot_app))
92
+ CFStringAppend (str, dot_app);
93
+
94
+ err = LSFindApplicationForInfo (kLSUnknownCreator, NULL, str, fs_ref, &URL);
95
+ *app_name = value; /* Don't need to get the app name, we already have it. */
96
+ }
97
+ else if (criterion == ID2SYM (rb_intern ("bundle_id"))) {
98
+ err = LSFindApplicationForInfo (kLSUnknownCreator, str, NULL, fs_ref, &URL);
99
+ }
100
+ else {
101
+ *error = "Invalid criterion";
102
+ CFRelease (str);
103
+ return FALSE;
104
+ }
105
+
106
+ CFRelease (str);
107
+ }
108
+
109
+ if (err != noErr) {
110
+ *error = "Can't locate the target bundle on the file system";
111
+ return FALSE;
112
+ }
113
+
114
+ rbosa_app_name_signature (URL, app_name, app_signature);
115
+
116
+ CFRelease (URL);
117
+
118
+ if (NIL_P (*app_signature)) {
119
+ *error = "Can't get the target bundle signature";
120
+ return FALSE;
121
+ }
122
+
123
+ return TRUE;
124
+ }
125
+
126
+ static inline VALUE
127
+ __get_criterion (VALUE hash, const char *str, VALUE *psym)
128
+ {
129
+ VALUE sym;
130
+ VALUE val;
131
+
132
+ sym = ID2SYM (rb_intern (str));
133
+ val = rb_hash_delete (hash, sym);
134
+
135
+ if (!NIL_P (val)) {
136
+ if (TYPE (val) != T_STRING)
137
+ rb_raise (rb_eArgError, "argument '%s' must have a String value", RVAL2CSTR (sym));
138
+ if (psym != NULL)
139
+ *psym = sym;
140
+ }
141
+
142
+ return val;
143
+ }
144
+
145
+ static OSStatus
146
+ send_simple_remote_event (AEEventClass ec, AEEventID ei, const char *target_url, const AEDesc *dp, AppleEvent *reply)
147
+ {
148
+ OSStatus err;
149
+ AEDesc target, ev, root_reply;
150
+
151
+ if ((err = AECreateDesc ('aprl', target_url, strlen(target_url), &target)) != noErr)
152
+ return err;
153
+
154
+ if ((err = AECreateAppleEvent (ec, ei, &target, kAutoGenerateReturnID, kAnyTransactionID, &ev)) != noErr) {
155
+ AEDisposeDesc (&target);
156
+ return err;
157
+ }
158
+
159
+ if (dp != NULL)
160
+ AEPutParamDesc (&ev, keyDirectObject, dp);
161
+
162
+ err = AESend (&ev, &root_reply, kAEWaitReply, kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
163
+ if (err == noErr)
164
+ err = AEGetParamDesc (&root_reply, keyDirectObject, typeWildCard, reply);
165
+
166
+ // XXX we should check for application-level errors
167
+
168
+ AEDisposeDesc (&target);
169
+ AEDisposeDesc (&ev);
170
+ AEDisposeDesc (&root_reply);
171
+
172
+ return err;
173
+ }
174
+
175
+ #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
176
+ typedef SInt16 ResFileRefNum;
177
+ #endif
178
+
179
+ static VALUE
180
+ get_remote_app_sdef (const char *target_url)
181
+ {
182
+ AEDesc zero, reply, aete;
183
+ Size datasize;
184
+ void * data;
185
+ int fd;
186
+ FSRef fs;
187
+ CFDataRef sdef_data;
188
+ VALUE sdef;
189
+ ResFileRefNum res_num;
190
+ Handle res;
191
+ SInt32 z = 0;
192
+ OSErr osa_error;
193
+ HFSUniStr255 resourceForkName;
194
+ char tmp_res_path[] = "/tmp/FakeXXXXXX.osax";
195
+
196
+ #define BOOM(m) \
197
+ do { \
198
+ rb_raise (rb_eRuntimeError, \
199
+ "Can't get scripting definition of remote application (%s) : %s (%d)", \
200
+ m, error_code_to_string (osa_error), osa_error); \
201
+ } while (0)
202
+
203
+ // XXX we should try to get the sdef via ascr/gsdf before trying to convert the AETE!
204
+
205
+ AECreateDesc (typeSInt32, &z, sizeof (z), &zero);
206
+ osa_error = send_simple_remote_event ('ascr', 'gdte', target_url, &zero, &reply);
207
+ AEDisposeDesc (&zero);
208
+ if (osa_error != noErr)
209
+ BOOM ("sending event");
210
+
211
+ osa_error = AECoerceDesc (&reply, kAETerminologyExtension, &aete);
212
+ AEDisposeDesc (&reply);
213
+ if (osa_error != noErr)
214
+ BOOM ("coercing result");
215
+
216
+ datasize = AEGetDescDataSize (&aete);
217
+ data = (void *)malloc (datasize);
218
+ if (data == NULL)
219
+ BOOM ("cannot allocate memory");
220
+
221
+ osa_error = AEGetDescData (&aete, data, datasize);
222
+ AEDisposeDesc (&aete);
223
+ if (osa_error != noErr) {
224
+ free (data);
225
+ BOOM ("get data");
226
+ }
227
+
228
+ if (mkstemps (tmp_res_path, 5) == -1) {
229
+ free (data);
230
+ BOOM ("generate resource file name");
231
+ }
232
+
233
+ fd = open (tmp_res_path, O_CREAT|O_TRUNC|O_WRONLY, 0644);
234
+ if (fd == -1) {
235
+ free (data);
236
+ BOOM ("creating resource file");
237
+ }
238
+ close (fd);
239
+
240
+ FSPathMakeRef ((const UInt8 *)tmp_res_path, &fs, NULL);
241
+ FSGetResourceForkName (&resourceForkName);
242
+
243
+ osa_error = FSCreateResourceFork (&fs, resourceForkName.length, resourceForkName.unicode, 0);
244
+ if (osa_error != noErr) {
245
+ free (data);
246
+ BOOM ("creating resource fork");
247
+ }
248
+
249
+ osa_error = FSOpenResourceFile (&fs, resourceForkName.length, resourceForkName.unicode, fsRdWrPerm, &res_num);
250
+ if (osa_error != noErr) {
251
+ free (data);
252
+ BOOM ("opening resource fork");
253
+ }
254
+
255
+ res = NewHandle (datasize);
256
+ memcpy (*res, data, datasize);
257
+ AddResource (res, 'aete', 0, (ConstStr255Param)"");
258
+
259
+ free (data);
260
+ CloseResFile (res_num);
261
+
262
+ osa_error = OSACopyScriptingDefinition (&fs, kOSAModeNull, &sdef_data);
263
+ unlink (tmp_res_path);
264
+ if (osa_error != noErr)
265
+ rb_raise (rb_eRuntimeError, "Cannot get scripting definition : error %d", osa_error);
266
+
267
+ sdef = rb_str_new ((const char *)CFDataGetBytePtr (sdef_data),
268
+ CFDataGetLength (sdef_data));
269
+
270
+ CFRelease (sdef_data);
271
+
272
+ return sdef;
273
+ }
274
+
275
+ VALUE
276
+ rbosa_scripting_info (VALUE self, VALUE hash)
277
+ {
278
+ const char * error;
279
+ VALUE criterion;
280
+ VALUE value;
281
+ VALUE remote;
282
+ char c_remote[128];
283
+ VALUE ary;
284
+ VALUE name;
285
+ VALUE signature;
286
+ VALUE sdef;
287
+ OSAError osa_error;
288
+
289
+ Check_Type (hash, T_HASH);
290
+
291
+ criterion = name = signature = Qnil;
292
+ value = __get_criterion (hash, "name", &criterion);
293
+ if (NIL_P (value))
294
+ value = __get_criterion (hash, "path", &criterion);
295
+ if (NIL_P (value))
296
+ value = __get_criterion (hash, "bundle_id", &criterion);
297
+ if (NIL_P (value))
298
+ value = __get_criterion (hash, "signature", &criterion);
299
+ if (NIL_P (value))
300
+ rb_raise (rb_eArgError, "expected :name, :path, :bundle_id or :signature key/value");
301
+
302
+ remote = __get_criterion (hash, "machine", NULL);
303
+ if (!NIL_P (remote)) {
304
+ VALUE username;
305
+ VALUE password;
306
+
307
+ if (NIL_P (value) || criterion != ID2SYM (rb_intern ("name")))
308
+ rb_raise (rb_eArgError, ":machine argument requires :name");
309
+ name = value;
310
+
311
+ username = __get_criterion (hash, "username", NULL);
312
+ password = __get_criterion (hash, "password", NULL);
313
+
314
+ if (NIL_P (username)) {
315
+ if (!NIL_P (password))
316
+ rb_raise (rb_eArgError, ":password argument requires :username");
317
+ snprintf (c_remote, sizeof c_remote, "eppc://%s/%s",
318
+ RVAL2CSTR (remote), RVAL2CSTR (value));
319
+ }
320
+ else {
321
+ if (NIL_P (password))
322
+ snprintf (c_remote, sizeof c_remote, "eppc://%s@%s/%s",
323
+ RVAL2CSTR (username), RVAL2CSTR (remote),
324
+ RVAL2CSTR (value));
325
+ else
326
+ snprintf (c_remote, sizeof c_remote, "eppc://%s:%s@%s/%s",
327
+ RVAL2CSTR (username), RVAL2CSTR (password),
328
+ RVAL2CSTR (remote), RVAL2CSTR (value));
329
+ }
330
+
331
+ remote = CSTR2RVAL (c_remote);
332
+ }
333
+
334
+ if (RHASH_TBL(hash)->num_entries > 0) {
335
+ VALUE keys;
336
+
337
+ keys = rb_funcall (hash, rb_intern ("keys"), 0);
338
+ rb_raise (rb_eArgError, "inappropriate argument(s): %s",
339
+ RSTRING_PTR(rb_inspect (keys)));
340
+ }
341
+
342
+ if (NIL_P (remote)) {
343
+ FSRef fs;
344
+ CFDataRef sdef_data;
345
+
346
+ if (!rbosa_translate_app (criterion, value, &signature, &name, &fs, &error))
347
+ rb_raise (rb_eRuntimeError, error);
348
+
349
+ osa_error = OSACopyScriptingDefinition (&fs, kOSAModeNull, &sdef_data);
350
+ if (osa_error != noErr)
351
+ rb_raise (rb_eRuntimeError, "Cannot get scripting definition : error %d", osa_error);
352
+
353
+ sdef = rb_str_new ((const char *)CFDataGetBytePtr (sdef_data),
354
+ CFDataGetLength (sdef_data));
355
+
356
+ CFRelease (sdef_data);
357
+ }
358
+ else {
359
+ sdef = get_remote_app_sdef (c_remote);
360
+ }
361
+
362
+ ary = rb_ary_new3 (3, name, NIL_P (remote) ? signature : remote, sdef);
363
+
364
+ return ary;
365
+ }
366
+
367
+ VALUE
368
+ rbosa_remote_processes (VALUE self, VALUE machine)
369
+ {
370
+ char buf[128];
371
+ CFStringRef str;
372
+ CFURLRef url;
373
+ AERemoteProcessResolverRef resolver;
374
+ CFArrayRef cfary;
375
+ CFStreamError cferr;
376
+ VALUE ary;
377
+ unsigned i, count;
378
+
379
+ snprintf (buf, sizeof buf, "eppc://%s", RVAL2CSTR (machine));
380
+ str = CFStringCreateWithCString (kCFAllocatorDefault, buf, kCFStringEncodingUTF8);
381
+ url = CFURLCreateWithString (kCFAllocatorDefault, str, NULL);
382
+ CFRelease (str);
383
+ resolver = AECreateRemoteProcessResolver (kCFAllocatorDefault, url);
384
+ CFRelease (url);
385
+
386
+ cfary = AERemoteProcessResolverGetProcesses (resolver, &cferr);
387
+ if (cfary == NULL) {
388
+ AEDisposeRemoteProcessResolver (resolver);
389
+ rb_raise (rb_eRuntimeError, "Can't resolve the remote processes on machine '%s' : error %d (domain %d)",
390
+ RVAL2CSTR (machine), cferr.error, cferr.domain);
391
+ }
392
+
393
+ ary = rb_ary_new ();
394
+ for (i = 0, count = CFArrayGetCount (cfary); i < count; i++) {
395
+ CFDictionaryRef dict;
396
+ VALUE hash;
397
+ CFNumberRef number;
398
+
399
+ dict = (CFDictionaryRef)CFArrayGetValueAtIndex (cfary, i);
400
+ hash = rb_hash_new ();
401
+
402
+ url = CFDictionaryGetValue (dict, kAERemoteProcessURLKey);
403
+ if (url == NULL)
404
+ continue;
405
+
406
+ url = CFURLCopyAbsoluteURL (url);
407
+ str = CFURLGetString (url);
408
+
409
+ rb_hash_aset (hash, ID2SYM (rb_intern ("url")), CSTR2RVAL (CFStringGetCStringPtr (str, CFStringGetFastestEncoding (str))));
410
+
411
+ CFRelease (url);
412
+
413
+ str = CFDictionaryGetValue (dict, kAERemoteProcessNameKey);
414
+ if (str == NULL)
415
+ continue;
416
+
417
+ rb_hash_aset (hash, ID2SYM (rb_intern ("name")), CSTR2RVAL (CFStringGetCStringPtr (str, CFStringGetFastestEncoding (str))));
418
+
419
+ number = CFDictionaryGetValue (dict, kAERemoteProcessUserIDKey);
420
+ if (number != NULL) {
421
+ int uid;
422
+
423
+ if (CFNumberGetValue (number, kCFNumberIntType, &uid))
424
+ rb_hash_aset (hash, ID2SYM (rb_intern ("uid")), INT2FIX (uid));
425
+ }
426
+
427
+ number = CFDictionaryGetValue (dict, kAERemoteProcessProcessIDKey);
428
+ if (number != NULL) {
429
+ int pid;
430
+
431
+ if (CFNumberGetValue (number, kCFNumberIntType, &pid))
432
+ rb_hash_aset (hash, ID2SYM (rb_intern ("pid")), INT2FIX (pid));
433
+ }
434
+
435
+ rb_ary_push (ary, hash);
436
+ }
437
+
438
+ AEDisposeRemoteProcessResolver (resolver);
439
+
440
+ return ary;
441
+ }