Persist

Persist Function

Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greasyfork.org/scripts/29175/189868/Persist.js

// ==UserScript==
// @name           Persist
// @namespace      http://gm.wesley.eti.br
// @description    Persist Function
// @author         w35l3y
// @email          [email protected]
// @copyright      2013+, w35l3y (http://gm.wesley.eti.br)
// @license        GNU GPL
// @homepage       http://gm.wesley.eti.br
// @version        1.0.1.0
// @language       en
// @include        nowhere
// @exclude        *
// @require        https://greasyfork.org/scripts/29175-xpath/code/XPath.js?version=189855
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @connect *
// ==/UserScript==

/**************************************************************************

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

**************************************************************************/

var Persist = function (s) {
    var service = Persist.services[s];

    this.request = function (obj) {
        var k,
            xthis = this,
            params = function (def) {
                var list = {};

                this.add = function (vars) {
                    if (vars) {

                        if (typeof vars == "object") {
                            for (var k in vars) {
                                var e = vars[k];

                                if (typeof e == "object" && (!/^(?:radio|checkbox)$/i.test(e.type) || e.checked)) {
                                    var n = e.name || k;

                                    if (e.checked && /^checkbox$/i.test(e.type)) {
                                        if (n in list) {
                                            list[n].push(e.value);
                                        } else {
                                            list[n] = [e.value];
                                        }
                                    } else if ("value" in e) {
                                        list[n] = e.value;
                                    } else {
                                        list[n] = e;
                                    }
                                } else {
                                    list[k] = e;
                                }
                            }
                        } else {
                            list = vars;
                        }
                    }
                };

                this.toString = function() {
                    if (typeof list == "object") {
                        var data = "";
                        for (var key in list) {
                            if (list[key] instanceof Array) {
                                var keyarr = key.replace(/^\s+|\s+$/g, "");
                                if (!/\[\w*\]$/.test(key)) keyarr += "[]";

                                for (var k in list[key]) {
                                    var v = list[key][k];
                                    data += "&" + encodeURIComponent(keyarr) + "=" + encodeURIComponent(v);
                                }
                            } else {
                                data += "&" + encodeURIComponent(key) + "=" + encodeURIComponent(list[key]);
                            }
                        }

                        return data.substr(1);
                    } else {
                        return list;
                    }
                };
            },
            data = new params();

        data.add(obj.pdata);
        data.add(obj.adata);
        data.add(obj.data);
        data.add(obj.odata);

        if (typeof obj.onload != "function") {
            obj.onload = function (obj) {
                console.log(["request.load", obj]);
            };
        }

        if (typeof obj.onerror != "function") {
            obj.onerror = function (obj) {
                console.log(["request.error", obj]);
            };
        }

        var update = function (obj, e) {
            obj.response = {
                raw	: function () {return e;},
                text	: function () {return e.responseText;},
                json	: function () {
                    try {
                        return JSON.parse(e.responseText);
                    } catch (x) {
                        return eval("(" + e.responseText + ")");
                    }
                },
                doc	: function () {
                    try {
                        return new DOMParser().parseFromString(e.responseText, /^Content-Type: ([\w/]+)$/mi.test(e.responseHeaders) && RegExp.$1 || "text/html");
                    } catch (x) {
                        var doc = document.implementation.createHTMLDocument("");
                        doc.documentElement.innerHTML = e.responseText;

                        return doc;
                    }
                },
            };
            obj.value = e.responseText;
        },
            params = {
                url		: obj.url,
                method	: obj.method,
                onload	: function (e) {
                    update(obj, e);

                    obj[(/^2/.test(e.status)?"onload":"onerror")].apply(xthis, [obj]);
                },
                onerror	: function (e) {
                    update(obj, e);

                    obj.onerror.apply(xthis, [obj]);
                }
            },
            sdata = data.toString();

        if (/^post$/i.test(obj.method)) {
            var p = {
                headers	: {
                    "Content-Type"	: "application/x-www-form-urlencoded"
                },
                data	: sdata,
            };

            console.log(sdata);

            for (k in p) {
                params[k] = p[k];
            }
        } else if (sdata) {
            params.url += "?" + sdata;

        }

        if (typeof obj.headers == "object")
            for (k in obj.headers) {
                params.headers[k] = obj.headers[k];
            }

        return GM_xmlhttpRequest(params);
    };

    for (var k in service) {
        this[k] = service[k];
    }
};

Persist.services	= {
    LOCAL		: {
        write	: function (obj) {
            var label_keys = "persist_keys-" + obj.service,
                label_data = "persist_data-" + obj.service,
                mapping = JSON.parse(GM_getValue(label_keys, "{}")),
                data = JSON.parse(GM_getValue(label_data, "[]")),
                key = obj.key;

            if (key in mapping) {
                key = mapping[obj.key];
            }

            if (key in data) {
                var tv = typeof obj.value,
                    td = typeof data[key];

                if ((td != tv) && (td == "object" || tv == "object")) {
                    throw ["Incompatible types ", td, tv].toString();
                } else {
                    switch (td) {
                        case "string":
                            if (-1 == obj.mode) {	// prepend
                                data[key] = obj.value + data[key];
                            } else if (1 == obj.mode) {	// append
                                data[key] += obj.value;
                            } else {	// overwrite (default)
                                data[key] = obj.value;
                            }
                            break;
                        case "boolean":
                            if (-1 == obj.mode) {	// unused
                                throw ["Reserved action"].toString();
                            } else if (1 == obj.mode) {	// toggle
                                data[key] = !data[key];
                            } else {	// overwrite (default)
                                data[key] = !!value;
                            }
                            break;
                        case "number":
                            var value = Number(obj.value);

                            if (-1 == obj.mode) {	// subtract
                                data[key] -= value;
                            } else if (1 == obj.mode) {	// add
                                data[key] += value;
                            } else {	// overwrite (default)
                                data[key] = value;
                            }
                            break;
                        case "object":
                            if (-1 == obj.mode) {	// prepend
                                for (var k in data[key]) {
                                    obj.value[k] = data[key][k];
                                }
                                data[key] = obj.value;
                            } else if (1 == obj.mode) {	// append
                                for (var k in obj.value) {
                                    data[key][k] = obj.value[k];
                                }
                            } else {	// overwrite (default)
                                data[key] = obj.value;
                            }
                            break;
                        default:
                            throw ["Unsupported type " + td, data[key], key].toString();
                    }

                    obj.value = data[key];
                }
            } else {
                var tkey = data.push(obj.value);

                if (--tkey != key) {
                    if ("key" in obj) {
                        if (key in mapping) {
                            console.log(["Wrong mapping... ", tkey, key]);
                        }

                        mapping[key] = tkey;
                        obj.key = key;

                        GM_setValue(label_keys, JSON.stringify(mapping));
                    } else {
                        obj.key = tkey;
                    }
                }
            }

            GM_setValue(label_data, JSON.stringify(data));

            if (typeof obj.onload != "function") {
                obj.onload = function (obj) {
                    console.log(["write.load", obj]);
                };
            }

            return obj.onload.apply(this, [obj]);
        },
        delete	: function (obj) {
            throw ["Not implemented"].toString();
        },
        read	: function (obj) {
            var mapping = JSON.parse(GM_getValue("persist_keys-" + obj.service, "{}")),
                key = obj.key;

            if (key in mapping) {
                key = mapping[key];
            }

            obj.value = JSON.parse(GM_getValue("persist_data-" + obj.service, "[]"))[key];

            if (typeof obj.onload != "function") {
                obj.onload = function (obj) {
                    console.log(["read.load", obj]);
                };
            }

            return obj.onload.apply(this, [obj]);
        },
    },
    PASTEBIN	: {
        write	: function (obj) {
            var execute = function (x) {
                var onload = x.onload,
                    value = x.value,
                    xthis = this,
                    p = {
                        url		: "http://pastebin.com/api/api_post.php",
                        method	: "post",
                        adata		: JSON.parse(GM_getValue("pastebin_adata", JSON.stringify({
                            //						api_dev_key			: "",	// required
                            //						api_user_key		: "",
                        }))),
                        pdata		: {
                            api_paste_format		: "text",
                            api_paste_private		: "1",
                            api_paste_expire_date	: "N",
                            api_paste_code		: x.value,	// required
                        },
                        odata		: {
                            api_paste_key		: obj.key,
                            api_option			: "paste"
                        },
                        onload	: function (y) {
                            if (/^https?:\/\//i.test(y.value) && /\w+$/.test(y.value)) {
                                var key = x.key;
                                x.key = RegExp["$&"];

                                x.onload = onload;
                                x.value = value;

                                x.onload.apply(xthis, [x]);

                                if (x.read) {
                                    /* It is implemented that way because currently there isn't an EDIT option via API */
                                    y.key = key;
                                    y.onload = function (z) {
                                        console.log(["delete.load", z]);
                                    };
                                    y.onerror = function (z) {
                                        console.log(["delete.error", z]);
                                    };

                                    xthis.delete.apply(xthis, [y]);
                                }
                            } else {
                                x.onerror.apply(xthis, [x]);
                            }
                        }
                    };

                for (var i in p) {
                    x[i] = p[i];
                }

                return this.request(x);
            };

            if (1 == Math.abs(obj.mode)) {	// prepend or append
                var value = obj.value,
                    onload = obj.onload,
                    xthis = this;

                obj.onload = function (x) {
                    obj.onload = onload;

                    if (-1 == obj.mode) {	// prepend
                        obj.value = value + obj.value;
                    } else {	// append
                        obj.value += value;
                    }

                    return execute.apply(xthis, [obj]);
                };

                return this.read.apply(this, [obj]);
            } else {
                return execute.apply(this, [obj]);
            }
        },
        read	: function (obj) {
            if ("key" in obj) {
                var onload = obj.onload,
                    xthis = this,
                    p = {
                        read		: false,
                        url		: "http://pastebin.com/download.php",
                        method	: "get",
                        adata		: {
                            i	: obj.key
                        },
                        onload	: function (x) {
                            obj.onload = onload;

                            if (x.response.raw().finalUrl.indexOf(x.url)) {
                                obj.value = "";

                                obj[typeof obj.onwarn == "function"?"onwarn":"onload"].apply(this, [obj]);
                            } else {
                                obj.read = true;

                                obj.onload.apply(xthis, [obj]);
                            }
                        }
                    };
                for (var i in p) {
                    obj[i] = p[i];
                }

                return this.request(obj);
            } else {
                obj.value = "";
                obj.read = false;

                obj[typeof obj.onwarn == "function"?"onwarn":"onload"].apply(this, [obj]);
            }
        },
        delete	: function (obj) {
            var onload = obj.onload,
                value = obj.value,
                xthis = this,
                p = {
                    url		: "http://pastebin.com/api/api_post.php",
                    method	: "post",
                    adata		: JSON.parse(GM_getValue("pastebin_adata", JSON.stringify({
                        //					api_dev_key			: "",	// required
                        //					api_user_key		: "",
                    }))),
                    pdata		: {},
                    odata		: {
                        api_paste_key		: obj.key,
                        api_option			: "delete"
                    },
                    onload	: function (x) {
                        if (/^Paste Removed$/i.test(x.value)) {
                            obj.onload = onload;
                            obj.value = value;

                            obj.onload.apply(xthis, [obj]);
                        } else {
                            obj.onerror.apply(xthis, [obj]);
                        }
                    }
                };

            for (var i in p) {
                obj[i] = p[i];
            }

            return this.request(obj);
        },
    },
    PASTEBIN2	: {
        write	: function (obj) {
            var ovalue = obj.value,
                xthis = this,
                execute = function (x) {
                    var onload = x.onload,
                        nvalue = x.value,
                        p = {
                            method	: "post",
                            adata	: JSON.parse(GM_getValue("pastebin2_adata", JSON.stringify({
                                //						paste_private		: "1",
                            }))),
                            pdata	: {
                                paste_format		: "1",
                                paste_private		: "2",
                                paste_expire_date	: "N",
                                paste_code			: x.value,	// required
                            },
                            odata	: {
                                submit			: "Submit",
                                submit_hidden	: "submit_hidden",
                                item_key		: obj.key,
                                post_key		: obj.key,
                            },
                            onload	: function (y) {
                                var doc = y.response.doc(),
                                    url = y.response.raw().finalUrl;

                                if (/warning\.php\?p=(\d+)/i.test(url)) {
                                    x.code = RegExp.$1 - 1;
                                    x.value = [
                                        "You have reached your limit of [10] pastes per 24 hours.",
                                        "You have reached your limit of [20] pastes per 24 hours.",
                                        "You have reached your limit of [250] pastes per 24 hours.",
                                    ][x.code] || xpath("string(id('content_left')/div[2])", doc) || "Unknown error (WARN " + x.code + ")";

                                    x.onerror.apply(xthis, [x]);
                                } else if ((/^https?:/i.test(url)) && (/\/(\w+)$/.test(url))) {
                                    x.key = RegExp.$1;

                                    if (xpath("string(.//text()[contains(., 'Pastebin.com is under heavy load right now')])", doc)) {
                                        x.onerror.apply(xthis, [x]);
                                    } else {
                                        if (xpath("id('siimage')", doc)[0]) {
                                            x.value = nvalue;
                                            GM_log(ovalue);
                                            alert("A new window will be opened. You must fill the captcha correctly, otherwise you will lose your data and a new paste will be created next time.");
                                            GM_openInTab(url);
                                        } else {
                                            var code = xpath("id('paste_code')", doc)[0];
                                            x.value = code && code.textContent || "";
                                        }
                                        x.onload = onload;
                                        x.onload.apply(xthis, [x]);
                                    }
                                } else {
                                    x.value = [
                                        "You have exceeded the maximum file size of [500] kilobytes per paste.",
                                        "You cannot create an empty paste.",
                                        "You have reached the maximum number of [25] unlisted pastes.",
                                        "You have reached the maximum number of [10] private pastes.",
                                    ][/index\.php\?e=(\d+)/.test(url) && (x.code = RegExp.$1 - 1)] || xpath("string(id('notice'))", doc) || "Unknown error (ERROR " + x.code + ")";

                                    x.onerror.apply(xthis, [x]);
                                }
                            }
                        };

                    for (var i in p) {
                        x[i] = p[i];
                    }

                    return this.request(x);
                };

            if (1 == Math.abs(obj.mode)) {	// prepend or append
                var onload = obj.onload;

                if ("" != ovalue) {
                    obj.onload = function (x) {
                        obj.onload = onload;

                        if (-1 == obj.mode) {	// prepend
                            obj.value = ovalue + obj.value;
                        } else {	// append
                            obj.value += ovalue;
                        }

                        return execute.apply(xthis, [obj]);
                    };
                }

                return xthis.read.apply(xthis, [obj]);
            } else {
                return execute.apply(xthis, [obj]);
            }
        },
        read	: function (obj) {
            var xthis = this;

            if ("key" in obj && obj.key) {
                var onload = obj.onload,
                    p = {
                        read		: false,
                        url		: "http://pastebin.com/download.php",
                        method	: "get",
                        adata		: {
                            i	: obj.key
                        },
                        onload	: function (x) {
                            var url = x.response.raw().finalUrl;

                            x.onload = onload;

                            if (url.indexOf(x.url)) {	// Unknown Paste ID
                                x.value = "";
                                x.url = "http://pastebin.com/post.php";
                                x.key = "";

                                x[typeof x.onwarn == "function"?"onwarn":"onload"].apply(this, [x]);
                            } else if (~x.value.indexOf("this is a private paste. If this is your private paste")) {	// may occur false positive
                                x.value = "This is a private paste (#"+x.key+"). You must login to Pastebin first.";
                                x.onerror.apply(xthis, [x]);
                            } else if (~x.value.indexOf("Pastebin.com is under heavy load right now")) {
                                x.value = "Pastebin.com is under heavy load right now.";
                                x.onerror.apply(xthis, [x]);
                            } else {
                                x.read = true;
                                x.url = "http://pastebin.com/edit.php";

                                x.onload.apply(xthis, [x]);
                            }
                        }
                    };
                for (var i in p) {
                    obj[i] = p[i];
                }

                return this.request(obj);
            } else {
                obj.read = false;
                obj.url = "http://pastebin.com/post.php";
                obj.key = "";

                this.request({
                    url		: "http://pastebin.com/",
                    method	: "get",
                    onload	: function (c) {
                        if (xpath("boolean(id('header_bottom')//a[contains(@href, '/logout')])", c.response.doc())) {
                            obj.value = "";

                            obj[typeof obj.onwarn == "function"?"onwarn":"onload"].apply(xthis, [obj]);
                        } else {
                            obj.value = "You must login to Pastebin first.";

                            obj.onerror.apply(xthis, [obj]);
                        }
                    },
                    onerror	: function (c) {
                        c.value = xpath("string(id('content_left')/div[1])", c.response.doc());

                        obj.onerror(c);
                    },
                });
            }
        },
        delete	: function (obj) {
            var onload = obj.onload,
                value = obj.value,
                xthis = this,
                p = {
                    url		: "http://pastebin.com/delete.php",
                    method	: "get",
                    adata	: {},
                    pdata	: {},
                    odata	: {
                        i	: obj.key,
                        r	: "/" + obj.key
                    },
                    onload	: function (x) {
                        if (/^Paste Removed$/i.test(x.value)) {
                            obj.onload = onload;
                            obj.value = value;

                            obj.onload.apply(xthis, [obj]);
                        } else {
                            obj.onerror.apply(xthis, [obj]);
                        }
                    }
                };

            for (var i in p) {
                obj[i] = p[i];
            }

            return this.request(obj);
        }
    }
};

Persist.write = function (obj) {
    var p = new Persist(obj.service);

    return p.write.apply(p, [obj]);
};

Persist.delete = function (obj) {
    var p = new Persist(obj.service);

    return p.delete.apply(p, [obj]);
};

Persist.read = function (obj) {
    var p = new Persist(obj.service);

    return p.read.apply(p, [obj]);
};