43 |
44 |
45 |
--------------------------------------------------------------------------------
/chrome/options.js:
--------------------------------------------------------------------------------
1 | function Options() {
2 | this.throbber_ = null;
3 | // False until we know the service is running.
4 | this.is_alive_ = false;
5 | }
6 | Options.prototype = {
7 | init: function() {
8 | $("#enable_scheduled_updates").change(function() {
9 | chrome.extension.sendRequest({
10 | action: "set-settings",
11 | enable_scheduled_updates: $(this).val() == "on"
12 | });
13 | });
14 |
15 | this.throbber_ = new Throbber(window, document.getElementById("throbber"));
16 | chrome.extension.onRequest.addListener(bind(this, "onRequest_"));
17 | this.refresh_();
18 | },
19 |
20 | update: function(force) {
21 | chrome.extension.sendRequest({action: force ? "force-update" : "update"});
22 | },
23 |
24 | reset: function() {
25 | chrome.extension.sendRequest({action: "reset"}, function(response) {
26 | $("#status").html("Settings reset. Restart the extension.");
27 | });
28 | },
29 |
30 | refresh_: function() {
31 | chrome.extension.sendRequest({action: "get-settings"}, function(response) {
32 | if (!this.is_alive_) {
33 | this.is_alive_ = true;
34 | $("#status").html("Ready.");
35 | }
36 | $("#index_date").html(new Date(response.current_version) + "");
37 | $("#script_count").html(response.script_count);
38 | $("#enable_scheduled_updates").attr(
39 | "checked", response.enable_scheduled_updates);
40 | $("#next_update_date").html(new Date(response.next_update_date) + "");
41 | });
42 | },
43 |
44 | onRequest_: function(request, sender, sendRequest) {
45 | if (request.action == "initialized") {
46 | this.is_alive_ = true;
47 | $("#status").html("Ready.");
48 | this.refresh_();
49 | }
50 | if (request.action == "updater-start") {
51 | $("#status").html("Updating...");
52 | this.throbber_.start();
53 | }
54 | if (request.action == "updater-done") {
55 | this.throbber_.stop();
56 | $("#status").html("Ready.");
57 | this.refresh_();
58 | }
59 | if (request.action == "updater-status") {
60 | $("#status").html(request.message);
61 | }
62 | if (request.action == "updater-progress") {
63 | $("#status").html(request.loaded);
64 | }
65 | }
66 | }
67 |
68 | var options = new Options();
69 |
--------------------------------------------------------------------------------
/chrome/picker.css:
--------------------------------------------------------------------------------
1 | body {
2 | line-height: 1.5;
3 | font-family: Helvetica Neue, Arial, Helvetica, sans-serif;
4 | color: #333333;
5 | font-size: 75%;
6 | min-width: 357px;
7 | overflow-x: hidden;
8 | }
9 |
10 | p { margin: 0 0 1.5em; }
11 |
12 | .la {
13 | text-align: left;
14 | }
15 |
16 | thead th { background: #c3d9ff; }
17 |
18 | th, td, caption { padding: 4px 10px 4px 5px; }
19 |
20 | tr.even td { background: #e5ecf9; }
21 |
22 | table {
23 | border-collapse: collapse;
24 | }
25 | table p {
26 | margin: 0.625em 0;
27 | line-height: 1.25em;
28 | }
29 | table.noborder td {
30 | border: 0;
31 | }
32 | table.nopad td {
33 | padding-left: 0;
34 | }
35 | table.wide {
36 | width: 100%;
37 | }
38 | table tr td.inv {
39 | background: #eee;
40 | }
41 | table tr td.vat {
42 | vertical-align: top;
43 | }
44 | table tr td.narrow {
45 | padding: 2px 5px;
46 | }
47 | table tr td.script-install {
48 | width: 16px;
49 | padding: 9px 0 0 7px;
50 | vertical-align: top;
51 | border-right: 0;
52 | }
53 | table tr td.script-meat {
54 | border-left: 0;
55 | padding-left: 7px;
56 | }
57 | th {
58 | background:none repeat scroll 0 0 #333333;
59 | border:1px solid #222222;
60 | color:white;
61 | font-size:1em;
62 | padding:3px 10px;
63 | }
64 | th a {
65 | color:white;
66 | font-size:1.1em;
67 | }
68 | th a:hover {
69 | color:#FFDD00;
70 | }
71 | th a:active {
72 | color:#FF8800;
73 | }
74 |
75 |
76 | span.rating {
77 | background: url(images/5stars-small-2.png) top left;
78 | width: 60px;
79 | display: block;
80 | height: 12px;
81 | }
82 | span.rating span.number {
83 | display: none;
84 | }
85 | span.rating span.stars {
86 | background: url(images/5stars-small-2.png) bottom left;
87 | display: block;
88 | height: 12px;
89 | width: 40px;
90 | }
91 |
--------------------------------------------------------------------------------
/chrome/picker.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/chrome/picker.js:
--------------------------------------------------------------------------------
1 | var HOUR_MS = 1000 * 60 * 60;
2 | var DAY_MS = HOUR_MS * 24;
3 |
4 | $(document).ready(function() {
5 | chrome.tabs.getSelected(null, function(tab) {
6 | var timer = new Timer();
7 | timer.mark("start search");
8 | chrome.extension.sendRequest(
9 | {action: "search", url: tab.url},
10 | function(response) {
11 | try {
12 | timer.mark("end search");
13 | if (response.status) {
14 | var results = [];
15 | for (var id in response.results) {
16 | var r = response.results[id];
17 | r.id = id;
18 | var updated = new Date(r.updated);
19 | r.updated_formatted = formatDate(updated);
20 | r.updated_iso8601 = formatISO8601(updated);
21 | results.push(r);
22 | }
23 |
24 | results.sort(function(a, b) {
25 | return b.rank - a.rank;
26 | });
27 |
28 | $("#results").pureJSTemplate({
29 | id : "tpl",
30 | data : {
31 | results: results
32 | }
33 | });
34 | timer.mark("end html");
35 | }
36 | } catch(e) { alert(e); }
37 | });
38 |
39 | });
40 |
41 | $("#results").click(function(e) {
42 | var url = e.target.href;
43 | if (!url)
44 | return;
45 |
46 | var a = url.match(/chrome-extension:\/\/[^/]*(.*)/);
47 | if (!(a && a.length == 2))
48 | return;
49 |
50 | url = "http://userscripts.org" + a[1];
51 | chrome.tabs.create({url: url});
52 | window.close();
53 | });
54 | });
55 |
56 | function formatDate(d) {
57 | var age = Date.now() - d.getTime();
58 | if (age < DAY_MS)
59 | return Math.floor(age / HOUR_MS) + " hours";
60 | var month_name = d.toString().split(" ")[1];
61 | return month_name + " " + d.getDate() + " " + d.getFullYear();
62 | }
63 |
--------------------------------------------------------------------------------
/chrome/purejstemplate_jquery.js:
--------------------------------------------------------------------------------
1 | /*
2 | PureJSTemplate
3 | Author: Mohammad S. Rahman
4 | License: MohammadLicense- use it, but quote me or I'll get you.
5 | Test: /test/purejstemplatetest.html
6 |
7 | Why use this: ITS FAST!!!
8 | */
9 | (function($) {
10 | $.fn.pureJSTemplate=function(options) {
11 | var tplID=options.id;
12 | var input= options.data;
13 | var tplObj=tplMap[tplID];
14 |
15 | if(!tplObj) {
16 | var tpl = document.getElementById(tplID).value;
17 |
18 | var leftjs=String.fromCharCode(21);
19 | var leftjsout=leftjs + "=";
20 |
21 | tpl=tpl.replace(replaceLeft, left+leftjs );
22 |
23 | var tplSplit = tpl.split(regexLeftRight);
24 | var js="var data=arguments[0]; var output=''; var ld='"+left+"'; var rd='"+right+"'; ";
25 | for(var i=0; i 0) {
273 | if (progress) {
274 | progress(total, stmts.length);
275 | }
276 | var pair = stmts.shift();
277 | t.executeSql(pair[0], pair[1], run_next_statement, fail);
278 | } else {
279 | callback(true);
280 | }
281 | };
282 |
283 | this.db_.transaction(run_next_statement);
284 | })
285 | }
286 |
--------------------------------------------------------------------------------
/chrome/stream.js:
--------------------------------------------------------------------------------
1 | function Stream() {
2 | this.pos_ = 0;
3 | this.length_ = 0;
4 | this.canvas_ = null;
5 | this.data_ = null;
6 | }
7 |
8 | Stream.prototype = {
9 | getb_: function() {
10 | if (this.pos_ >= this.length_)
11 | throw new Error("out of bounds");
12 |
13 | var b = this.data_[this.pos_ + Math.floor(this.pos_ / 3)];
14 | this.pos_++;
15 | return b;
16 | },
17 |
18 | load: wrap(function(document, url, callback) {
19 | d("Stream.load " + url);
20 | var timer = new Timer();
21 | var image = new Image();
22 | var that = this;
23 | image.onload = function() {
24 | that.length_ = image.width * image.height * 3;
25 | that.canvas_ = document.createElement("canvas");
26 | that.canvas_.width = image.width;
27 | that.canvas_.height = image.height;
28 | var context = that.canvas_.getContext("2d");
29 | context.drawImage(image, 0, 0, image.width, image.height);
30 | that.data_ = context.getImageData(0, 0, image.width, image.height).data;
31 | that.pos_ = 0;
32 | timer.mark("stream loaded from '" + url + "', length = " + that.length_);
33 | callback();
34 | };
35 | image.src = url;
36 | }),
37 |
38 | getDataUrl: function() {
39 | return this.canvas_.toDataURL();
40 | },
41 |
42 | length: function() {
43 | return this.length_;
44 | },
45 |
46 | seek: function(pos) {
47 | if (pos >= this.length_)
48 | throw new Error("out of bounds");
49 | this.pos_ = pos;
50 | },
51 |
52 | read8: function() {
53 | return this.getb_();
54 | },
55 |
56 | read16: function() {
57 | return (this.getb_() << 8) + this.getb_();
58 | },
59 |
60 | read64: function() {
61 | return (this.getb_() << 56) +
62 | (this.getb_() << 48) +
63 | (this.getb_() << 40) +
64 | (this.getb_() << 32) +
65 | (this.getb_() << 24) +
66 | (this.getb_() << 16) +
67 | (this.getb_() << 8) +
68 | this.getb_();
69 | }
70 | }
71 |
72 |
--------------------------------------------------------------------------------
/chrome/throbber.js:
--------------------------------------------------------------------------------
1 | function Throbber(window, div) {
2 | this.win_ = window;
3 | this.div_ = div;
4 | this.id_ = null;
5 | this.running_ = false;
6 | this.pos_ = 0;
7 | }
8 | Throbber.prototype = {
9 | start: function() {
10 | if (this.running_)
11 | return;
12 |
13 | this.running_ = true;
14 | this.startTimer_();
15 | },
16 | stop: function() {
17 | this.running_ = false;
18 | this.win_.clearTimeout(this.id_);
19 | delete this.id_;
20 | },
21 | tick_: function() {
22 | if (!this.running_)
23 | return;
24 | this.pos_++;
25 | if (this.pos_ > 35)
26 | this.pos_ = 0;
27 | $(this.div_).css({backgroundPosition: (this.pos_ * -16) + "px"});
28 | this.startTimer_();
29 | },
30 | startTimer_: function() {
31 | var that = this;
32 | this.id_ = this.win_.setTimeout(function() { that.tick_(); }, 50);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/chrome/throbber.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/chrome/throbber.png
--------------------------------------------------------------------------------
/chrome/updater.js:
--------------------------------------------------------------------------------
1 | var URL = "http://skrul.com/projects/greasefire/indexes/";
2 |
3 | var TIME_CHECK_INTERVAL = 60 * 1000;
4 | var DAYS_TO_MILLISECONDS = 24 * 60 * 60 * 1000;
5 |
6 | function Updater(store) {
7 | function setIf(key, value) {
8 | if (localStorage[key] === undefined) {
9 | localStorage[key] = value;
10 | }
11 | }
12 |
13 | setIf("enable_scheduled_updates", true);
14 | setIf("update_interval_ms", DAYS_TO_MILLISECONDS);
15 | // Schedule our first update for 30 seconds from now.
16 | setIf("next_update_date", Date.now() + (1000 * 30));
17 |
18 | this.store_ = store;
19 | this.update_interval_ms_ = parseInt(localStorage["update_interval_ms"]);
20 | this.next_update_date_ =
21 | new Date(parseInt(localStorage["next_update_date"]));
22 | this.isUpdating_ = false;
23 | this.enable_scheduled_updates_ =
24 | localStorage["enable_scheduled_updates"] == "true";
25 | this.timer_id = null;
26 | }
27 |
28 | Updater.prototype = {
29 | reset: function() {
30 | delete localStorage["enable_scheduled_updates"];
31 | delete localStorage["update_interval_ms"];
32 | delete localStorage["next_update_date"];
33 | },
34 |
35 | startScheduledUpdates: function() {
36 | this.startTimer_();
37 | },
38 |
39 | enable_scheduled_updates: function() {
40 | return this.enable_scheduled_updates_;
41 | },
42 |
43 | set_enable_scheduled_updates: function(val) {
44 | this.enable_scheduled_updates_ = val;
45 | localStorage["enable_scheduled_updates"] = val;
46 | },
47 |
48 | next_update_date: function() {
49 | return this.next_update_date_;
50 | },
51 |
52 | notifyStart_: function() {
53 | chrome.extension.sendRequest({action: "updater-start"});
54 | },
55 |
56 | notifyDone_: function() {
57 | chrome.extension.sendRequest({action: "updater-done"});
58 | },
59 |
60 | notifyStatus_: function(message) {
61 | chrome.extension.sendRequest(
62 | {action: "updater-status", message: message});
63 | },
64 |
65 | update: wrap(function(force, callback) {
66 | if (this.isUpdating_) {
67 | callback(false, "Already updating");
68 | return;
69 | }
70 |
71 | var that = this;
72 | this.notifyStart_();
73 |
74 | var finish = function(success, error) {
75 | that.scheduleNextUpdate_();
76 | that.notifyDone_();
77 | callback(success, error);
78 | };
79 |
80 | this.getVersion_(URL + "latest", function(success, latest_version) {
81 | if (!success) {
82 | finish(false, "can't read version");
83 | return;
84 | }
85 |
86 | var current_version = that.store_.current_version();
87 | d("latest version " + latest_version);
88 | d("current version " + current_version);
89 | if (!force && current_version && latest_version <= current_version) {
90 | that.notifyStatus_("Index is up to date.");
91 | finish(true);
92 | return;
93 | }
94 |
95 | var base_url = URL + formatISO8601(latest_version);
96 | that.updateFromBaseUrl_(base_url, latest_version, function(success, error) {
97 | finish(success, error);
98 | });
99 | });
100 | }),
101 |
102 | updateWithLocalData: wrap(function(callback) {
103 | if (this.isUpdating_) {
104 | callback(false, "Already updating");
105 | return;
106 | }
107 |
108 | var that = this;
109 | this.getVersion_("indexes/latest", function(success, local_version) {
110 | if (!success) {
111 | callback(false, "can't read local version");
112 | return;
113 | }
114 | d("local version " + local_version);
115 | that.updateFromBaseUrl_("indexes", local_version, callback);
116 | });
117 | }),
118 |
119 | updateFromBaseUrl_: wrap(function(base_url, version, callback) {
120 | d("Updater.updateFromBaseUrl_ " + base_url + " " + version);
121 |
122 | var that = this;
123 | this.isUpdating_ = true;
124 | var finish = function(success, error) {
125 | that.isUpdating_ = false;
126 | callback(success, error);
127 | };
128 |
129 | var includes;
130 | var excludes;
131 | var scripts;
132 |
133 | var on_progress = function(loaded, total) {
134 | chrome.extension.sendRequest({
135 | action: "updater-status",
136 | message: "Downloading indexes (" + loaded + ")"});
137 | };
138 |
139 | var done_downloading = function(data, error) {
140 | if (data) {
141 | scripts = data;
142 | that.store_.installNewData(
143 | version, includes, excludes, scripts, function() {
144 | finish(true);
145 | });
146 | } else {
147 | finish(false, error);
148 | }
149 | };
150 |
151 | var includes_dl = new Downloader(on_progress);
152 | var excludes_dl = new Downloader(on_progress);
153 | var scripts_dl = new Downloader(on_progress);
154 | includes_dl.get(base_url + "/include.dat", function(data, status) {
155 | if (!data) {
156 | finish(false, status);
157 | return;
158 | }
159 | includes = fixEncoding(data);
160 |
161 | excludes_dl.get(base_url + "/exclude.dat", function(data, status) {
162 | if (!data) {
163 | finish(false, status);
164 | return;
165 | }
166 | excludes = fixEncoding(data);
167 |
168 | scripts_dl.get(base_url + "/scripts.txt", function(data, status) {
169 | if (!data) {
170 | finish(false, status);
171 | return;
172 | }
173 | scripts = data;
174 |
175 | that.store_.installNewData(
176 | version, includes, excludes, scripts, function() {
177 | finish(true);
178 | });
179 | });
180 | });
181 | });
182 | }),
183 |
184 | getVersion_: wrap(function(url, callback) {
185 | var downloader = new Downloader();
186 | downloader.get(url + "?" + Math.random(), function(data, error) {
187 | if (data) {
188 | var d = parseISO8601(data);
189 | if (d) {
190 | callback(true, d);
191 | return;
192 | }
193 | }
194 | callback(false, error);
195 | });
196 | }),
197 |
198 | startTimer_: function() {
199 | if (this.timer_id)
200 | return;
201 | var that = this;
202 | this.timer_id = window.setTimeout(function() {
203 | that.tick_();
204 | }, TIME_CHECK_INTERVAL);
205 | },
206 |
207 | tick_: function() {
208 | d("tick " + (new Date()));
209 | if (this.enable_scheduled_updates_ &&
210 | Date.now() >= this.next_update_date_) {
211 | var that = this;
212 | this.update(false, function(success, error) {
213 | if (!success) {
214 | d("Error doing scheduled update: " + error);
215 | }
216 | that.startTimer_();
217 | });
218 | } else {
219 | this.startTimer_();
220 | }
221 | },
222 |
223 | scheduleNextUpdate_: function() {
224 | this.next_update_date_ = new Date(Date.now() + this.update_interval_ms_);
225 | localStorage["next_update_date"] = this.next_update_date_.getTime();
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/chrome/util.js:
--------------------------------------------------------------------------------
1 | var DEBUG = true;
2 | var DAYS_TO_SECONDS = 24 * 60 * 60;
3 |
4 | function Wrapper(that, callback) {
5 | this.that_ = that;
6 | this.callback_ = callback;
7 | }
8 | Wrapper.prototype = {
9 | wrap: function(f) {
10 | var that = this;
11 | return function() {
12 | try {
13 | f.apply(that.that_, arguments);
14 | } catch(e) {
15 | var message = e.message + "\n";
16 | message += stack().join("\n");
17 | that.callback_(false, message);
18 | }
19 | };
20 | }
21 | }
22 |
23 | function wrap(f) {
24 | return function() {
25 | try {
26 | f.apply(this, arguments);
27 | } catch(e) {
28 | var message = "wrap error: " + e;
29 | console.log(e);
30 | console.log(e.stack);
31 | arguments[arguments.length - 1](false, message);
32 | }
33 | };
34 | }
35 |
36 | function Timer() {
37 | if (!DEBUG) return;
38 | this.start_ = (new Date()).getTime();
39 | this.time_ = this.start_;
40 | }
41 | Timer.prototype = {
42 | mark: function(s) {
43 | if (!DEBUG) return;
44 | var now = (new Date()).getTime();
45 | this.log_(now - this.time_, "MARK: " + s);
46 | this.time_ = now;
47 | },
48 | done: function(s) {
49 | if (!DEBUG) return;
50 | var now = (new Date()).getTime();
51 | this.log_(now - this.start_, "DONE: " + s);
52 | },
53 | log_: function(ms, s) {
54 | d(s.substr(0, 1024) + " " + ms + "ms");
55 | }
56 | };
57 |
58 | function d(s) {
59 | if (DEBUG) {
60 | console.log(s.substr(0, 1024) + (s.length > 1024 ? "..." : ""));
61 | }
62 | }
63 |
64 | function bind(o, f) {
65 | return function() {
66 | if (typeof f == "string")
67 | f = o[f];
68 | f.apply(o, arguments);
69 | };
70 | }
71 |
72 | function stack() {
73 | var callstack = [];
74 | var currentFunction = arguments.callee.caller;
75 | while (currentFunction) {
76 | var fn = currentFunction.toString();
77 | var fname = fn.substring(fn.indexOf("function") + 8, fn.indexOf(' ')) || 'anonymous';
78 | callstack.push(fname);
79 | currentFunction = currentFunction.caller;
80 | }
81 | return callstack;
82 | }
83 |
84 | function parseISO8601(s) {
85 | var a = s.match(/(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z/);
86 | if (a && a.length == 7) {
87 | var d = new Date(a[1], a[2] - 1, a[3], a[4], a[5], a[6]);
88 | var offset = d.getTimezoneOffset() * 60 * 1000 * -1;
89 | d.setTime(d.getTime() + offset);
90 | return d;
91 | }
92 | alert("bad date " + s);
93 | return null;
94 | }
95 |
96 | function formatISO8601(d) {
97 | function pad(s) { return ("0" + s).substr(-2); }
98 | return d.getUTCFullYear() + "-" +
99 | pad(d.getUTCMonth() + 1) + "-" +
100 | pad(d.getUTCDate()) + "T" +
101 | pad(d.getUTCHours()) + ":" +
102 | pad(d.getUTCMinutes()) + ":" +
103 | pad(d.getUTCSeconds()) + "Z";
104 | }
105 |
106 | function fixEncoding(data) {
107 | function mask(data) {
108 | var a = [];
109 | var i = 0;
110 | while (i + 10 < data.length) {
111 | a.push(String.fromCharCode(data.charCodeAt(i ) & 0xff,
112 | data.charCodeAt(i + 1) & 0xff,
113 | data.charCodeAt(i + 2) & 0xff,
114 | data.charCodeAt(i + 3) & 0xff,
115 | data.charCodeAt(i + 4) & 0xff,
116 | data.charCodeAt(i + 5) & 0xff,
117 | data.charCodeAt(i + 6) & 0xff,
118 | data.charCodeAt(i + 7) & 0xff,
119 | data.charCodeAt(i + 8) & 0xff,
120 | data.charCodeAt(i + 9) & 0xff));
121 | i += 10;
122 | }
123 | for (; i < data.length; i++) {
124 | a.push(String.fromCharCode(data.charCodeAt(i) & 0xff));
125 | }
126 | return a.join("");
127 | }
128 |
129 | var timer = new Timer();
130 | var filtered = data.replace(/[\uf780-\uf7ff]{1,600}/g, mask);
131 | timer.mark("mask " + data.length + " bytes.");
132 | return filtered;
133 | }
134 |
--------------------------------------------------------------------------------
/firefox/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/firefox/chrome.manifest:
--------------------------------------------------------------------------------
1 | skin greasefire2 classic/1.0 chrome/content/
2 | overlay chrome://browser/content/browser.xul chrome://greasefire2/content/browser.xul
3 | content greasefire2 chrome/content/
4 |
5 | component {7c5b9317-0b18-4390-9a0a-a594d544a99f} components/gfUpdaterService.js
6 | contract @b0nk3rz.net/greasefire2/updater;1 {7c5b9317-0b18-4390-9a0a-a594d544a99f}
7 | category profile-after-change @b0nk3rz.net/greasefire2/updater;1 @b0nk3rz.net/greasefire2/updater;1
8 |
9 | component {d647ff9b-ac4c-4d0e-8fbd-484765be5549} components/gfGreasefireService.js
10 | contract @b0nk3rz.net/greasefire2/service;1 {d647ff9b-ac4c-4d0e-8fbd-484765be5549}
11 | category profile-after-change @b0nk3rz.net/greasefire2/service;1 @b0nk3rz.net/greasefire2/service;1
12 |
13 | component {0c1b14b2-4a2c-4ba4-bf38-0f6844439986} components/gfTestHarnessCommandLineHandler.js
14 | contract @b0nk3rz.net/greasefire2/testharness/commandlinehandler;1 {0c1b14b2-4a2c-4ba4-bf38-0f6844439986}s
15 | category command-line-handler @b0nk3rz.net/greasefire2/testharness/commandlinehandler;1 @b0nk3rz.net/greasefire2/testharness/commandlinehandler;1
16 |
17 | component {52b17aee-2705-42e0-bf2d-92afb900c4c8} components/gfTestHarnessCommandLineHandler.js
18 | contract @b0nk3rz.net/greasefire2/testharness/consolelistener;1 {52b17aee-2705-42e0-bf2d-92afb900c4c8}
19 |
20 | overlay chrome://greasefire2/content/prefs.xul chrome://greasefire2/content/closewindow.xul
21 | overlay chrome://greasefire2/content/picker.xul chrome://greasefire2/content/closewindow.xul
22 |
--------------------------------------------------------------------------------
/firefox/chrome/content/browser.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | .tbb-scripts-available .toolbarbutton-icon,
6 | /* Icons in a Puzzle Toolbar shouldn't have a background, so set the background on the button itself. */
7 | .puzzleBars-bar .tbb-scripts-available {
8 | background: linear-gradient(top, #f2825b 0%, #e55b2b 50%, #f07146 100%);
9 | background: -moz-linear-gradient(top, #f2825b 0%, #e55b2b 50%, #f07146 100%);
10 | }
11 |
--------------------------------------------------------------------------------
/firefox/chrome/content/browser.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 |
6 | var GreasefireController = {
7 |
8 | _XUL_NS: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
9 | _appContext: null,
10 | _menuItem: null,
11 | _currentResults: null,
12 | _currentURI: null,
13 | _toolbutton: null,
14 | $: function(aID) document.getElementById(aID),
15 |
16 | init: function() {
17 | XPCOMUtils.defineLazyGetter(this, "_gfs", function() {
18 | return Cc["@b0nk3rz.net/greasefire2/service;1"].getService().wrappedJSObject;
19 | });
20 |
21 | window.addEventListener("load", this, false);
22 | },
23 |
24 | _newLocation: function(aURI) {
25 | this._currentURI = aURI;
26 | this._currentResults = aURI ? this._gfs.search(aURI) : null;
27 | this._updateMenu();
28 | },
29 |
30 | _setupMenu: function() {
31 | if (this._menuItem)
32 | return false;
33 |
34 | this._toolbutton = this.$("greasemonkey-tbb") || this.$("scriptish-button");
35 |
36 | // Github #8: Prevent the JS error when neither GM or Scriptish are enabled
37 | if (!this._toolbutton) {
38 | return false;
39 | }
40 |
41 | var popup = this._toolbutton.firstChild;
42 | popup.insertBefore(document.createElementNS(this._XUL_NS, "menuseparator"),
43 | popup.firstChild);
44 |
45 | this._menuItem = document.createElementNS(this._XUL_NS, "menuitem");
46 | this._menuItem.addEventListener("command", function (event){GreasefireController.openResults();}, false);
47 |
48 | popup.insertBefore(this._menuItem, popup.firstChild);
49 |
50 | window.removeEventListener("aftercustomization", this, false);
51 | this._newLocation(gBrowser.currentURI);
52 | },
53 |
54 | _updateMenu: function() {
55 | if (!this._menuItem)
56 | return false;
57 |
58 | var count = this._currentResults ? this._currentResults.length : 0;
59 |
60 | this._menuItem.setAttribute("label", (count + " script(s) available"));
61 | this._menuItem.setAttribute("disabled", count == 0);
62 |
63 | if (this._toolbutton) {
64 | if (count > 0){
65 | this._toolbutton.classList.add("tbb-scripts-available");
66 | var _prefs = Services.prefs.getBranch("extensions.greasefire2.");
67 | if(_prefs.getCharPref('notification_sound_path') != "")
68 | new Audio(_prefs.getCharPref('notification_sound_path')).play();
69 | }else
70 | this._toolbutton.classList.remove("tbb-scripts-available");
71 | }
72 | },
73 |
74 | openResults: function() {
75 | if (!this._currentResults || !this._currentResults.length)
76 | return false;
77 |
78 | var params = {
79 | results: this._currentResults,
80 | currentURI: this._currentURI
81 | };
82 |
83 | openDialog("chrome://greasefire2/content/picker.xul",
84 | "",
85 | "chrome,dialog=no,resizable",
86 | params);
87 | },
88 |
89 | handleEvent: function(aEvent) {
90 | switch (aEvent.type) {
91 | case "load":
92 | window.addEventListener("aftercustomization", this, false);
93 | gBrowser.addProgressListener(this);
94 | CustomizableUI.addListener(this);
95 | // no break
96 | case "aftercustomization":
97 | this._setupMenu();
98 | break;
99 | }
100 | },
101 |
102 | onWidgetAfterDOMChange: function(aNode) {
103 | switch(aNode.id) {
104 | case "greasemonkey-tbb":
105 | case "scriptish-button":
106 | this._setupMenu();
107 | break;
108 | }
109 | },
110 |
111 | // nsIWebProgress
112 | onLocationChange: function(aProgress, aRequest, aURI) {
113 | this._newLocation(aURI);
114 | }
115 | }
116 |
117 | GreasefireController.init();
118 |
--------------------------------------------------------------------------------
/firefox/chrome/content/browser.xul:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
15 |
16 |
--------------------------------------------------------------------------------
/firefox/chrome/content/closewindow.xul:
--------------------------------------------------------------------------------
1 |
2 |
4 | %browserDTD;
5 | ]>
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/firefox/chrome/content/picker.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | .pickerlist > treechildren::-moz-tree-progressmeter {
6 | border: 1px solid #999999;
7 | margin: 6px 0px 6px 0px;
8 | background-color: transparent;
9 | color: #5ece10;
10 | }
11 |
12 | .pickerlist-ff4 > treechildren::-moz-tree-progressmeter {
13 | color: #5ece10;
14 | }
15 |
16 | .throbber {
17 | width: 16px;
18 | height: 16px;
19 | }
20 |
21 | .throbber-throb {
22 | list-style-image: url("chrome://global/skin/icons/loading_16.png");
23 | }
24 |
--------------------------------------------------------------------------------
/firefox/chrome/content/picker.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
6 | Cu.import("resource://gre/modules/XPCOMUtils.jsm");
7 | Cu.import("resource://gre/modules/Services.jsm");
8 |
9 | function GF_Trim(s) {
10 | return s.replace(/^\s\s*/, "").replace(/\s\s*$/, "");
11 | }
12 |
13 | const US_BASE = Cc["@b0nk3rz.net/greasefire2/updater;1"].getService().wrappedJSObject._prefs.getCharPref("us_mirror");
14 |
15 | function $(id) {
16 | return document.getElementById(id);
17 | }
18 |
19 | function getWebProgress(aIframe) {
20 | var wp = aIframe.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
21 | .getInterface(Ci.nsIWebProgress);
22 | return wp;
23 | }
24 |
25 | var PickerController = {
26 |
27 | _list: null,
28 | _info: null,
29 | _source: null,
30 | _tabpanels: null,
31 | _scriptInfoLoaded: false,
32 | _scriptSourceLoaded: false,
33 | _busyCount: 0,
34 |
35 | init: function PickerController_init() {
36 |
37 | var params = window.arguments[0];
38 | this._results = params.results;
39 | var uri = params.currentURI;
40 |
41 | document.title = "Scripts for \"" + uri.spec + "\"";
42 |
43 | this._install = $("install");
44 |
45 | this._list = $("list");
46 | this._list.classList.add("pickerlist-ff4");
47 | this._view = new ResultsView(this._results);
48 | this._list.view = this._view;
49 | this._list.addEventListener("select", this, false);
50 |
51 | var flags = Ci.nsIWebProgress.NOTIFY_STATE_REQUEST;
52 |
53 | this._info = $("info");
54 | this._info.addEventListener("click", this, false);
55 | var wp = getWebProgress(this._info);
56 | wp.addProgressListener(this, flags);
57 |
58 | this._source = $("source");
59 | wp = getWebProgress(this._source);
60 | wp.addProgressListener(this, flags);
61 |
62 | this._tabpanels = $("tabpanels");
63 | this._tabpanels.addEventListener("select", this, false);
64 |
65 | if (this._results.length > 0) {
66 | this._list.view.selection.select(0);
67 | }
68 | },
69 |
70 | _installScript: function(aURL) {
71 | var win = Services.wm.getMostRecentWindow("navigator:browser");
72 |
73 | // If we don't have a recent window, open a new one
74 | if (!win) {
75 | window.open(aURL);
76 | return;
77 | }
78 |
79 | var uri = Services.io.newURI(aURL, null, null);
80 |
81 | if (win.GM_BrowserUI) // for GM
82 | win.GM_BrowserUI.startInstallScript(uri, false);
83 | else if (win.Scriptish_installUri) // for Scriptish
84 | win.Scriptish_installUri(uri, win);
85 | },
86 |
87 | installSelectedScript: function () {
88 | var index = this._list.view.selection.currentIndex;
89 | var info = this._view.getInfo(index);
90 |
91 | var uriSpec = US_BASE + "source/" + info.scriptId + ".user.js";
92 | this._installScript(uriSpec);
93 | },
94 |
95 | updateFilter: function() {
96 | var filter = $("filter").value;
97 | var a = GF_Trim(filter).split(" ");
98 | this._view.setFilter(a);
99 | },
100 |
101 | handleEvent: function (aEvent) {
102 | // This select event is for either the result list or tab panel.
103 | if (aEvent.type == "select") {
104 | // If the list selection changed, clear the load flags.
105 | if (aEvent.target.id == "list") {
106 | this._scriptInfoLoaded = false;
107 | this._scriptSourceLoaded = false;
108 | }
109 | var index = this._list.view.selection.currentIndex;
110 | var info = this._view.getInfo(index);
111 | this._scriptSelected(info);
112 | return true;
113 | }
114 |
115 | if (aEvent.type == "click") {
116 | var target = aEvent.target;
117 | if ((target instanceof HTMLAnchorElement ||
118 | target instanceof HTMLAreaElement ||
119 | target instanceof HTMLLinkElement) &&
120 | target.hasAttribute("href")) {
121 | aEvent.preventDefault();
122 | var href = target.getAttribute("href");
123 |
124 | if (target.className == "userjs") {
125 | this._installScript(href);
126 | return false;
127 | }
128 |
129 | // HACK: remove the greasefire subdomain from the URL so
130 | // clicked links go back to http://userscripts.org
131 | var currentUrl = $("url").value;
132 | currentUrl = currentUrl.replace("http://greasefire.", "http://");
133 |
134 | var url = Services.io.newURI(currentUrl, null, null);
135 | var absolute = url.resolve(href);
136 |
137 | // Append source=greasefire2 so we can track clicks back to the
138 | // main site.
139 | absolute += absolute.indexOf("?") == -1 ? "?" : "&";
140 | absolute += "source=greasefire";
141 | openURL(absolute);
142 | return false;
143 | }
144 | }
145 |
146 | },
147 |
148 | _scriptSelected: function (aInfo) {
149 | this._install.label = "Install \"" + aInfo.name + "\"";
150 |
151 | if (this._tabpanels.selectedPanel.id == "info_panel") {
152 | this._loadInfo(aInfo);
153 | } else {
154 | this._loadSource(aInfo);
155 | }
156 | },
157 |
158 | _loadInfo: function (aInfo) {
159 | var uri = US_BASE + "show/" + aInfo.scriptId;
160 | $("url").value = uri;
161 | if (this._scriptInfoLoaded) {
162 | return;
163 | }
164 | this._info.webNavigation.loadURI(uri,
165 | Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
166 | null,
167 | null,
168 | null);
169 | this._scriptInfoLoaded = true;
170 | },
171 |
172 | _loadSource: function(aInfo) {
173 | var uri = US_BASE + "review/" + aInfo.scriptId + ".txt";
174 | $("url").value = uri;
175 | if (this._scriptSourceLoaded) {
176 | return;
177 | }
178 | this._source.webNavigation.loadURI(
179 | uri,
180 | Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
181 | null,
182 | null,
183 | null);
184 | this._scriptSourceLoaded = true;
185 | },
186 |
187 | // nsIWebProgressListener
188 | onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) {
189 |
190 | if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
191 | this._busyCount++;
192 | }
193 |
194 | if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
195 | this._busyCount--;
196 | }
197 |
198 | $("throbber").className = this._busyCount ? "throbber-throb" : "throbber";
199 | },
200 |
201 | QueryInterface: XPCOMUtils.generateQI([
202 | Ci.nsISupports, Ci.nsIDOMEventListener, Ci.nsIWebProgressListener,
203 | Ci.nsISupportsWeakReference])
204 |
205 | }
206 |
207 | function ResultsView(aResults) {
208 |
209 | this._a = aResults;
210 | this._view = [];
211 | for (var len = aResults.length, i = 0; i < len; i++) {
212 | this._view.push(i);
213 | }
214 | this._sort();
215 | }
216 |
217 | ResultsView.prototype = {
218 | _treebox: null,
219 | _selection: null,
220 | _currentSort: "scriptrank",
221 | _sorts: {
222 | scriptname: true,
223 | scriptrank: false
224 | },
225 | getInfo: function (row) {
226 | return this._a[this._view[row]];
227 | },
228 | get rowCount() {
229 | return this._view.length;
230 | },
231 | getCellText: function (row, column) {
232 | var result = this._a[this._view[row]];
233 | switch(column.id) {
234 | case "scriptname": return result.name;
235 | case "scriptmatch": return result.match;
236 | case "scriptinstalls": return result.installs;
237 | case "scriptupdated":
238 | return (new Date(result.updated)).toLocaleDateString();
239 | case "scriptrank": return result.rank;
240 | }
241 | },
242 | getCellValue: function (row, column) {
243 | return this._a[this._view[row]].rank * 100;
244 | },
245 | getProgressMode: function (row, column) {
246 | return Ci.nsITreeView.PROGRESS_NORMAL;
247 | },
248 | cycleHeader: function (column) {
249 | var dir = this._sorts[column.id];
250 | this._sorts[column.id] = !dir;
251 | this._currentSort = column.id;
252 | this._sort();
253 | this._treebox.invalidate();
254 | },
255 | setFilter: function (filter) {
256 | var oldLength = this._view.length;
257 | this._view = [];
258 | if (filter == "") {
259 | for (var i = 0; i < this._a.length; i++) {
260 | this._view.push(i);
261 | }
262 | }
263 | else {
264 | this._a.forEach(function (e, idx) {
265 | for (var i = 0; i < filter.length; i++) {
266 | if (e.name.toLowerCase().indexOf(filter[i].toLowerCase()) < 0) {
267 | return;
268 | }
269 | }
270 | this._view.push(idx);
271 | }, this);
272 | }
273 |
274 | this._treebox.beginUpdateBatch();
275 | try {
276 | this._treebox.rowCountChanged(0, this._view.length - oldLength);
277 | this._sort();
278 | this._selection.select(0);
279 | }
280 | finally {
281 | this._treebox.endUpdateBatch();
282 | }
283 | },
284 | _sort: function () {
285 |
286 | var colId = this._currentSort;
287 | var direction = this._sorts[colId];
288 |
289 | var _a = this._a;
290 | var cmp = function (aidx, bidx) {
291 |
292 | function getValue(o) {
293 | switch(colId) {
294 | case "scriptname": return o.name.toLowerCase();
295 | case "scriptmatch": return o.match;
296 | case "scriptinstalls": return o.installs;
297 | case "scriptupdated": return o.updated;
298 | case "scriptrank": return o.rank;
299 | }
300 | }
301 |
302 | var a = _a[aidx];
303 | var b = _a[bidx];
304 | if (getValue(a) < getValue(b)) {
305 | return direction ? -1 : 1;
306 | }
307 | if (getValue(a) > getValue(b)) {
308 | return direction ? 1 : -1;
309 | }
310 | return 0;
311 | }
312 |
313 | this._view.sort(cmp);
314 | },
315 | get selection() {
316 | return this._selection;
317 | },
318 | set selection(selection) {
319 | this._selection = selection;
320 | },
321 | setTree: function (treebox) { this._treebox = treebox; },
322 | isContainer: function (row) { return false; },
323 | isSeparator: function (row) { return false; },
324 | isSorted: function () { return false; },
325 | getLevel: function (row) { return 0; },
326 | getImageSrc: function (row, col) { return null; },
327 | };
328 |
--------------------------------------------------------------------------------
/firefox/chrome/content/picker.xul:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
17 |
21 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
39 |
40 |
41 |
42 |
48 |
49 |
56 |
57 |
63 |
64 |
70 |
71 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/firefox/chrome/content/prefs.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | .throbber {
6 | -moz-margin-start: 5px;
7 | width: 16px;
8 | height: 16px;
9 | list-style-image: url("chrome://global/skin/icons/loading_16.png");
10 | }
11 |
--------------------------------------------------------------------------------
/firefox/chrome/content/prefs.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
6 | Cu.import("resource://gre/modules/XPCOMUtils.jsm");
7 |
8 | function $(id) {
9 | return document.getElementById(id);
10 | }
11 |
12 | var PrefsController = {
13 |
14 | _gfs: Cc["@b0nk3rz.net/greasefire2/service;1"].getService().wrappedJSObject,
15 | _up: Cc["@b0nk3rz.net/greasefire2/updater;1"].getService().wrappedJSObject,
16 | filePicker: Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker),
17 |
18 | init: function PrefsController_init() {
19 | //$("days").value = this._up.updateIntervalMinutes / 1440; // (1440 = 24 * 60)
20 | $("us_mirror").value = this._up._prefs.getCharPref("us_mirror");
21 | $("notificationSound").value = this._up._prefs.getCharPref("notification_sound_path");
22 | $("useNotification").checked = (this._up._prefs.getCharPref("notification_sound_path") != "");
23 | if(this._up._prefs.getCharPref("notification_sound_path") == "") $('nsBrowser').setAttribute('disabled','true');
24 | //this._up.addListener(this);
25 | this._updateDisplay();
26 | },
27 |
28 | unload: function () {
29 | this._up.removeListener(this);
30 | },
31 |
32 | update: function() {
33 | if (this._up.isUpdating) {
34 | this._up.cancelUpdate();
35 | }
36 | else {
37 | this._up.startUpdate(false);
38 | }
39 | },
40 |
41 | updateInterval: function (aDays) {
42 | var d = parseInt(aDays);
43 | if (!isNaN(d) && d >= 0) {
44 | this._up.updateIntervalMinutes = d * 1440; // (1440 = 24 * 60)
45 | }
46 | this._updateDisplay();
47 | },
48 |
49 | updateCheckbox: function (aChecked) {
50 | if (aChecked) {
51 | var d = $("days").value;
52 | if (d == 0) {
53 | d = 1;
54 | $("days").value = 1;
55 | }
56 | this.updateInterval(d);
57 | }
58 | else {
59 | this._up.updateIntervalMinutes = 0;
60 | }
61 | this._updateDisplay();
62 | },
63 |
64 | updateMirror: function (aMirror) {
65 | this._up._prefs.setCharPref("us_mirror", aMirror);
66 | },
67 |
68 | updateNotificationSoundCheckbox: function (aChecked){
69 | if(!aChecked){
70 | $('nsBrowser').setAttribute('disabled', 'true');
71 | $('notificationSound').value="";
72 | this._up._prefs.setCharPref('notification_sound_path', "");
73 | }else
74 | $('nsBrowser').removeAttribute('disabled');
75 | },
76 |
77 | updateNotificationSound: function (filePath){
78 | this._up._prefs.setCharPref('notification_sound_path', filePath);
79 | },
80 |
81 | getSoundFileBrowser: function (){
82 | var window = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser");
83 | this.filePicker.init(window, "Select notification sound file..", Ci.nsIFilePicker.modeOpen);
84 | this.filePicker.appendFilters(Ci.nsIFilePicker.filterAudio); //filterAudio
85 | return this.filePicker;
86 | },
87 |
88 | onUpdateStarted: function () {
89 | $("status").value = "Connecting...";
90 | this._updateDisplay();
91 | },
92 |
93 | onUpdateFinished: function (aStatus, aMessage) {
94 |
95 | if (aStatus == Cr.NS_OK) {
96 | $("status").value = "Update complete!";
97 | }
98 | else if (aStatus == Cr.NS_BINDING_ABORTED) {
99 | $("status").value = "Update cancelled";
100 | $("progress").value = 0;
101 | }
102 | else if (aStatus == Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
103 | $("status").value = "Already up to date.";
104 | $("progress").value = 0;
105 | }
106 | else {
107 | $("status").value = "Error updating: " + aMessage;
108 | }
109 |
110 | this._updateDisplay();
111 | },
112 |
113 | onDownloadProgress: function (aCurrentBytes, aTotalBytes) {
114 | $("progress").value = (aCurrentBytes / aTotalBytes) * 100;
115 |
116 | if (aCurrentBytes == aTotalBytes) {
117 | $("status").value = "Extracting new index...";
118 | }
119 | else {
120 | $("status").value = "Downloading " + aCurrentBytes + " of " + aTotalBytes + " bytes";
121 | }
122 | },
123 |
124 | _updateDisplay: function() (this._gfs.getIndexDate((function(aDate) {
125 | $("index-date").value = (new Date(aDate)).toLocaleString();
126 | $("script-count").value = this._gfs.scriptCount;
127 |
128 | if (this._up.updateIntervalMinutes > 0) {
129 | $("next-update").value = (new Date(this._up.nextUpdateDate)).toLocaleString();
130 | $("auto").checked = true;
131 | }
132 | else {
133 | $("next-update").value = "n/a";
134 | $("auto").checked = false;
135 | }
136 |
137 | if (this._up.isUpdating) {
138 | $("update-button").label = "Cancel update";
139 | $("progress-box").hidden = false;
140 | $("throbber").hidden = false;
141 | }
142 | else {
143 | $("update-button").label = "Update now";
144 | $("throbber").hidden = true;
145 | }
146 | }).bind(this))),
147 |
148 | QueryInterface: XPCOMUtils.generateQI([
149 | Ci.nsISupports, Ci.nsIDOMEventListener])
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/firefox/chrome/content/prefs.xul:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
92 |
--------------------------------------------------------------------------------
/firefox/chrome/content/test/test.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
6 |
7 | Cu.import("resource://gre/modules/Services.jsm");
8 |
9 | var bis;
10 | var seekable;
11 | var cache = [];
12 |
13 | function runTest() {
14 |
15 | var method = 2;
16 |
17 | var urls = [
18 | "http://reddit.com/",
19 | "http://slashdot.org/",
20 | "http://nytimes.com/",
21 | "http://www.cnn.com/blah",
22 | "http://google.com",
23 | "http://www.google.com",
24 | "http://myspace.com",
25 | "http://facebook.com"
26 | ];
27 | var o = {};
28 |
29 | var t = Date.now();
30 |
31 | if (method == 1 || method == 2) {
32 | var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
33 | file.initWithPath("/home/steve/dev/greasefire2/index.dat");
34 |
35 | var fis = Cc["@mozilla.org/network/file-input-stream;1"]
36 | .createInstance(Ci.nsIFileInputStream);
37 | fis.init(file, -1, 0, 0);
38 | var buffer = Cc["@mozilla.org/network/buffered-input-stream;1"]
39 | .createInstance(Ci.nsIBufferedInputStream);
40 | buffer.init(fis, 4096);
41 |
42 | bis = Cc["@mozilla.org/binaryinputstream;1"]
43 | .createInstance(Ci.nsIBinaryInputStream);
44 | bis.setInputStream(buffer);
45 |
46 | // var junk = [];
47 | // bis.readByteArray(file.fileSize, junk, {});
48 |
49 | seekable = buffer.QueryInterface(Ci.nsISeekableStream);
50 | }
51 | else {
52 | Services.scriptloader
53 | .loadSubScript("file:///home/steve/dev/greasefire2/index.json", o);
54 | }
55 |
56 | var d = Date.now() - t;
57 | log("startup " + d + "ms");
58 |
59 | for (var i = 0; i < urls.length; i++) {
60 | var matches = [];
61 | var t = Date.now();
62 | switch (method) {
63 | case 1: find1(urls[i], 0, 0, matches); break
64 | case 2: find2(urls[i], 0, 0, matches); break;
65 | case 3: find3(o.data, urls[i], 0, matches); break;
66 |
67 | }
68 | var d = Date.now() - t;
69 |
70 | var m = {};
71 | var count = 0;
72 | for (var j = 0; j < matches.length; j++) {
73 | if (!(matches[j] in m)) {
74 | count++;
75 | m[matches[j]] = 1;
76 | }
77 | }
78 |
79 | log("--> " + urls[i] + " matches " + count + " " + d + "ms");
80 | }
81 |
82 | return true;
83 | }
84 |
85 | function find1(url, indexPos, stringPos, matches) {
86 |
87 | seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, indexPos);
88 |
89 | var idsLength = bis.read64();
90 | for (var i = 0; i < idsLength; i++) {
91 | matches.push(bis.read64());
92 | }
93 |
94 | if (stringPos > url.length - 1) {
95 | return;
96 | }
97 |
98 | var childrenLength = bis.read16();
99 | for (var i = 0; i < childrenLength; i++) {
100 | var c = String.fromCharCode(bis.read16());
101 | var pos = bis.read64();
102 | if (c == "*") {
103 | for (var j = stringPos; j < url.length; j++) {
104 | var tell = seekable.tell();
105 | find1(url, pos, j, matches);
106 | seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, tell);
107 | }
108 | }
109 | else if (url.charAt(stringPos) == c) {
110 | var tell = seekable.tell();
111 | find1(url, pos, stringPos + 1, matches);
112 | seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, tell);
113 | }
114 | }
115 | }
116 |
117 | function find2(url, indexPos, stringPos, matches) {
118 |
119 | var o = cache[indexPos];
120 | if (!o) {
121 | o = {};
122 | cache[indexPos] = o;
123 |
124 | seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, indexPos);
125 |
126 | var idsLength = bis.read64();
127 | if (idsLength > 0) {
128 | var ids = [];
129 | for (var i = 0; i < idsLength; i++) {
130 | ids.push(bis.read64());
131 | }
132 | o[" "] = ids;
133 | }
134 |
135 | var childrenLength = bis.read16();
136 | for (var i = 0; i < childrenLength; i++) {
137 | var c = String.fromCharCode(bis.read16());
138 | var pos = bis.read64();
139 | o[c] = pos;
140 | }
141 | }
142 |
143 | var ids = o[" "];
144 | if (ids) {
145 | for (var i = 0; i < ids.length; i++) {
146 | matches.push(ids[i]);
147 | }
148 | }
149 |
150 | if (stringPos > url.length - 1) {
151 | return;
152 | }
153 |
154 | var nextPos = o[url.charAt(stringPos)];
155 | if (nextPos) {
156 | find2(url, nextPos, stringPos + 1, matches);
157 | }
158 |
159 | var wildPos = o["*"];
160 | if (wildPos) {
161 | for (var i = 0; i < url.length; i++) {
162 | find2(url, wildPos, i, matches);
163 | }
164 | }
165 |
166 | }
167 |
168 | function find3(data, url, stringPos, matches) {
169 |
170 | var ids = data[" "];
171 | if (ids) {
172 | for (var i = 0; i < ids.length; i++) {
173 | matches.push(ids[i]);
174 | }
175 | }
176 |
177 | if (stringPos > url.length - 1) {
178 | return;
179 | }
180 |
181 | var next = data[url.charAt(stringPos)];
182 | if (next) {
183 | find3(next, url, stringPos + 1, matches);
184 | }
185 |
186 | var wild = data["*"];
187 | if (wild) {
188 | for (var i = 0; i < url.length; i++) {
189 | find3(wild, url, i, matches);
190 | }
191 | }
192 |
193 | }
194 |
--------------------------------------------------------------------------------
/firefox/chrome/content/test/test_autoupdate.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
6 |
7 | Cu.import("resource://gre/modules/Services.jsm");
8 |
9 | function runTest() {
10 | var mainThread = Services.tm.mainThread;
11 |
12 | var gfs = Cc["@b0nk3rz.net/greasefire2/service;1"]
13 | .getService(Ci.gfIGreasefireService);
14 |
15 | var u = Cc["@b0nk3rz.net/greasefire2/updater;1"]
16 | .getService(Ci.gfIUpdaterService);
17 |
18 | u.updateIntervalMinutes = 2;
19 |
20 | log("index date: " + (new Date(gfs.indexDate)));
21 | log("next update date: " + (new Date(u.nextUpdateDate)));
22 | log("update interval: " + u.updateIntervalMinutes);
23 |
24 | var done = false;
25 |
26 | u.addListener({
27 | onUpdateStarted: function() {
28 | log("onUpdateStarted");
29 | },
30 | onUpdateFinished: function(aStatus, aMessage) {
31 | log("onUpdateFinished " + aStatus.toString(16) + " " + aMessage);
32 | done = true;
33 | },
34 | onDownloadProgress: function(aCurrentBytes, aTotalBytes) {
35 | //log("onDownloadProgress " + aCurrentBytes + " " + aTotalBytes);
36 | }
37 | });
38 |
39 | for (var i = 0; i < 3; i++) {
40 | done = false;
41 | while (!done) {
42 | mainThread.processNextEvent(true);
43 | }
44 |
45 | log("index date: " + (new Date(gfs.indexDate)));
46 | log("next update date: " + (new Date(u.nextUpdateDate)));
47 | log("update interval: " + u.updateIntervalMinutes);
48 | }
49 |
50 | return true;
51 | }
52 |
--------------------------------------------------------------------------------
/firefox/chrome/content/test/test_picker.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
6 |
7 | Cu.import("resource://gre/modules/Services.jsm");
8 |
9 | function runTest() {
10 |
11 | var gfs = Cc["@b0nk3rz.net/greasefire2/service;1"]
12 | .getService(Ci.gfIGreasefireService);
13 |
14 | var uri = Services.io.newURI("http://www.google.com", null, null);
15 | var results = gfs.search(uri);
16 |
17 | var params = Cc["@mozilla.org/embedcomp/dialogparam;1"]
18 | .createInstance(Ci.nsIDialogParamBlock);
19 | var array = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
20 | array.appendElement(results, false);
21 | array.appendElement(uri, false);
22 | params.objects = array;
23 |
24 | Services.ww.openWindow(null,
25 | "chrome://greasefire2/content/picker.xul",
26 | "_blank",
27 | "chrome,all,dialog,modal,dialog=no",
28 | params);
29 |
30 | return true;
31 | }
32 |
--------------------------------------------------------------------------------
/firefox/chrome/content/test/test_prefs.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
6 |
7 | Cu.import("resource://gre/modules/Services.jsm");
8 |
9 | function runTest() {
10 | Services.ww.openWindow(null,
11 | "chrome://greasefire2/content/prefs.xul",
12 | "_blank",
13 | "chrome,all,dialog,modal,centerscreen",
14 | null);
15 |
16 | return true;
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/firefox/chrome/content/test/test_results.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
6 |
7 | Cu.import("resource://gre/modules/Services.jsm");
8 |
9 | function runTest() {
10 |
11 | var gfs = Cc["@b0nk3rz.net/greasefire2/service;1"]
12 | .getService(Ci.gfIGreasefireService);
13 |
14 | var results = gfs.search(
15 | Services.io.newURI("http://www.google.com", null, null));
16 |
17 | var params = Cc["@mozilla.org/embedcomp/dialogparam;1"]
18 | .createInstance(Ci.nsIDialogParamBlock);
19 | var array = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
20 | array.appendElement(results, false);
21 | params.objects = array;
22 |
23 | Services.ww.openWindow(null,
24 | "chrome://greasefire2/content/results.xul",
25 | "_blank",
26 | "chrome,all,dialog=no",
27 | params);
28 |
29 | return true;
30 | }
31 |
--------------------------------------------------------------------------------
/firefox/chrome/content/test/test_service.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
6 |
7 | Cu.import("resource://gre/modules/Services.jsm");
8 |
9 | function runTest() {
10 |
11 | var urls = [
12 | /*
13 | "http://reddit.com/",
14 | "http://slashdot.org/",
15 | "http://nytimes.com/",
16 | "http://www.cnn.com/blah",
17 | "http://google.com",
18 | "http://www.google.com",
19 | "http://myspace.com",
20 | "http://facebook.com"
21 | */
22 | "http://www.mozilla.org"
23 | ];
24 |
25 | var gfs = Cc["@b0nk3rz.net/greasefire2/service;1"]
26 | .getService(Ci.gfIGreasefireService);
27 |
28 | for (var i = 0; i < urls.length; i++) {
29 |
30 | var uri = Services.io.newURI(urls[i], null, null);
31 |
32 | var t = Date.now();
33 | var hasScripts = gfs.hasScripts(uri);
34 | var d = Date.now() - t;
35 |
36 | log("--> " + urls[i] + " hasScripts " + d + "ms");
37 |
38 | t = Date.now();
39 | var results = gfs.search(uri);
40 | d = Date.now() - t;
41 |
42 | log("--> " + urls[i] + " matches " + results.length + " " + d + "ms");
43 |
44 | for (var j = 0; j < results.length; j++) {
45 | var r = results.queryElementAt(j, Ci.gfISearchResult);
46 | log("-------> " + r.scriptId + " " + r.match + " " + r.rank);
47 | }
48 |
49 | }
50 |
51 | return true;
52 | }
53 |
--------------------------------------------------------------------------------
/firefox/chrome/content/test/test_updater.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
6 |
7 | Cu.import("resource://gre/modules/Services.jsm");
8 |
9 | function runTest() {
10 | var mainThread = Services.tm.mainThread;
11 |
12 | var gfs = Cc["@b0nk3rz.net/greasefire2/service;1"]
13 | .getService(Ci.gfIGreasefireService);
14 |
15 | var u = Cc["@b0nk3rz.net/greasefire2/updater;1"]
16 | .getService(Ci.gfIUpdaterService);
17 |
18 | log("index date" + (new Date(gfs.indexDate)));
19 |
20 | var done = false;
21 | var doCancel = false;
22 |
23 | u.addListener({
24 | onUpdateStarted: function() {
25 | log("onUpdateStarted");
26 | if (doCancel) {
27 | log("cancelling");
28 | u.cancelUpdate();
29 | }
30 | },
31 | onUpdateFinished: function(aStatus, aMessage) {
32 | log("onUpdateFinished " + aStatus.toString(16) + " " + aMessage);
33 | done = true;
34 | },
35 | onDownloadProgress: function(aCurrentBytes, aTotalBytes) {
36 | //log("onDownloadProgress " + aCurrentBytes + " " + aTotalBytes);
37 | }
38 | });
39 |
40 | u.startUpdate(true);
41 | while (!done) {
42 | mainThread.processNextEvent(true);
43 | }
44 |
45 | log("index date" + (new Date(gfs.indexDate)));
46 |
47 | done = false;
48 | u.startUpdate(false);
49 | while (!done) {
50 | mainThread.processNextEvent(true);
51 | }
52 |
53 | log("index date" + (new Date(gfs.indexDate)));
54 |
55 | /*
56 | doCancel = true;
57 |
58 | done = false;
59 | u.startUpdate(true);
60 | while (!done) {
61 | mainThread.processNextEvent(true);
62 | }
63 |
64 | log("index date" + (new Date(gfs.indexDate)));
65 | */
66 | return true;
67 | }
68 |
--------------------------------------------------------------------------------
/firefox/chrome/content/test/test_userscriptinfo.js:
--------------------------------------------------------------------------------
1 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
2 |
3 | Cu.import("resource://gre/modules/Services.jsm");
4 |
5 | function runTest() {
6 |
7 | var usis = Cc["@b0nk3rz.net/greasefire2/userscript-info-service;1"]
8 | .getService(Ci.gfIUserScriptInfoService);
9 |
10 | var obs = {
11 | observe: function(subject, topic, data) {
12 | var info = subject.QueryInterface(Ci.gfIUserScriptInfo);
13 | log("id " + info.scriptId);
14 | log("name " + info.name);
15 | log("description " + info.description);
16 | }
17 | }
18 |
19 | usis.request(13269, obs);
20 | usis.request(24556, obs);
21 |
22 | Services.ww.openWindow(null,
23 | "chrome://greasefire2/content/results.xul",
24 | "_blank",
25 | "chrome,all,dialog=no",
26 | null);
27 | }
28 |
--------------------------------------------------------------------------------
/firefox/components/gfGreasefireService.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
6 |
7 | Cu.import("resource://gre/modules/XPCOMUtils.jsm");
8 | Cu.import("resource://gre/modules/Services.jsm");
9 | Cu.import("resource://gre/modules/AddonManager.jsm");
10 |
11 | const DEBUG = false;
12 |
13 | const NS_PROFILE_STARTUP_OBSERVER_ID = "profile-after-change";
14 | const NS_PROFILE_SHUTDOWN_OBSERVER_ID = "profile-before-change";
15 |
16 | const JARFILES = ["include.dat", "exclude.dat", "scripts.db", "info.ini"];
17 |
18 | var indexesDir = null;
19 | function GF_GetIndexesDir(aCallback) {
20 | var installLocation = null;
21 | if (indexesDir) {
22 | return aCallback(indexesDir.clone());
23 | }
24 |
25 | var addonID = "greasefire2@b0nk3rz.net";
26 | var file = Services.dirsvc.get("ProfD", Ci.nsIFile);
27 | file.append(addonID);
28 | var profDir = file.clone();
29 | file.append("indexes");
30 | indexesDir = file;
31 |
32 | // if the profile directory DNE then create it
33 | if (!file.exists()) {
34 | AddonManager.getAddonByID(addonID, function(aAddon) {
35 | Cu.import("resource://gre/modules/NetUtil.jsm");
36 | Cu.import("resource://gre/modules/FileUtils.jsm");
37 |
38 | var xpi = aAddon.getResourceURI("").QueryInterface(Ci.nsIFileURL).file;
39 | try {
40 | var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
41 | .createInstance(Ci.nsIZipReader);
42 | zipReader.open(xpi);
43 | indexesDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0755);
44 | JARFILES.forEach(function(e) {
45 | var f = indexesDir.clone();
46 | f.append(e);
47 | zipReader.extract("indexes/" + e, f);
48 | });
49 | zipReader.close();
50 | } catch (e) {
51 | var indexes = xpi.clone();
52 | indexes.append("indexes");
53 | indexes.copyTo(profDir, "indexes");
54 | }
55 |
56 | aCallback(indexesDir.clone());
57 | });
58 |
59 | return;
60 | }
61 |
62 | aCallback(indexesDir.clone());
63 | }
64 |
65 | function d(s) {
66 | if (DEBUG) {
67 | dump("gfGreasefireService: " + s + "\n");
68 | }
69 | }
70 |
71 | function gfGreasefireService()
72 | {
73 | d("ctor");
74 |
75 | this.wrappedJSObject = this;
76 | this._started = false;
77 | this._includes = null;
78 | this._excludes = null;
79 | this._conn = null;
80 |
81 | this._scriptCount = null;
82 | this._indexDate = Date.now();
83 |
84 | Services.obs.addObserver(this, NS_PROFILE_SHUTDOWN_OBSERVER_ID, false);
85 | }
86 |
87 | gfGreasefireService.prototype = {
88 | classDescription: "Greasefire Service",
89 | classID: Components.ID("{d647ff9b-ac4c-4d0e-8fbd-484765be5549}"),
90 | contractID: "@b0nk3rz.net/greasefire2/service;1"
91 | }
92 |
93 | gfGreasefireService.prototype.startup =
94 | function gfGreasefirbeService_startup()
95 | {
96 | d("startup");
97 |
98 | if (this._started) {
99 | return;
100 | }
101 |
102 | var self = this;
103 | this._scriptCount = null;
104 | this._indexDate = null;
105 |
106 | GF_GetIndexesDir(function(dir) {
107 | var file = dir.clone() ;
108 | file.append("include.dat");
109 | self._includes = new gfIndexReader(file);
110 |
111 | file = dir.clone();
112 | file.append("exclude.dat");
113 | self._excludes = new gfIndexReader(file);
114 |
115 | file = dir.clone();
116 | file.append("scripts.db");
117 | self._conn = Services.storage.openDatabase(file);
118 |
119 | self._started = true;
120 | });
121 |
122 | }
123 |
124 | gfGreasefireService.prototype.shutdown =
125 | function gfGreasefireService_shutdown()
126 | {
127 | d("shutdown");
128 |
129 | if (!this._started) {
130 | return;
131 | }
132 |
133 | if (this._includes) {
134 | this._includes.close();
135 | }
136 |
137 | if (this._excludes) {
138 | this._excludes.close();
139 | }
140 |
141 | // Only mozilla 1.9 has a close method
142 | if (this._conn && this._conn.close) {
143 | this._conn.close();
144 | }
145 |
146 | this._started = false;
147 | }
148 |
149 | gfGreasefireService.prototype.hasScripts =
150 | function gfGreasefireService_hasScripts(aURL)
151 | {
152 | if (!this._includes || !this._excludes) {
153 | return false;
154 | }
155 |
156 | var urlSpec = this._fixUrl(aURL);
157 |
158 | var excludes = {};
159 | this._excludes.search(urlSpec, excludes, false);
160 |
161 | var matches = {};
162 | this._includes.search(urlSpec, matches, true, excludes);
163 |
164 | for (var id in matches) {
165 | return true;
166 | }
167 |
168 | return false;
169 | }
170 |
171 | gfGreasefireService.prototype.search =
172 | function gfGreasefireService_search(aURL)
173 | {
174 | var result = [];
175 | if (!this._includes || !this._excludes) {
176 | return result;
177 | }
178 |
179 | var urlSpec = this._fixUrl(aURL);
180 |
181 | var excludes = {};
182 | var t = Date.now();
183 | this._excludes.search(urlSpec, excludes, false);
184 | var excludesMark = Date.now();
185 |
186 | var matches = {};
187 | this._includes.search(urlSpec, matches, false, excludes);
188 | var searchMark = Date.now();
189 |
190 | var infos = this._getScriptInfos(matches);
191 | var ranks = this._rankMatches(matches, infos);
192 | for (var id in matches) {
193 | if (infos[id]) {
194 | var r = new gfSearchResult(id, infos[id], matches[id], ranks[id]);
195 | result.push(r);
196 | }
197 | }
198 |
199 | d("****** Search " + aURL.spec +
200 | " matches " + result.length +
201 | " exclude " + (excludesMark - t) +
202 | " include " + (searchMark - t));
203 |
204 | return result;
205 | }
206 |
207 | gfGreasefireService.prototype.__defineGetter__("scriptCount",
208 | function gfGreasefireService_get_scriptCount()
209 | {
210 | if (!this._started) {
211 | return 0;
212 | }
213 |
214 | if (!this._scriptCount) {
215 | var sql = "select count(1) from scripts";
216 | var stmt = this._conn.createStatement(sql);
217 | stmt.executeStep();
218 | this._scriptCount = stmt.getInt32(0);
219 | stmt.finalize();
220 | }
221 |
222 | return this._scriptCount;
223 | });
224 |
225 | gfGreasefireService.prototype.getIndexDate =
226 | function gfGreasefireService_getIndexDate(aCallback)
227 | {
228 |
229 | var self = this;
230 | if (self._indexDate) {
231 | aCallback(self._indexDate);
232 | } else {
233 | self._indexDate = 0;
234 |
235 | GF_GetIndexesDir(function(dir) {
236 | var iniFile = dir.clone();
237 | iniFile.append("info.ini");
238 |
239 | if (iniFile.exists()) {
240 | try {
241 | var ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"]
242 | .getService(Ci.nsIINIParserFactory)
243 | .createINIParser(iniFile);
244 |
245 | var dateString = ini.getString("indexes", "date");
246 | self._indexDate = Date.parse(dateString);
247 | } catch (e) {
248 | Cu.reportError(e);
249 | }
250 | }
251 |
252 | aCallback(self._indexDate);
253 | });
254 | }
255 | };
256 |
257 | gfGreasefireService.prototype._fixUrl =
258 | function gfGreasefireService__fixUrl(aURL)
259 | {
260 | var urlSpec = aURL.spec;
261 |
262 | // XXX performance breaks down on really long URLs, so trim to 50 chars
263 | urlSpec = urlSpec.substring(0, 50);
264 | return urlSpec;
265 | }
266 |
267 | gfGreasefireService.prototype._getScriptInfos =
268 | function gfGreasefireService__getSctiptInfos(matches)
269 | {
270 | var ids = [];
271 | for (var id in matches) {
272 | ids.push(id);
273 | }
274 |
275 | var infos = {};
276 | var sql = "select id, name, installs, updated from scripts where id in (";
277 | sql += ids.join(",");
278 | sql += ");";
279 |
280 | var stmt = this._conn.createStatement(sql);
281 | while (stmt.executeStep()) {
282 | infos[stmt.getInt32(0)] = {
283 | name: stmt.getString(1),
284 | installs: stmt.getInt32(2),
285 | updated: stmt.getInt64(3)
286 | };
287 | }
288 | stmt.finalize();
289 | return infos;
290 | }
291 |
292 | gfGreasefireService.prototype._rankMatches =
293 | function gfGreasefireService__rankMatches(matches, infos)
294 | {
295 | var ranks = [];
296 | var updatedMin = null;
297 | var updatedMax = null;
298 | var installsMin = null;
299 | var installsMax = null;
300 | var matchMin = null;
301 | var matchMax = null;
302 |
303 |
304 | for (var id in matches) {
305 | var info = infos[id];
306 | if (!info) continue;
307 | var match = matches[id];
308 | if (updatedMin == null || info.updated < updatedMin) {
309 | updatedMin = info.updated;
310 | }
311 | if (updatedMax == null || info.updated > updatedMax) {
312 | updatedMax = info.updated;
313 | }
314 |
315 | if (installsMin == null || info.installs < installsMin) {
316 | installsMin = info.installs;
317 | }
318 | if (installsMax == null || info.installs > installsMax) {
319 | installsMax = info.installs;
320 | }
321 |
322 | if (matchMin == null || match < matchMin) {
323 | matchMin = match;
324 | }
325 | if (matchMax == null || match > matchMax) {
326 | matchMax = match;
327 | }
328 | }
329 |
330 | var updatedRange = updatedMax - updatedMin;
331 | var installsRange = installsMax - installsMin;
332 | var matchRange = matchMax - matchMin;
333 |
334 | for (var id in matches) {
335 | var info = infos[id];
336 | if (!info) continue;
337 | var matchCount = matches[id];
338 |
339 | var updated = updatedRange > 0 ?
340 | (info.updated - updatedMin) / updatedRange : 1;
341 | var installs = installsRange > 0 ?
342 | (info.installs - installsMin) / installsRange : 1;
343 | var match = matchRange > 0 ?
344 | (matchCount - matchMin) / matchRange : 1;
345 |
346 | ranks[id] = (updated * .5) + (installs * .25) + (match * .25);
347 |
348 | }
349 |
350 | return ranks;
351 | }
352 |
353 | // nsIObserver
354 |
355 | gfGreasefireService.prototype.observe =
356 | function gfGreasefireService_observe(aSubject, aTopic, aData)
357 | {
358 |
359 | if (aTopic == NS_PROFILE_STARTUP_OBSERVER_ID) {
360 | this.startup();
361 | }
362 | else if (aTopic == NS_PROFILE_SHUTDOWN_OBSERVER_ID) {
363 | this.shutdown();
364 | Services.obs.removeObserver(this, NS_PROFILE_STARTUP_OBSERVER_ID);
365 | Services.obs.removeObserver(this, NS_PROFILE_SHUTDOWN_OBSERVER_ID);
366 | }
367 | }
368 |
369 | function gfSearchResult(aScriptId, aInfo, aMatch, aRank)
370 | {
371 | this._scriptId = aScriptId;
372 | this._info = aInfo;
373 | this._match = aMatch;
374 | this._rank = aRank;
375 | }
376 |
377 | gfSearchResult.prototype = {
378 | get scriptId() {
379 | return this._scriptId;
380 | },
381 | get match() {
382 | return this._match;
383 | },
384 | get name() {
385 | return this._info.name;
386 | },
387 | get installs() {
388 | return this._info.installs;
389 | },
390 | get updated() {
391 | return this._info.updated;
392 | },
393 | get rank() {
394 | return this._rank;
395 | }
396 |
397 | }
398 |
399 | function gfIndexReader(aFile)
400 | {
401 |
402 | this._fis = Cc["@mozilla.org/network/file-input-stream;1"]
403 | .createInstance(Ci.nsIFileInputStream);
404 | this._fis.init(aFile, -1, 0, 0);
405 | var buffer = Cc["@mozilla.org/network/buffered-input-stream;1"]
406 | .createInstance(Ci.nsIBufferedInputStream);
407 | buffer.init(this._fis, 4096);
408 | this._seekable = buffer.QueryInterface(Ci.nsISeekableStream);
409 |
410 | this._bis = Cc["@mozilla.org/binaryinputstream;1"]
411 | .createInstance(Ci.nsIBinaryInputStream);
412 | this._bis.setInputStream(buffer);
413 |
414 | this._cache = [];
415 | }
416 |
417 | gfIndexReader.prototype = {
418 |
419 | close: function() {
420 | this._fis.close();
421 | },
422 |
423 | search: function(aUrl, aMatches, aFirstOnly, aExcludes) {
424 | this._search(aUrl, 0, 0, 0, aMatches, aFirstOnly, aExcludes);
425 | },
426 |
427 | _search: function(aUrl, aIndexPos, aStringPos, aMatchedCount, aMatches, aFirstOnly, aExcludes) {
428 |
429 | var o = this._cache[aIndexPos];
430 | if (!o) {
431 | o = {};
432 | this._cache[aIndexPos] = o;
433 |
434 | this._seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, aIndexPos);
435 |
436 | var idsLength = this._bis.read64();
437 | if (idsLength > 0) {
438 | var ids = [];
439 | for (var i = 0; i < idsLength; i++) {
440 | ids.push(this._bis.read64());
441 | }
442 | o["ids"] = ids;
443 | }
444 |
445 | var childrenLength = this._bis.read16();
446 | for (var i = 0; i < childrenLength; i++) {
447 | var c = String.fromCharCode(this._bis.read16());
448 | var pos = this._bis.read64();
449 | o[c] = pos;
450 | }
451 | }
452 |
453 | var ids = o["ids"];
454 | if (ids) {
455 | for (var i = 0; i < ids.length; i++) {
456 | var id = ids[i];
457 | var matchedCount = aMatches[id];
458 | if (!matchedCount || (matchedCount && aMatchedCount > matchedCount)) {
459 | if (!aExcludes || (aExcludes && !(id in aExcludes))) {
460 | aMatches[id] = aMatchedCount;
461 |
462 | if (aFirstOnly) {
463 | return false;
464 | }
465 | }
466 | }
467 | }
468 | }
469 |
470 | var wildPos = o["*"];
471 | if (wildPos) {
472 | for (var i = 0; i < aUrl.length; i++) {
473 | var cont = this._search(aUrl,
474 | wildPos,
475 | i,
476 | aMatchedCount,
477 | aMatches,
478 | aFirstOnly,
479 | aExcludes);
480 |
481 | if(!cont) {
482 | return false;
483 | }
484 |
485 | }
486 | }
487 |
488 | if (aStringPos > aUrl.length - 1) {
489 | return true;
490 | }
491 |
492 | var nextPos = o[aUrl.charAt(aStringPos)];
493 | if (nextPos) {
494 | var cont = this._search(aUrl,
495 | nextPos,
496 | aStringPos + 1,
497 | aMatchedCount + 1,
498 | aMatches,
499 | aFirstOnly,
500 | aExcludes);
501 |
502 | if(!cont) {
503 | return false;
504 | }
505 |
506 | }
507 |
508 | var tldPos = o[" "];
509 | if (tldPos) {
510 | // Consume all characters up to /
511 | var slashPos = aUrl.indexOf("/", aStringPos + 1);
512 | if (slashPos >= 0) {
513 | var cont = this._search(aUrl,
514 | tldPos,
515 | slashPos,
516 | aMatchedCount + 1,
517 | aMatches,
518 | aFirstOnly,
519 | aExcludes);
520 |
521 | if(!cont) {
522 | return false;
523 | }
524 |
525 | }
526 |
527 | }
528 |
529 | return true;
530 | }
531 | }
532 |
533 | var NSGetFactory = null;
534 |
535 | // Firefox4 support 2011/4/24 by TonyQ
536 |
537 | gfGreasefireService.prototype.QueryInterface =
538 | XPCOMUtils.generateQI([Ci.nsIObserver]);
539 |
540 | var NSGetFactory = XPCOMUtils.generateNSGetFactory([
541 | gfGreasefireService
542 | ]);
543 |
--------------------------------------------------------------------------------
/firefox/components/gfTestHarnessCommandLineHandler.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
6 |
7 | Cu.import("resource://gre/modules/XPCOMUtils.jsm");
8 | Cu.import("resource://gre/modules/Services.jsm");
9 |
10 | function d(s) {
11 | dump("gfTestHarnessCommandLineHandler: " + s + "\n");
12 | }
13 |
14 | function gfTestHarnessRunEnvironment() {
15 | }
16 |
17 | gfTestHarnessRunEnvironment.prototype.log =
18 | function gfTestHarnessRunEnvironment_log(s)
19 | {
20 | dump("[log] " + s + "\n");
21 | }
22 |
23 | gfTestHarnessRunEnvironment.prototype.newURI =
24 | function gfTestHarnessRunEnvironment_newURI(aSpec)
25 | {
26 | return Services.io.newURI(aSpec, null, null);
27 | }
28 |
29 | gfTestHarnessRunEnvironment.prototype.assertEqual =
30 | function gfTestHarnessRunEnvironment_assertEqual(a, b)
31 | {
32 | if (a != b) {
33 | this.error("Values are not equal, '" + a + "' != '" + b + "'");
34 | }
35 | }
36 |
37 | gfTestHarnessRunEnvironment.prototype.assertTrue =
38 | function gfTestHarnessRunEnvironment_assertTrue(a)
39 | {
40 | if (!a) {
41 | this.error("Value is not true");
42 | }
43 | }
44 |
45 | gfTestHarnessRunEnvironment.prototype.error =
46 | function gfTestHarnessRunEnvironment_error(aMessage)
47 | {
48 | this.log("ERROR: " + aMessage);
49 | var stack = Components.stack;
50 | while (stack) {
51 | this.log(" " + stack);
52 | stack = stack.caller;
53 | }
54 | throw Cr.NS_ERROR_ILLEGAL_VALUE;
55 | }
56 |
57 | function gfTestHarnessCommandLineHandler()
58 | {
59 | }
60 |
61 | gfTestHarnessCommandLineHandler.prototype = {
62 | classDescription: "Test Harness Command Line Handler",
63 | classID: Components.ID("{0c1b14b2-4a2c-4ba4-bf38-0f6844439986}"),
64 | contractID: "@b0nk3rz.net/greasefire2/testharness/commandlinehandler;1"
65 | }
66 |
67 | gfTestHarnessCommandLineHandler.prototype.handle =
68 | function gfTestHarnessCommandLineHandler_handle(aCommandLine)
69 | {
70 | var testPath;
71 | try {
72 | testPath = aCommandLine.handleFlagWithParam("test", true);
73 | }
74 | catch(e) {
75 | }
76 |
77 | if (testPath) {
78 | aCommandLine.preventDefault = true;
79 | var shouldQuit = this._runTest(testPath);
80 | if (shouldQuit) {
81 | aCommandLine.preventDefault = true;
82 | }
83 | else {
84 | // var appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
85 | // .getService(Ci.nsIAppStartup);
86 | // appStartup.run();
87 | }
88 | }
89 | }
90 |
91 | gfTestHarnessCommandLineHandler.prototype._runTest =
92 | function gfTestHarnessCommandLineHandler__runTest(aPath)
93 | {
94 | var consoleListener = Cc["@b0nk3rz.net/greasefire2/testharness/consolelistener;1"]
95 | .createInstance(Ci.nsIConsoleListener);
96 | Services.console.registerListener(consoleListener);
97 |
98 | var o = new gfTestHarnessRunEnvironment();
99 | var shouldQuit = true;
100 |
101 | var url = "chrome://greasefire2/content/test/" + aPath;
102 | Services.console.logStringMessage("Running test at '" + url + "'");
103 |
104 | try {
105 | Services.scriptloader.loadSubScript(url, o);
106 | shouldQuit = !o.runTest();
107 | Services.console.logStringMessage("PASSED");
108 | }
109 | catch(e) {
110 | Services.console.logStringMessage("FAILED");
111 | Cu.reportError(e);
112 | var stack = e.location;
113 | while (stack) {
114 | dump(" " + stack + "\n");
115 | stack = stack.caller;
116 | }
117 | }
118 |
119 | return shouldQuit;
120 | }
121 |
122 | gfTestHarnessCommandLineHandler.prototype.__defineGetter__("helpinfo",
123 | function gfTestHarnessCommandLineHandler_helpinfo()
124 | {
125 | return "Halp!";
126 | });
127 |
128 | function gfTestHarnessConsoleListener()
129 | {
130 | }
131 |
132 | gfTestHarnessConsoleListener.prototype = {
133 | classDescription: "Test Harness Console Listener",
134 | classID: Components.ID("{52b17aee-2705-42e0-bf2d-92afb900c4c8}"),
135 | contractID: "@b0nk3rz.net/greasefire2/testharness/consolelistener;1",
136 | observe: function(aMessage) {
137 | dump("[console] " + aMessage.message + "\n");
138 | }
139 | }
140 |
141 | function HEX(n) {
142 | var s = n.toString(16);
143 | if (s.length == 1) {
144 | s = "0" + s;
145 | }
146 | return s;
147 | }
148 |
149 | gfTestHarnessCommandLineHandler.prototype.QueryInterface =
150 | XPCOMUtils.generateQI([Ci.nsICommandLineHandler]);
151 |
152 | gfTestHarnessConsoleListener.prototype.QueryInterface =
153 | XPCOMUtils.generateQI([Ci.nsIConsoleListener]);
154 |
155 | var NSGetFactory = XPCOMUtils.generateNSGetFactory([
156 | gfTestHarnessCommandLineHandler, gfTestHarnessConsoleListener
157 | ]);
158 |
--------------------------------------------------------------------------------
/firefox/components/gfUpdaterService.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
6 |
7 | const MINUTE_IN_MS = 60000;
8 |
9 | const DEBUG = false;
10 |
11 | const NS_PROFILE_STARTUP_OBSERVER_ID = "profile-after-change";
12 | const NS_PROFILE_SHUTDOWN_OBSERVER_ID = "profile-before-change";
13 |
14 | const JARFILES = ["include.dat", "exclude.dat", "scripts.db", "info.ini"];
15 |
16 | Cu.import("resource://gre/modules/XPCOMUtils.jsm");
17 | Cu.import("resource://gre/modules/Services.jsm");
18 |
19 |
20 | function TRYIGNORE(aFunc) {
21 | try {
22 | aFunc();
23 | }
24 | catch (e) {
25 | Cu.reportError(e);
26 | }
27 | }
28 |
29 | function d(s) {
30 | if (DEBUG) {
31 | dump("gfUpdaterService: " + s + "\n");
32 | }
33 | }
34 |
35 | function gfUpdaterService() {
36 | d("ctor");
37 |
38 | this.wrappedJSObject = this;
39 | this._gfs = null;
40 | this._prefs = null;
41 | this._isUpdating = false;
42 | this._listeners = [];
43 |
44 | this._nextUpdate = null;
45 | this._timer = null;
46 | this._wbp = null;
47 | this._timer = null;
48 |
49 | Services.obs.addObserver(this, NS_PROFILE_SHUTDOWN_OBSERVER_ID, false);
50 | }
51 |
52 | gfUpdaterService.prototype = {
53 | classDescription: "Greasefire Updater Service",
54 | classID: Components.ID("{7c5b9317-0b18-4390-9a0a-a594d544a99f}"),
55 | contractID: "@b0nk3rz.net/greasefire2/updater;1"
56 | }
57 |
58 | gfUpdaterService.prototype._startup =
59 | function gfUpdaterService__startup()
60 | {
61 | d("startup");
62 |
63 | this._gfs = Cc["@b0nk3rz.net/greasefire2/service;1"].getService().wrappedJSObject;
64 |
65 | this._prefs = Services.prefs.getBranch("extensions.greasefire2.");
66 |
67 | // If we are overdue for an update at startup, push it a minute in the future
68 | // so we don't slow down startup
69 | if (this.updateIntervalMinutes > 0 && Date.now() > this.nextUpdateDate) {
70 | this._updateNextUpdateDate(1);
71 | }
72 |
73 | this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
74 | this._timer.initWithCallback(this,
75 | MINUTE_IN_MS,
76 | Ci.nsITimer.TYPE_REPEATING_SLACK);
77 | }
78 |
79 | gfUpdaterService.prototype._shutdown =
80 | function gfUpdaterService__shutdown()
81 | {
82 | d("shutdown");
83 |
84 | if (this._timer) {
85 | this._timer.cancel();
86 | this._timer = null;
87 | }
88 | }
89 |
90 | gfUpdaterService.prototype._updateNextUpdateDate =
91 | function gfUpdaterService__updateNextUpdateDate(aMinutes)
92 | {
93 | var ms = aMinutes * MINUTE_IN_MS;
94 | this._prefs.setCharPref("next_update_date", Date.now() + ms);
95 | }
96 |
97 | gfUpdaterService.prototype._processDownload =
98 | function gfUpdaterService__processDownload()
99 | {
100 | var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
101 | .createInstance(Ci.nsIZipReader);
102 |
103 | var status = Cr.NS_OK;
104 | var message = "OK";
105 |
106 | try {
107 | zipReader.open(this._dest);
108 | JARFILES.forEach(function(e) {
109 | zipReader.test(e);
110 | });
111 |
112 | var exDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
113 | exDir.append("greasefire2@b0nk3rz.net");
114 |
115 | var unpackDir = exDir.clone();
116 | unpackDir.append("indexes.new");
117 | unpackDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0755);
118 |
119 | JARFILES.forEach(function(e) {
120 | var f = unpackDir.clone();
121 | f.append(e);
122 | zipReader.extract(e, f);
123 | });
124 |
125 | var oldIndexDir = exDir.clone();
126 | oldIndexDir.append("indexes");
127 |
128 | var backupDir = exDir.clone();
129 | backupDir.append("indexes.backup");
130 | backupDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0755);
131 |
132 | // Stop the greasefire2 service and move the dirs around
133 | this._gfs.shutdown();
134 | try {
135 | if (oldIndexDir.exists()) {
136 | oldIndexDir.moveTo(backupDir, "");
137 | }
138 | unpackDir.moveTo(null, "indexes");
139 | }
140 | catch (e) {
141 | // Something went wrong, move things back
142 | Cu.reportError("Error moving indexes " + e.message);
143 | status = Cr.NS_ERROR_FAILURE;
144 | message = "Error moving indexes: " + e.message;
145 |
146 | unpackDir.remove(true);
147 | oldIndexDir.moveTo(exDir, "");
148 | }
149 | this._gfs.startup();
150 |
151 | // Everything is ok, delete the backup dir
152 | backupDir.remove(true);
153 | }
154 | catch (e) {
155 | Cu.reportError(e);
156 | if (status = Cr.NS_OK) {
157 | status = Cr.NS_ERROR_FAILURE;
158 | message = e.message;
159 | }
160 | }
161 |
162 | TRYIGNORE(function() {
163 | zipReader.close();
164 | });
165 |
166 | this._updateFinished(status, message);
167 | }
168 |
169 | gfUpdaterService.prototype._updateFinished =
170 | function gfUpdaterService__updateFinished(aStatus, aMessage) {
171 |
172 | this._isUpdating = false;
173 |
174 | if (this._dest) {
175 | var dest = this._dest;
176 | TRYIGNORE(function() {
177 | dest.remove(false);
178 | });
179 | this._dest = null;
180 | }
181 |
182 | if (this._wbp) {
183 | this._wbp.progressListener = null;
184 | }
185 | this._wbp = null;
186 |
187 | this._notify(function(l) {
188 | l.onUpdateFinished(aStatus, aMessage);
189 | });
190 | }
191 |
192 | gfUpdaterService.prototype._notify =
193 | function gfUpdaterService__notify(aFunc)
194 | {
195 | this._listeners.forEach(function(l) {
196 | try {
197 | aFunc(l);
198 | }
199 | catch (e) {
200 | Cu.reportError(e);
201 | }
202 | });
203 | }
204 |
205 | gfUpdaterService.prototype.startUpdate =
206 | function gfUpdaterService_startUpdate(aForce)
207 | { return;
208 | /*
209 | if (this._isUpdating) {
210 | return;
211 | }
212 |
213 | var self = this;
214 | this._isUpdating = true;
215 | this._notify(function(l) {
216 | l.onUpdateStarted();
217 | });
218 |
219 | try {
220 | this._wbp = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
221 | .createInstance(Ci.nsIWebBrowserPersist);
222 | this._wbp.progressListener = this;
223 |
224 | // Create a destination file for the download
225 | this._dest = Services.dirsvc.get("TmpD", Ci.nsIFile);
226 | this._dest.append("greasefire2_index_download.jar");
227 | this._dest.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
228 |
229 | // Start the download
230 | var uri = Services.io.newURI(
231 | this._prefs.getComplexValue("update_url", Ci.nsISupportsString).data,
232 | null, null);
233 |
234 | var headers = null;
235 | this._gfs.getIndexDate(function(aDate) {
236 | if (aDate > 0 && !aForce) {
237 | headers = "If-Modified-Since: " +
238 | (new Date(aDate)).toGMTString() + "\r\n";
239 | }
240 |
241 | self._wbp.saveURI(uri, null, null, null, headers, self._dest, null); // TODO: use real pricacy context
242 | });
243 | }
244 | catch (e) {
245 | // Something went wrong setting up the download.
246 | Cu.reportError(e);
247 | this._updateFinished(Cr.NS_ERROR_FAILURE, e.message);
248 | }
249 | */
250 | }
251 |
252 | gfUpdaterService.prototype.cancelUpdate =
253 | function gfUpdaterService_cancelUpdate()
254 | {
255 | if (this._isUpdating && this._wbp) {
256 | this._wbp.cancelSave();
257 | }
258 | }
259 |
260 | gfUpdaterService.prototype.__defineGetter__("isUpdating",
261 | function gfUpdaterService_get_isUpdating()
262 | {
263 | return this._isUpdating;
264 | });
265 |
266 | gfUpdaterService.prototype.__defineGetter__("nextUpdateDate",
267 | function gfUpdaterService_get_nextUpdateDate()
268 | {
269 | try {
270 | return parseInt(this._prefs.getCharPref("next_update_date"));
271 | }
272 | catch(e) {
273 | }
274 | return 0;
275 | });
276 |
277 | gfUpdaterService.prototype.__defineGetter__("updateIntervalMinutes",
278 | function gfUpdaterService_get_updateIntervalMinutes()
279 | {
280 | try {
281 | return this._prefs.getIntPref("update_interval_minutes");
282 | }
283 | catch(e) {
284 | }
285 | return 0;
286 | });
287 |
288 | gfUpdaterService.prototype.__defineSetter__("updateIntervalMinutes",
289 | function gfUpdaterService_set_updateIntervalMinutes(aMinutes)
290 | {
291 | this._prefs.setIntPref("update_interval_minutes", aMinutes);
292 | this._updateNextUpdateDate(aMinutes);
293 | });
294 |
295 | gfUpdaterService.prototype.addListener =
296 | function gfUpdaterService_addListener(aListener)
297 | {
298 | if (this._listeners.indexOf(aListener) >= 0) {
299 | return;
300 | }
301 | this._listeners.push(aListener);
302 | }
303 |
304 | gfUpdaterService.prototype.removeListener =
305 | function gfUpdaterService_removeListener(aListener)
306 | {
307 | this._listeners.filter(function(e) {
308 | return aListener != e;
309 | });
310 | }
311 |
312 | // nsIWebProgressListener
313 | gfUpdaterService.prototype.onStateChange =
314 | function gfUpdaterService_onStateChange(aWebProgress,
315 | aRequest,
316 | aStateFlags,
317 | aStatus)
318 | {
319 | d("onStateChange");
320 | if (this._isUpdating && aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
321 |
322 | if (this._wbp.result == Cr.NS_BINDING_ABORTED) {
323 | this._updateFinished(Cr.NS_BINDING_ABORTED, "Cancelled");
324 | return;
325 | }
326 |
327 | var responseStatus = null;
328 | try {
329 | responseStatus = aRequest.QueryInterface(Ci.nsIHttpChannel).responseStatus;
330 | }
331 | catch (e) {
332 | }
333 |
334 | if (responseStatus == 200) {
335 | this._processDownload();
336 | return;
337 | }
338 |
339 | if (responseStatus == 304) {
340 | this._updateFinished(Cr.NS_ERROR_FILE_ALREADY_EXISTS, "Not Modified");
341 | return;
342 | }
343 |
344 | this._updateFinished(Cr.NS_ERROR_FAILURE,
345 | "status = 0x" + aStatus.toString(16) + " " +
346 | "http = " + responseStatus);
347 | }
348 | }
349 |
350 | gfUpdaterService.prototype.onProgressChange =
351 | function gfUpdaterService_onProgressChange(aWebProgress,
352 | aRequest,
353 | aCurSelfProgress,
354 | aMaxSelfProgress,
355 | aCurTotalProgress,
356 | aMaxTotalProgress)
357 | {
358 | if (this._isUpdating) {
359 | this._notify(function(l) {
360 | l.onDownloadProgress(aCurTotalProgress, aMaxTotalProgress);
361 | });
362 | }
363 | }
364 |
365 | gfUpdaterService.prototype.onLocationChange =
366 | function gfUpdaterService_onLocationChange(aWebProgress, aRequest, aLocation)
367 | {
368 | }
369 |
370 | gfUpdaterService.prototype.onStatusChange =
371 | function gfUpdaterService_onStatusChange(aWebProgress,
372 | aRequest,
373 | aStatus,
374 | aMessage)
375 | {
376 | }
377 |
378 | gfUpdaterService.prototype.onSecurityChange =
379 | function gfUpdaterService_onSecurityChange(aWebProgress, aRequest, aState)
380 | {
381 | }
382 |
383 | // nsITimer
384 | gfUpdaterService.prototype.notify =
385 | function gfUpdaterService_notify(aTimer)
386 | {
387 | if (this.updateIntervalMinutes > 0 && Date.now() > this.nextUpdateDate) {
388 | this._updateNextUpdateDate(this.updateIntervalMinutes);
389 | this.startUpdate(false);
390 | }
391 | }
392 |
393 | // nsIObserver
394 | gfUpdaterService.prototype.observe =
395 | function gfUpdaterService_observe(aSubject, aTopic, aData)
396 | {
397 | if (aTopic == NS_PROFILE_STARTUP_OBSERVER_ID) {
398 | this._startup();
399 | }
400 | else if (aTopic == NS_PROFILE_SHUTDOWN_OBSERVER_ID) {
401 | this._shutdown();
402 | Services.obs.removeObserver(this, NS_PROFILE_STARTUP_OBSERVER_ID);
403 | Services.obs.removeObserver(this, NS_PROFILE_SHUTDOWN_OBSERVER_ID);
404 | }
405 | }
406 |
407 | var NSGetFactory = null;
408 | gfUpdaterService.prototype.QueryInterface =
409 | XPCOMUtils.generateQI([Ci.nsIObserver,
410 | Ci.nsIWebProgressListener,
411 | Ci.nsITimerCallback]);
412 | NSGetFactory = XPCOMUtils.generateNSGetFactory([gfUpdaterService]);
413 |
414 | function dob(o) {
415 |
416 | var s = "";
417 | if (typeof(o) == "string") {
418 | s = o;
419 | }
420 | else {
421 | if (o.length) {
422 | }
423 | else {
424 | var a = [];
425 | for (var k in o) {
426 | a.push(k + " => " + o[k]);
427 | }
428 | s = a.join(", ");
429 | }
430 | }
431 |
432 | dump("[updater] " + s + "\n");
433 |
434 | }
435 |
--------------------------------------------------------------------------------
/firefox/defaults/preferences/greasefire.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 by Steve Krulewitz
3 | * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
4 | */
5 | pref("extensions.greasefire2.update_interval_minutes", 0);
6 | pref("extensions.greasefire2.update_url", "http://frog23.net/greasefire/update.php");
7 | pref("extensions.greasefire2.us_mirror", "http://userscripts-mirror.org/scripts/");
8 | pref("extensions.greasefire2.notification_sound_path", "");
9 |
10 |
--------------------------------------------------------------------------------
/firefox/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/firefox/icon.png
--------------------------------------------------------------------------------
/firefox/indexes/exclude.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/firefox/indexes/exclude.dat
--------------------------------------------------------------------------------
/firefox/indexes/include.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/firefox/indexes/include.dat
--------------------------------------------------------------------------------
/firefox/indexes/info.ini:
--------------------------------------------------------------------------------
1 | [indexes]
2 | date=2014-05-24T08:06:23Z
3 |
--------------------------------------------------------------------------------
/firefox/indexes/scripts.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/firefox/indexes/scripts.db
--------------------------------------------------------------------------------
/firefox/install.rdf:
--------------------------------------------------------------------------------
1 |
2 |
3 | #filter substitution
4 |
5 | greasefire2@b0nk3rz.net
6 | 2.1.1
7 | 2
8 |
9 |
10 |
11 |
12 | {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
13 | 4.0
14 | 34.*
15 |
16 |
17 |
18 | Greasefire2
19 | B0nk3rZ
20 | http://www.b0nk3rz.net/
21 | Automatically find Greasemonkey scripts on userscripts-mirror.org
22 | chrome://greasefire2/content/prefs.xul
23 |
24 | Original creator: skrul (Steve Krulewitz)
25 | frog23 (http://frog23.net/) for supplying the latest index
26 | Flame images from Foxkeh's Blog (http://www.foxkeh.com)
27 | Erik Vold (http://erikvold.com)
28 | Greg Parris (http://phob.net)
29 | Tony Wang ( https://www.masterbranch.com/developer/tonyq.wang )
30 | Quicksaver (https://github.com/Quicksaver) - Compatibility with CustomizableUI (Puzzle Toolbars)
31 |
32 |
--------------------------------------------------------------------------------
/firefox/makexpi.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | zip \
4 | greasefire2.xpi \
5 | install.rdf \
6 | icon.png \
7 | chrome.manifest \
8 | components/* \
9 | defaults/preferences/* \
10 | chrome/content/* \
11 | chrome/content/test/* \
12 | indexes/*
13 |
14 | if [[ "test" != "$1" ]]; then
15 | zip -d greasefire2.xpi chrome/content/test/ chrome/content/test/*
16 | fi
17 |
--------------------------------------------------------------------------------
/java/greasefire-scraper/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/java/greasefire-scraper/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | greasefire-scraper
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/java/greasefire-scraper/downloadscripts.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/java/greasefire-scraper/downloadscripts.jar
--------------------------------------------------------------------------------
/java/greasefire-scraper/generateindex.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/java/greasefire-scraper/generateindex.jar
--------------------------------------------------------------------------------
/java/greasefire-scraper/lib/commons-codec-1.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/java/greasefire-scraper/lib/commons-codec-1.3.jar
--------------------------------------------------------------------------------
/java/greasefire-scraper/lib/commons-httpclient-3.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/java/greasefire-scraper/lib/commons-httpclient-3.1.jar
--------------------------------------------------------------------------------
/java/greasefire-scraper/lib/commons-logging-1.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/java/greasefire-scraper/lib/commons-logging-1.1.jar
--------------------------------------------------------------------------------
/java/greasefire-scraper/lib/htmlcleaner2_1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/java/greasefire-scraper/lib/htmlcleaner2_1.jar
--------------------------------------------------------------------------------
/java/greasefire-scraper/lib/sqlitejdbc-v043-nested.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/B0nk3rZ/greasefire2/7f9a346ce9c2e08ea396bd584a75c656262805b2/java/greasefire-scraper/lib/sqlitejdbc-v043-nested.jar
--------------------------------------------------------------------------------
/java/greasefire-scraper/src/com/skrul/greasefire/AlphaPNGOutputStream.java:
--------------------------------------------------------------------------------
1 | package com.skrul.greasefire;
2 |
3 | import java.awt.image.BufferedImage;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.File;
6 | import java.io.IOException;
7 | import java.io.OutputStream;
8 |
9 | import javax.imageio.ImageIO;
10 |
11 | public class AlphaPNGOutputStream extends OutputStream {
12 |
13 | private File outputFile;
14 | private ByteArrayOutputStream os;
15 |
16 | public AlphaPNGOutputStream(File outputFile) {
17 | this.outputFile = outputFile;
18 | this.os = new ByteArrayOutputStream();
19 | }
20 |
21 | @Override
22 | public void close() throws IOException {
23 | byte[] bytes = this.os.toByteArray();
24 | double size = bytes.length / 4.0;
25 | if (size - Math.floor(size) > 0)
26 | size++;
27 |
28 | BufferedImage bi = new BufferedImage((int) size, 1, BufferedImage.TYPE_INT_ARGB);
29 | bi.coerceData(false);
30 | int pos = 0;
31 | for (int i = 0; i < bytes.length; i += 4) {
32 | int r = bytes[i];
33 | int g = i + 1 < bytes.length ? bytes[i + 1] : 0;
34 | int b = i + 2 < bytes.length ? bytes[i + 2] : 0;
35 | int a = i + 3 < bytes.length ? bytes[i + 3] : 0;
36 | int value = ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF) << 0);
37 | bi.setRGB(pos, 0, value);
38 | pos++;
39 | }
40 |
41 | ImageIO.write(bi, "PNG", this.outputFile);
42 | }
43 |
44 | @Override
45 | public void write(int b) throws IOException {
46 | this.os.write(b);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/java/greasefire-scraper/src/com/skrul/greasefire/DownloadScripts.java:
--------------------------------------------------------------------------------
1 | package com.skrul.greasefire;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileOutputStream;
6 | import java.io.FileWriter;
7 | import java.io.IOException;
8 | import java.text.SimpleDateFormat;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 | import java.util.Properties;
12 | import java.util.logging.Level;
13 | import java.util.logging.Logger;
14 |
15 | import org.apache.commons.httpclient.HttpClient;
16 | import org.apache.commons.httpclient.HttpMethod;
17 | import org.apache.commons.httpclient.methods.GetMethod;
18 | import org.htmlcleaner.HtmlCleaner;
19 | import org.htmlcleaner.TagNode;
20 | import org.htmlcleaner.XPatherException;
21 |
22 | public class DownloadScripts {
23 |
24 | public static final Logger logger = Logger.getLogger(DownloadScripts.class.getName());
25 | private static final SimpleDateFormat sdf =
26 | new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
27 |
28 | public static void main(String[] args) throws Exception {
29 |
30 | if (args.length != 2) {
31 | System.out.println("usage: downloadscripts [destinationdir] [full|new]");
32 | System.exit(1);
33 | }
34 |
35 | File dir = new File(args[0]);
36 | if (!(dir.isDirectory() && dir.exists())) {
37 | throw new RuntimeException("Directory '" + dir.getPath() + "' does not exist");
38 | }
39 |
40 | boolean full = args[1].equals("full");
41 |
42 | logger.info("Saving to '" + dir.getPath() + "'");
43 |
44 | DownloadScripts da = new DownloadScripts();
45 | da.run(dir, full);
46 | }
47 |
48 | public void run(File dir, boolean full) {
49 |
50 | HttpClient client = new HttpClient();
51 | String url = "http://greasefire.userscripts.org/scripts?page=";
52 | int page = 1;
53 | boolean done = false;
54 | while (!done && page < 1500) {
55 | List