var _SAFESIGNED_cert_type = 255; var _SAFESIGNED_certificate = 4508 var _SAFESIGNED_sb_logo = ''; var _SAFESIGNED_scripts = document.getElementsByTagName("script"); var _SAFESIGNED_count = _SAFESIGNED_scripts.length; if (typeof _SAFESIGNED_refresh_page !== 'function' ) { function _SAFESIGNED_refresh_page() { setTimeout(function() { location.reload(true); }, 3600000); } _SAFESIGNED_refresh_page(); } function _SAFESIGNED_normalize_url(url) { return url.replace(/\/+$/, ''); } //split "167, 42, 5" into [167, 42, 5] (no nested calls or commas inside values expected) function _SAFESIGNED_parse_args(args_str) { var args = []; var parts = args_str.split(','); for (var i = 0; i < parts.length; i++) { var p = parts[i].replace(/^\s+|\s+$/g, ''); if (p === '') { continue; } var q = p.charAt(0); if ((q == "'" || q == '"') && p.charAt(p.length - 1) == q) { args.push(p.substring(1, p.length - 1)); } else if (/^-?\d+(\.\d+)?$/.test(p)) { args.push(Number(p)); } else { args.push(p); } } return args; } //run the embed snippet (e.g. "var SEAL_CONTAINER_1 = new SEAL(1, 2, 5); SEAL_CONTAINER_1.loadSeal();") without //eval, so the seal works on pages whose Content-Security-Policy does not allow 'unsafe-eval' function _SAFESIGNED_run_inline(code) { var re = /(?:var\s+)?([A-Za-z_$][\w$]*)\s*=\s*new\s+SEAL\s*\(([^)]*)\)/g; var found = false; var m; //ignore commented-out code (eval would), keeping "//" that follows ":" as in URLs code = code.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|[^:])\/\/.*$/gm, '$1'); while ((m = re.exec(code)) !== null) { var args = _SAFESIGNED_parse_args(m[2]); var seal = new SEAL(args[0], args[1], args[2], args[3]); //loader responses call SEAL_CONTAINER_.gen_seal_*(), so the instance must be global under that name window[m[1]] = seal; window[seal.var_name] = seal; var load_re = new RegExp(m[1].replace(/\$/g, '\\$') + '\\s*\\.\\s*loadSeal\\s*\\('); if (load_re.test(code)) { seal.loadSeal(); } found = true; } return found; } while (_SAFESIGNED_count > 0) { _SAFESIGNED_count--; var _SAFESIGNED_curr_script = _SAFESIGNED_scripts[_SAFESIGNED_count]; var _SAFESIGNED_script = "https://verify.safesigned.com/seal/" + _SAFESIGNED_cert_type + '/' + _SAFESIGNED_certificate; if (_SAFESIGNED_normalize_url(_SAFESIGNED_curr_script.src) == _SAFESIGNED_normalize_url(_SAFESIGNED_script)) { //add seal CSS (Note: we can override the _SAFESIGNED_ variable with no harm, because the script object it //used to reference has already been inserted into the section of the page) _SAFESIGNED_css = document.createElement('link'); _SAFESIGNED_css.rel = "stylesheet"; _SAFESIGNED_css.type = "text/css"; _SAFESIGNED_css.href = "https://verify.safesigned.com/static/api/seal_css.css"; //TODO: append only if it does not exist yet //TODO: simply add snippet to loadSeal method? document.getElementsByTagName('head')[0].appendChild(_SAFESIGNED_css); //execute code for triggering seal loading var _SAFESIGNED_inline = _SAFESIGNED_curr_script.text || _SAFESIGNED_curr_script.textContent || _SAFESIGNED_curr_script.innerHTML; if (_SAFESIGNED_inline && !_SAFESIGNED_run_inline(_SAFESIGNED_inline)) { //unrecognised snippet format: fall back to eval (fails on pages whose CSP blocks 'unsafe-eval') try { window['eval'](_SAFESIGNED_inline); } catch (ex) { if (window.console) { console.warn('Safesigned seal: unable to run seal snippet', ex); } } } break; } } /* this version of the script is meant for displaying ALL types of seals (external seals currently excluded) and should be coupled with a code which loads seals ASYNCHRONOUSLY */ function SEAL(cert_type_id, cert_id, seal_shape, text_id) { text_id = typeof text_id !== 'undefined' ? text_id : 'none'; this.text_id = text_id; this.cert_id = cert_id; this.cert_type_id = cert_type_id; this.seal_shape = seal_shape; //1 - notary, 2 - tab, 4 - rectangle, 5 - classic this.base_url = "https://verify.safesigned.com/"; this.var_name = 'SEAL_CONTAINER_' + this.cert_type_id; //CON instance variable name this.t_AR = 1200; //seal automatic reload time in seconds (after the seal has been loaded) this.t_SL = 2000; //spinner "loading" time in miliseconds //determine current page url (TODO: move this to function A() because you trigger security exception there //again anyway (to check loading in iframe etc) try { this.p_url = window.top.location.href; //we need to get topmost location (just in case if page uses frames) this.r_url = window.top.document.referrer; //referring url ... needed only for statistics } catch (ex) { //security exception... seal is loaded on a page which is open in a frame on another domain this.p_url = window.location.href; //save current page url, although it won't be used, because //it is open in a frame on another domain this.r_url = ''; } this.loadSeal = function() { this.c_name = 'safesigned_seal_' + this.cert_type_id //seal container name this.c_div = document.getElementById(this.c_name); //container div this.A(); //create script request link and insert it into section (and load it this way) //TODO: load CSS here if not yet included? }; //generates a link to the seal displaying script and inserts this link into the head //section of the page so that the script is retrieved and executed this.A = function() { var CON_objHead = document.getElementsByTagName("head")[0]; var CON_objScript = document.createElement("script"); CON_objScript.type = 'text/javascript'; var CON_mode = location.protocol; var CON_isSecure = (CON_mode == 'https:') ? 1 : 0; var parts = this.r_url.split('/', 3); var ref_domain = (parts.length < 3) ? '' : parts[2]; var cookies = document.cookie.split(';'), name = 'safesigned_ct=', //cookie name token = 'F0F0'; for (var i = 0; i < cookies.length; i++) { var c = cookies[i]; while (c.charAt(0) == ' ') { c = c.substring(1, c.length); } if (c.indexOf(name) === 0) { token = c.substring(name.length, c.length); } } //generate a link to request the seal var seal_req_link = this.base_url + "seal_loader/" + this.cert_type_id + '/' + this.cert_id + '/?' + 'secure=' + CON_isSecure + '&p_url=' + escape(this.p_url) + '&token=' + token + '&s_shape=' + this.seal_shape + '&ref_d=' + escape(ref_domain) + '&text_id=' + this.text_id + '&' + Math.floor(Math.random()*999999999999); try { var dummy = window.top.document; //trigger security exception if page is loaded in an iframe on another domain } catch (ex) { //create invalid script link that will result in a NOT VERIFIED seal //-6 for p_url is our special error code which indicates that a security exception was triggered seal_req_link = this.base_url + "seal_loader/" + this.cert_type_id + '/' + this.cert_id + '/?' + 'secure=' + CON_isSecure + '&p_url=-6' + '&s_shape=' + this.seal_shape + '&ref_d=' + '&' + Math.floor(Math.random()*999999999999); } CON_objScript.src = seal_req_link; CON_objHead.appendChild(CON_objScript); var self = this; window.setTimeout(function() { self.A(); }, (this.t_AR * 1000)); //set automatic seal reload time }; //attach signature bubble toggling to an element. Handlers are set as properties (no inline //attributes, no eval) so the seal works under a strict Content-Security-Policy this.bind_bubble_toggle = function(el, bubble_id) { var self = this; el.onmouseover = function() { self.sig_bubble_pre_toggle(bubble_id, true); }; el.onmouseout = function() { self.sig_bubble_pre_toggle(bubble_id, false); }; }; //create the link to the certificate page showing the seal image (as a background for rectangle seals) this.make_seal_link = function(cert_link, seal_img_url, as_background, bubble_id) { var link = document.createElement("a"); link.target = "_top"; link.href = cert_link; var hover_el = link; if (as_background) { link.style.background = "transparent url(" + seal_img_url + ") no-repeat 0 0"; link.appendChild(document.createTextNode("\u00a0")); } else { var img = document.createElement("img"); img.src = seal_img_url; img.alt = "Seal"; img.oncontextmenu = function() { return false; }; link.appendChild(img); hover_el = img; } if (bubble_id) { this.bind_bubble_toggle(hover_el, bubble_id); } return link; }; this.sig_box_html = function(shape, signature) { return ['
', this.html_escape(signature), '
'].join(""); }; //create the signature bubble (hidden) at the top of the container if it does not exist yet this.add_sig_bubble = function(container, bubble_id, shape) { var sig_bubble = document.getElementById(bubble_id); if (!sig_bubble) { sig_bubble = document.createElement("div"); sig_bubble.id = bubble_id; this.bind_bubble_toggle(sig_bubble, bubble_id); sig_bubble.innerHTML = ['
', '', CON_SIG_MSG, '', '
'].join(""); container.insertBefore(sig_bubble, container.firstChild); } sig_bubble.style.display = "none"; }; //generate a seal placed in the seal container (classic or notary) //if signature is not provided (undefined), this means we have tech. issues or "not verified" case //if signature IS provided (even if it is an empty string) this.gen_seal_boxed = function(shape, cert_link, seal_img_url, signature) { var use_bubble = (signature === ""); //empty string (NOTE: undefined does not count!) var show_sig = signature ? true : false; var bubble_id = "sig_bubble_" + this.cert_type_id; this.c_div.innerHTML = show_sig ? this.sig_box_html(shape, signature) : ""; this.c_div.insertBefore(this.make_seal_link(cert_link, seal_img_url, false, use_bubble ? bubble_id : null), this.c_div.firstChild); if (use_bubble) { this.add_sig_bubble(this.c_div, bubble_id, shape); } }; //generate classic seal this.gen_seal_cls = function(cert_link, seal_img_url, signature) { this.gen_seal_boxed("classic", cert_link, seal_img_url, signature); }; //generate rectangular seal this.gen_seal_rect = function(cert_link, seal_img_url, signature) { //create master rectangle box if necessary var all_rect_box_id = "CON_all_rect_box"; var rect_box = document.getElementById(all_rect_box_id); if (!rect_box) { rect_box = document.createElement("div"); rect_box.id = all_rect_box_id; document.body.insertBefore(rect_box, document.body.firstChild); } //create new rectangle seal div (if it doesn't exist yet) and place it into the master box var new_div_id = "safesigned_con_rect_" + this.cert_type_id; var new_div = document.getElementById(new_div_id); if (!new_div) { //if div does not exist yet new_div = document.createElement("div"); new_div.id = new_div_id; new_div.className = "safesigned_con_rect"; rect_box.appendChild(new_div); //increase width of the master box by 121px (110px seal + 11px right margin) so that //new rectangle will fit in var curr_width = (rect_box.style.width) ? parseInt(rect_box.style.width) : 0; rect_box.style.width = (curr_width + 121) + "px"; } //if signature is not provided (undefined), this means we have tech. issues or "not verified" case //if signature IS provided (even if it is an empty string) var use_bubble = (signature === ""); //empty string (NOTE: undefined does not count!) var show_sig = signature ? true : false; var bubble_id = "sig_bubble_" + this.cert_type_id; new_div.innerHTML = show_sig ? this.sig_box_html("rect", signature) : ""; //signature goes before the seal new_div.appendChild(this.make_seal_link(cert_link, seal_img_url, true, use_bubble ? bubble_id : null)); if (use_bubble) { this.add_sig_bubble(new_div, bubble_id, "rect"); } }; this.toggle_sig_bubble = function(bubble_id, show) { var sig_bubble = document.getElementById(bubble_id); if (!sig_bubble) { return; //silently fail if bubble does not exist } if (show) { clearTimeout(this.bubble_hide_timer); sig_bubble.style.display = "block"; } else { sig_bubble.style.display = "none"; } }; this.sig_bubble_pre_toggle = function(bubble_id, show) { if (show) { this.toggle_sig_bubble(bubble_id, true); } else { var self = this; this.bubble_hide_timer = setTimeout(function() { self.toggle_sig_bubble(bubble_id, false); }, 50); } }; //HTML escape string this.html_escape = function(str) { return str.replace(/&/g, "&").replace(//g, ">"); }; } //end CON