Commit | Line | Data |
---|---|---|
21c4e167 H |
1 | /* |
2 | The contents of this file are subject to the Mozilla Public | |
3 | License Version 1.1 (the "License"); you may not use this file | |
4 | except in compliance with the License. You may obtain a copy of | |
5 | the License at http://www.mozilla.org/MPL/ | |
6 | ||
7 | Software distributed under the License is distributed on an "AS | |
8 | IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
9 | implied. See the License for the specific language governing | |
10 | rights and limitations under the License. | |
11 | ||
12 | fehmozexRunProgram and fehmozexGetEnvironment are taken from MozEx (and modified). | |
13 | MozEx is Copyright (C) 2003 Tomas Styblo <tripie@cpan.org> | |
14 | the stuff to read link-handlers.js cargo culted from AdBlock plus | |
15 | The rest is by Larry D'Anna and are Copyright (C) 2007 Larry D'Anna <larry@elder-gods.org> | |
16 | ||
17 | */ | |
18 | ||
19 | function fehError (msg) { | |
20 | alert(msg); | |
21 | } | |
22 | ||
23 | function fehmozexGetEnvironment(key) { | |
24 | var res=""; | |
25 | ||
26 | try { | |
27 | var pr = Components.classes["@mozilla.org/process/util;1"]. | |
28 | createInstance(Components.interfaces.nsIProcess); | |
29 | var env = Components.classes["@mozilla.org/process/environment;1"]; | |
30 | ||
31 | if (env != null) | |
32 | { | |
33 | env = env.createInstance(Components.interfaces.nsIEnvironment); | |
34 | res = env.get(key); | |
35 | } | |
36 | else | |
37 | { | |
38 | // Hack for mozilla 1.4 | |
39 | res = pr.getEnvironment(key); | |
40 | } | |
41 | } | |
42 | catch (e) | |
43 | { | |
44 | // do nothing | |
45 | } | |
46 | return res; | |
47 | } | |
48 | ||
49 | function fehmozexRunProgram(cmd, esc) { | |
50 | if (cmd == null || cmd.length == 0) { | |
51 | return false; // no command is set | |
52 | } | |
53 | var args = new Array(); | |
54 | ||
55 | // Match either | |
56 | // a) apos. followed by anything till apos. followed by space or end of string | |
57 | // - escape apos. by backslash, if it is not supposed to be part of the string | |
58 | // b) space delimited word | |
59 | // - escape space by backslash, if it is not supposed to be part of the string | |
60 | // No other escaping is implemented, because it would make writing windows-like | |
61 | // paths hard | |
62 | // | |
63 | // Use debugging facility to see what is the result if you are not sure how | |
64 | // to use this | |
65 | scmd=cmd.match(/"(\"|.)*?"(?=\s|$)|(\\\s|\S)+/g); | |
66 | for (var i in scmd) | |
67 | { | |
68 | // If it is apos. delimited | |
69 | if (scmd[i].slice(0,1)=='"') | |
70 | { | |
71 | // Remove quotes on the begin and end | |
72 | scmd[i]=scmd[i].replace(/^"(.*?)"$/, "$1"); | |
73 | // De-escape apostroph | |
74 | // \x22 is a " but the " is fucking up my emacs colors | |
75 | scmd[i]=scmd[i].replace(/\\\x22/g, "\x22"); | |
76 | } else { | |
77 | // De-escape spaces | |
78 | scmd[i]=scmd[i].replace(/\\(\s)/g, "$1"); | |
79 | } | |
80 | } | |
81 | ||
82 | var executable = scmd.shift(); | |
83 | if (executable.length == 0) { | |
84 | fehError("no executable in command"); | |
85 | return false; | |
86 | } | |
87 | ||
88 | for (var i = 0; i < scmd.length; i++) { | |
89 | var param = scmd[i]; | |
90 | var buf = ""; | |
91 | if (param.length == 0) { | |
92 | continue; | |
93 | } | |
94 | for (var e = 0; e < param.length; e++) { | |
95 | var c = param[e]; | |
96 | if (c == '%') { | |
97 | var a = param[++e]; | |
98 | if (esc[a] === undefined) { | |
99 | fehError("unknown escape in command '" + cmd + "': %" + a); | |
100 | return false; | |
101 | } | |
102 | else { | |
103 | buf += esc[a]; | |
104 | } | |
105 | } | |
106 | else { | |
107 | buf += c; | |
108 | } | |
109 | } | |
110 | args.push(buf); | |
111 | } | |
112 | ||
113 | try { | |
114 | var exec = Components.classes["@mozilla.org/file/local;1"]. | |
115 | createInstance(Components.interfaces.nsILocalFile); | |
116 | var pr = Components.classes["@mozilla.org/process/util;1"]. | |
117 | createInstance(Components.interfaces.nsIProcess); | |
118 | var path = null; | |
119 | ||
120 | // $PATH stuff (only on UNIX) | |
121 | if (window.navigator.platform.toLowerCase().indexOf("win") == -1) | |
122 | { | |
123 | path = fehmozexGetEnvironment("PATH").split(":"); | |
124 | } | |
125 | ||
126 | // If executable is an absolute path or we don not know how to get PATH | |
127 | // (windows), run it or fail. Otherwise look for the executable in $PATH. | |
128 | // FIXME: How do you tell portably if a path is absolute? | |
129 | if (executable.charAt(0) == "/" || path == null) { | |
130 | dump ("feh: executable is " + executable + "\n"); | |
131 | exec.initWithPath(executable); | |
132 | if (! exec.exists()) { | |
133 | throw "executable '" + executable + "' does not exist."; | |
134 | } | |
135 | } | |
136 | else { | |
137 | var found = false; | |
138 | for (i = 0; i < path.length; i++) { | |
139 | exec.initWithPath(path[i]); | |
140 | exec.appendRelativePath(executable); | |
141 | if (exec.exists()) { | |
142 | dump ("feh: executable is " + path[i] + "/" + executable + "\n"); | |
143 | found = true; | |
144 | break; | |
145 | } | |
146 | } | |
147 | if (!found) { | |
148 | throw "could not find '" + executable + "' in path:\n" + path.join ("\n"); | |
149 | } | |
150 | } | |
151 | ||
152 | ||
153 | for (var j = 0; j < args.length; j ++) | |
154 | dump ("feh: arg " + j + " is " + args[j] + "\n"); | |
155 | ||
156 | ||
157 | pr.init(exec); | |
158 | pr.run(false /* don't block */, args, args.length); | |
159 | } | |
160 | catch (e) { | |
161 | fehError("cannot run executable '" + | |
162 | executable + "' (args: " + args + "): " + e); | |
163 | return false; | |
164 | } | |
165 | // alert(pr.pid); /* pid is not implemented :((( */ | |
166 | return true; | |
167 | } | |
168 | ||
169 | var feh = { | |
170 | ||
171 | onshow: function() { | |
172 | ||
173 | for (var name in feh.progs) { | |
174 | gContextMenu.showItem( "context-" + name, gContextMenu.onLink ); | |
175 | } | |
176 | ||
177 | //gContextMenu.showItem( "context-za", gContextMenu.onLink ); | |
178 | //alert(">>>>>> " + gContextMenu.linkURL); | |
179 | }, | |
180 | ||
181 | onLoad: function() { | |
182 | // initialization code | |
183 | this.initialized = true; | |
184 | ||
185 | try { | |
186 | ||
187 | var dirService = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties); | |
188 | var path = dirService.get("ProfD", Components.interfaces.nsIFile); | |
189 | path.append("link-handlers.js"); | |
190 | ||
191 | var stream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream); | |
192 | ||
193 | stream.init(path, 0x01, 0444, 0); | |
194 | ||
195 | var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"] | |
196 | .createInstance(Components.interfaces.nsIScriptableInputStream); | |
197 | sstream.init(stream); | |
198 | ||
199 | var data = ""; | |
200 | ||
201 | var str = sstream.read(4096); | |
202 | while (str.length > 0) { | |
203 | data += str; | |
204 | str = sstream.read(4096); | |
205 | } | |
206 | ||
207 | sstream.close(); | |
208 | stream.close(); | |
209 | ||
210 | //alert(data); | |
211 | ||
212 | progs = eval("feh.progs = " + data + ";"); | |
213 | } catch (e) { | |
214 | fehError("error reading link-handlers.js: " + e); | |
215 | return null; | |
216 | } | |
217 | ||
218 | var menu = document.getElementById("contentAreaContextMenu"); | |
219 | var ni; | |
220 | ||
221 | /* | |
222 | ni = document.createElement("menuitem"); | |
223 | ni.setAttribute("label", "feh"); | |
224 | ni.setAttribute("oncommand", "feh(this);"); | |
225 | menu.appendChild(ni); | |
226 | ||
227 | ni = document.createElement("menuitem"); | |
228 | ni.setAttribute("label", "za"); | |
229 | ni.setAttribute("id", "context-za"); | |
230 | ni.setAttribute("oncommand", "feh.za(this)"); | |
231 | menu.appendChild(ni); | |
232 | ||
233 | */ | |
234 | ||
235 | feh.proga = new Array(); | |
236 | var i = 0; | |
237 | ||
238 | for (var name in feh.progs) { | |
239 | dump("FEHHH " + name + " ::: " + feh.progs[name] + "\n"); | |
240 | /* | |
241 | feh.progsubs[name] = function() { | |
242 | fehmozexRunProgram (feh.progs[name], {'r' : gContextMenu.linkURL}); | |
243 | }*/ | |
244 | feh.proga.push (name); | |
245 | ni = document.createElement("menuitem"); | |
246 | ni.setAttribute("label", name); | |
247 | ni.setAttribute("id", "context-" + name); | |
248 | //ni.setAttribute("oncommand", "dump(\"ZZZZZZZZZZZZ +\"" + name + "\"\\n\"); feh.progsubs[\"" + name + "\"];"); | |
249 | //ni.setAttribute("oncommand", "dump(\"ZZZZZZZZZZZZ "+ name +"\\n\");"); | |
250 | dump("ZZZZZ: fehDispatch(\""+ name +"\");\n"); | |
251 | //ni.setAttribute("oncommand", "fehDispatch(\""+ name +"\");"); | |
252 | ni.setAttribute("oncommand", "fehDispatch("+ i +");"); | |
253 | menu.appendChild(ni); | |
254 | i++; | |
255 | } | |
256 | dump ("end feh\n") | |
257 | ||
258 | var h = menu.getAttribute("onpopupshowing"); | |
259 | menu.feh_onshowing = eval ("function(event) {" + h + "}"); | |
260 | ||
261 | /* | |
262 | menu.setAttribute("onpopupshowing", | |
263 | "if (event.target != this) return true; gContextMenu = new nsContextMenu( this ); feh.onshow(); return gContextMenu.shouldDisplay;");*/ | |
264 | ||
265 | menu.setAttribute("onpopupshowing", "var ret = this.feh_onshowing(event); feh.onshow(); return x;"); | |
266 | //alert(menu.initClipboardItems); | |
267 | ||
268 | }, | |
269 | ||
270 | progs: {}, | |
271 | ||
272 | /* | |
273 | progs: { | |
274 | "seeurl" : "gnome-terminal -x sh -c \"echo foo: %r | less\" ", | |
275 | "links" : "gnome-terminal -x links %r " }, | |
276 | */ | |
277 | ||
278 | //progsubs: {}, | |
279 | ||
280 | za: function(o) { | |
281 | fehmozexRunProgram ("gnome-terminal -x sh -c \"echo foo: %r | less\" ", {'r' : gContextMenu.linkURL}); | |
282 | } | |
283 | ||
284 | ||
285 | }; | |
286 | ||
287 | function fehDispatch(i) { | |
288 | var name = feh.proga[i]; | |
289 | fehmozexRunProgram (feh.progs[name], {'r' : gContextMenu.linkURL}); | |
290 | } | |
291 | ||
292 | ||
293 | /* | |
294 | function feh(o) { | |
295 | alert("feh " + o.parentNode.localName + ":::" + o.parentNode.getAttribute("onpopupshowing")); | |
296 | } | |
297 | */ | |
298 | ||
299 | ||
300 | //window.addEventListener("load", function(e) { feh.onLoad(e); }, false); |