• Resolved crmacdonald1

    (@crmacdonald1)


    So! I’ve been frustrated with some hackery run amok on my site.

    I don’t have a shared hosting environment, and only manage 1 website.

    I have installed your plugin and found some “Potential Threats”.

    I’m not as seasoned as others in this matter, and while I understand the basics in malicious coding (base64, iframe, eval), my problem is, when I find it, I don’t know how much of the coding is malicious (in other words, I don’t always know where the malicious code ends, and where the safe/ regular coding begins [or vice versa]).

    Should the entire run of coding that the plugin has found and labelled as “Potential Threats” be considered malicious? Or just part of it? The coding that the plugin found is definitely malicious, as I see “eval” and such buzzwords contained in it to tip me off as such.

    Here’s what the plugin found:

    _________________________________________________________________
    _________________________________________________________________

    …\wp-content\plugins\gotmls\images\trace.php

    <?php eval(‘$_SERVER[“REMOTE_ADDR”] = “‘.$_SERVER[“REMOTE_ADDR”].'”;’);
    // Debug Tracer function by ELI at GOTMLS.NET
    function GOTMLS_debug_trace($file) {
    if (!session_id())
    @session_start();
    if (!isset($_SESSION[“GOTMLS_traces”]))
    $_SESSION[“GOTMLS_traces”] = 0;
    if (!isset($_SESSION[“GOTMLS_trace_includes”]))
    $_SESSION[“GOTMLS_trace_includes”] = array();
    if (isset($_SESSION[“GOTMLS_trace_includes”][$_SESSION[“GOTMLS_traces”]][$file]))
    $_SESSION[“GOTMLS_traces”] = microtime(true);
    if (!$GOTMLS_headers_sent && $GOTMLS_headers_sent = headers_sent($filename, $linenum)) {
    if (!$filename)
    $filename = __(“an unknown file”,’gotmls’);
    if (!is_numeric($linenum))
    $linenum = __(“unknown”,’gotmls’);
    $_SESSION[“GOTMLS_trace_includes”][$_SESSION[“GOTMLS_traces”]][$file] = microtime(true).sprintf(__(‘: Headers sent by %1$s on line %2$s.’,’gotmls’), $filename, $linenum);
    } else
    $_SESSION[“GOTMLS_trace_includes”][$_SESSION[“GOTMLS_traces”]][$file] = microtime(true);
    if (isset($_GET[“GOTMLS_traces”]) && count($_SESSION[“GOTMLS_trace_includes”][$_SESSION[“GOTMLS_traces”]]) > $_GET[“GOTMLS_includes”]) {
    $_SESSION[“GOTMLS_traces”] = microtime(true);
    foreach ($_SESSION[“GOTMLS_trace_includes”] as $trace => $array)
    if ($trace < $_GET[“GOTMLS_traces”])
    unset($_SESSION[“GOTMLS_trace_includes”][$trace]);
    die(print_r(array(““.substr($_SESSION[“GOTMLS_traces”], 0, 10).”

    ",$_SESSION["GOTMLS_trace_includes"],"
    ")));
    	}
    }
Viewing 13 replies - 1 through 13 (of 13 total)
  • Thread Starter crmacdonald1

    (@crmacdonald1)

    _________________________________________________________________
    _________________________________________________________________

    …\wp-content\plugins\jetpack\_inc\postmessage.js

    /**
    The MIT License

    Copyright (c) 2010 Daniel Park (https://metaweb.com, https://postmessage.freebaseapps.com)

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the “Software”), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
    **/
    var NO_JQUERY = {};
    (function(window, $, undefined) {

    if (!(“console” in window)) {
    var c = window.console = {};
    c.log = c.warn = c.error = c.debug = function(){};
    }

    if ($ === NO_JQUERY) {
    // jQuery is optional
    $ = {
    fn: {},
    extend: function() {
    var a = arguments[0];
    for (var i=1,len=arguments.length; i<len; i++) {
    var b = arguments[i];
    for (var prop in b) {
    a[prop] = b[prop];
    }
    }
    return a;
    }
    };
    }

    $.fn.pm = function() {
    console.log(“usage: \nto send: $.pm(options)\nto receive: $.pm.bind(type, fn, [origin])”);
    return this;
    };

    // send postmessage
    $.pm = window.pm = function(options) {
    pm.send(options);
    };

    // bind postmessage handler
    $.pm.bind = window.pm.bind = function(type, fn, origin, hash, async_reply) {
    pm.bind(type, fn, origin, hash, async_reply === true);
    };

    // unbind postmessage handler
    $.pm.unbind = window.pm.unbind = function(type, fn) {
    pm.unbind(type, fn);
    };

    // default postmessage origin on bind
    $.pm.origin = window.pm.origin = null;

    // default postmessage polling if using location hash to pass postmessages
    $.pm.poll = window.pm.poll = 200;

    var pm = {

    send: function(options) {
    var o = $.extend({}, pm.defaults, options),
    target = o.target;
    if (!o.target) {
    console.warn(“postmessage target window required”);
    return;
    }
    if (!o.type) {
    console.warn(“postmessage type required”);
    return;
    }
    var msg = {data:o.data, type:o.type};
    if (o.success) {
    msg.callback = pm._callback(o.success);
    }
    if (o.error) {
    msg.errback = pm._callback(o.error);
    }
    if ((“postMessage” in target) && !o.hash) {
    pm._bind();
    target.postMessage(JSON.stringify(msg), o.origin || ‘*’);
    }
    else {
    pm.hash._bind();
    pm.hash.send(o, msg);
    }
    },

    bind: function(type, fn, origin, hash, async_reply) {
    pm._replyBind ( type, fn, origin, hash, async_reply );
    },

    _replyBind: function(type, fn, origin, hash, isCallback) {
    if ((“postMessage” in window) && !hash) {
    pm._bind();
    }
    else {
    pm.hash._bind();
    }
    var l = pm.data(“listeners.postmessage”);
    if (!l) {
    l = {};
    pm.data(“listeners.postmessage”, l);
    }
    var fns = l[type];
    if (!fns) {
    fns = [];
    l[type] = fns;
    }
    fns.push({fn:fn, callback: isCallback, origin:origin || $.pm.origin});
    },

    unbind: function(type, fn) {
    var l = pm.data(“listeners.postmessage”);
    if (l) {
    if (type) {
    if (fn) {
    // remove specific listener
    var fns = l[type];
    if (fns) {
    var m = [];
    for (var i=0,len=fns.length; i<len; i++) {
    var o = fns[i];
    if (o.fn !== fn) {
    m.push(o);
    }
    }
    l[type] = m;
    }
    }
    else {
    // remove all listeners by type
    delete l[type];
    }
    }
    else {
    // unbind all listeners of all type
    for (var i in l) {
    delete l[i];
    }
    }
    }
    },

    data: function(k, v) {
    if (v === undefined) {
    return pm._data[k];
    }
    pm._data[k] = v;
    return v;
    },

    _data: {},

    _CHARS: ‘0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz’.split(”),

    _random: function() {
    var r = [];
    for (var i=0; i<32; i++) {
    r[i] = pm._CHARS[0 | Math.random() * 32];
    };
    return r.join(“”);
    },

    _callback: function(fn) {
    var cbs = pm.data(“callbacks.postmessage”);
    if (!cbs) {
    cbs = {};
    pm.data(“callbacks.postmessage”, cbs);
    }
    var r = pm._random();
    cbs[r] = fn;
    return r;
    },

    _bind: function() {
    // are we already listening to message events on this w?
    if (!pm.data(“listening.postmessage”)) {
    if (window.addEventListener) {
    window.addEventListener(“message”, pm._dispatch, false);
    }
    else if (window.attachEvent) {
    window.attachEvent(“onmessage”, pm._dispatch);
    }
    pm.data(“listening.postmessage”, 1);
    }
    },

    _dispatch: function(e) {
    //console.log(“$.pm.dispatch”, e, this);
    try {
    var msg = JSON.parse(e.data);
    }
    catch (ex) {
    //console.warn(“postmessage data invalid json: “, ex); //message wasn’t meant for pm
    return;
    }
    if (!msg.type) {
    //console.warn(“postmessage message type required”); //message wasn’t meant for pm
    return;
    }
    var cbs = pm.data(“callbacks.postmessage”) || {},
    cb = cbs[msg.type];
    if (cb) {
    cb(msg.data);
    }
    else {
    var l = pm.data(“listeners.postmessage”) || {};
    var fns = l[msg.type] || [];
    for (var i=0,len=fns.length; i<len; i++) {
    var o = fns[i];
    if (o.origin && o.origin !== ‘*’ && e.origin !== o.origin) {
    console.warn(“postmessage message origin mismatch”, e.origin, o.origin);
    if (msg.errback) {
    // notify post message errback
    var error = {
    message: “postmessage origin mismatch”,
    origin: [e.origin, o.origin]
    };
    pm.send({target:e.source, data:error, type:msg.errback});
    }
    continue;
    }

    function sendReply ( data ) {
    if (msg.callback) {
    pm.send({target:e.source, data:data, type:msg.callback});
    }
    }

    try {
    if ( o.callback ) {
    o.fn(msg.data, sendReply, e);
    } else {
    sendReply ( o.fn(msg.data, e) );
    }
    }
    catch (ex) {
    if (msg.errback) {
    // notify post message errback
    pm.send({target:e.source, data:ex, type:msg.errback});
    } else {
    throw ex;
    }
    }
    };
    }
    }
    };

    // location hash polling
    pm.hash = {

    send: function(options, msg) {
    //console.log(“hash.send”, target_window, options, msg);
    var target_window = options.target,
    target_url = options.url;
    if (!target_url) {
    console.warn(“postmessage target window url is required”);
    return;
    }
    target_url = pm.hash._url(target_url);
    var source_window,
    source_url = pm.hash._url(window.location.href);
    if (window == target_window.parent) {
    source_window = “parent”;
    }
    else {
    try {
    for (var i=0,len=parent.frames.length; i<len; i++) {
    var f = parent.frames[i];
    if (f == window) {
    source_window = i;
    break;
    }
    };
    }
    catch(ex) {
    // Opera: security error trying to access parent.frames x-origin
    // juse use window.name
    source_window = window.name;
    }
    }
    if (source_window == null) {
    console.warn(“postmessage windows must be direct parent/child windows and the child must be available through the parent window.frames list”);
    return;
    }
    var hashmessage = {
    “x-requested-with”: “postmessage”,
    source: {
    name: source_window,
    url: source_url
    },
    postmessage: msg
    };
    var hash_id = “#x-postmessage-id=” + pm._random();
    target_window.location = target_url + hash_id + encodeURIComponent(JSON.stringify(hashmessage));
    },

    _regex: /^\#x\-postmessage\-id\=(\w{32})/,

    _regex_len: “#x-postmessage-id=”.length + 32,

    _bind: function() {
    // are we already listening to message events on this w?
    if (!pm.data(“polling.postmessage”)) {
    setInterval(function() {
    var hash = “” + window.location.hash,
    m = pm.hash._regex.exec(hash);
    if (m) {
    var id = m[1];
    if (pm.hash._last !== id) {
    pm.hash._last = id;
    pm.hash._dispatch(hash.substring(pm.hash._regex_len));
    }
    }
    }, $.pm.poll || 200);
    pm.data(“polling.postmessage”, 1);
    }
    },

    _dispatch: function(hash) {
    if (!hash) {
    return;
    }
    try {
    hash = JSON.parse(decodeURIComponent(hash));
    if (!(hash[‘x-requested-with’] === ‘postmessage’ &&
    hash.source && hash.source.name != null && hash.source.url && hash.postmessage)) {
    // ignore since hash could’ve come from somewhere else
    return;
    }
    }
    catch (ex) {
    // ignore since hash could’ve come from somewhere else
    return;
    }
    var msg = hash.postmessage,
    cbs = pm.data(“callbacks.postmessage”) || {},
    cb = cbs[msg.type];
    if (cb) {
    cb(msg.data);
    }
    else {
    var source_window;
    if (hash.source.name === “parent”) {
    source_window = window.parent;
    }
    else {
    source_window = window.frames[hash.source.name];
    }
    var l = pm.data(“listeners.postmessage”) || {};
    var fns = l[msg.type] || [];
    for (var i=0,len=fns.length; i<len; i++) {
    var o = fns[i];
    if (o.origin) {
    var origin = /https?\:\/\/[^\/]*/.exec(hash.source.url)[0];
    if (o.origin !== ‘*’ && origin !== o.origin) {
    console.warn(“postmessage message origin mismatch”, origin, o.origin);
    if (msg.errback) {
    // notify post message errback
    var error = {
    message: “postmessage origin mismatch”,
    origin: [origin, o.origin]
    };
    pm.send({target:source_window, data:error, type:msg.errback, hash:true, url:hash.source.url});
    }
    continue;
    }
    }

    function sendReply ( data ) {
    if (msg.callback) {
    pm.send({target:source_window, data:data, type:msg.callback, hash:true, url:hash.source.url});
    }
    }

    try {
    if ( o.callback ) {
    o.fn(msg.data, sendReply);
    } else {
    sendReply ( o.fn(msg.data) );
    }
    }
    catch (ex) {
    if (msg.errback) {
    // notify post message errback
    pm.send({target:source_window, data:ex, type:msg.errback, hash:true, url:hash.source.url});
    } else {
    throw ex;
    }
    }
    };
    }
    },

    _url: function(url) {
    // url minus hash part
    return (“”+url).replace(/#.*$/, “”);
    }

    };

    $.extend(pm, {
    defaults: {
    target: null, /* target window (required) */
    url: null, /* target window url (required if no window.postMessage or hash == true) */
    type: null, /* message type (required) */
    data: null, /* message data (required) */
    success: null, /* success callback (optional) */
    error: null, /* error callback (optional) */
    origin: “*”, /* postmessage origin (optional) */
    hash: false /* use location hash for message passing (optional) */
    }
    });

    })(this, typeof jQuery === “undefined” ? NO_JQUERY : jQuery);

    /**
    * https://www.JSON.org/json2.js
    **/
    if (! (“JSON” in window && window.JSON)){JSON={}}(function(){function f(n){return n<10?”0″+n:n}if(typeof Date.prototype.toJSON!==”function”){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+”-“+f(this.getUTCMonth()+1)+”-“+f(this.getUTCDate())+”T”+f(this.getUTCHours())+”:”+f(this.getUTCMinutes())+”:”+f(this.getUTCSeconds())+”Z”};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\”\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={“\b”:”\\b”,”\t”:”\\t”,”\n”:”\\n”,”\f”:”\\f”,”\r”:”\\r”,'”‘:’\\”‘,”\\”:”\\\\”},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'”‘+string.replace(escapable,function(a){var c=meta[a];return typeof c===”string”?c:”\\u”+(“0000″+a.charCodeAt(0).toString(16)).slice(-4)})+'”‘:'”‘+string+'”‘}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value===”object”&&typeof value.toJSON===”function”){value=value.toJSON(key)}if(typeof rep===”function”){value=rep.call(holder,key,value)}switch(typeof value){case”string”:return quote(value);case”number”:return isFinite(value)?String(value):”null”;case”boolean”:case”null”:return String(value);case”object”:if(!value){return”null”}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)===”[object Array]”){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||”null”}v=partial.length===0?”[]”:gap?”[\n”+gap+partial.join(“,\n”+gap)+”\n”+mind+”]”:”[“+partial.join(“,”)+”]”;gap=mind;return v}if(rep&&typeof rep===”object”){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k===”string”){v=str(k,value);if(v){partial.push(quote(k)+(gap?”: “:”:”)+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?”: “:”:”)+v)}}}}v=partial.length===0?”{}”:gap?”{\n”+gap+partial.join(“,\n”+gap)+”\n”+mind+”}”:”{“+partial.join(“,”)+”}”;gap=mind;return v}}if(typeof JSON.stringify!==”function”){JSON.stringify=function(value,replacer,space){var i;gap=””;indent=””;if(typeof space===”number”){for(i=0;i<space;i+=1){indent+=” “}}else{if(typeof space===”string”){indent=space}}rep=replacer;if(replacer&&typeof replacer!==”function”&&(typeof replacer!==”object”||typeof replacer.length!==”number”)){throw new Error(“JSON.stringify”)}return str(“”,{“”:value})}}if(typeof JSON.parse!==”function”){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value===”object”){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return”\\u”+(“0000″+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:[“\\\/bfnrt]|u[0-9a-fA-F]{4})/g,”@”).replace(/”[^”\\\n\r]*”|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,”]”).replace(/(?:^|:|,)(?:\s*\[)+/g,””))){j=eval(“(“+text+”)”);return typeof reviver===”function”?walk({“”:j},””):j}throw new SyntaxError(“JSON.parse”)}}}());

    ____________________________________________________________________
    ____________________________________________________________________

    Thread Starter crmacdonald1

    (@crmacdonald1)

    _________________________________________________________________
    _________________________________________________________________

    …\wp-content\plugins\jetpack\modules\infinite-scroll\infinity.js

    (function($){ // Open closure

    // Local vars
    var Scroller, ajaxurl, stats, type, text, totop, timer;

    // IE requires special handling
    var isIE = ( -1 != navigator.userAgent.search( ‘MSIE’ ) );
    if ( isIE ) {
    var IEVersion = navigator.userAgent.match(/MSIE\s?(\d+)\.?\d*;/);
    var IEVersion = parseInt( IEVersion[1] );
    }

    /**
    * Loads new posts when users scroll near the bottom of the page.
    */
    Scroller = function( settings ) {
    var self = this;

    // Initialize our variables
    this.id = settings.id;
    this.body = $( document.body );
    this.window = $( window );
    this.element = $( ‘#’ + settings.id );
    this.wrapperClass = settings.wrapper_class;
    this.ready = true;
    this.disabled = false;
    this.page = 1;
    this.offset = settings.offset;
    this.currentday = settings.currentday;
    this.order = settings.order;
    this.throttle = false;
    this.handle = ‘<div id=”infinite-handle”><span>’ + text.replace( ‘\\’, ” ) + ‘</span></div>’;
    this.google_analytics = settings.google_analytics;
    this.history = settings.history;
    this.origURL = window.location.href;

    // Footer settings
    this.footer = $( ‘#infinite-footer’ );
    this.footer.wrap = settings.footer;

    // We have two type of infinite scroll
    // cases ‘scroll’ and ‘click’

    if ( type == ‘scroll’ ) {
    // Bind refresh to the scroll event
    // Throttle to check for such case every 300ms

    // On event the case becomes a fact
    this.window.bind( ‘scroll.infinity’, function() {
    this.throttle = true;
    });

    // Go back top method
    self.gotop();

    setInterval( function() {
    if ( this.throttle ) {
    // Once the case is the case, the action occurs and the fact is no more
    this.throttle = false;
    // Reveal or hide footer
    self.thefooter();
    // Fire the refresh
    self.refresh();
    }
    }, 300 );

    // Ensure that enough posts are loaded to fill the initial viewport, to compensate for short posts and large displays.
    self.ensureFilledViewport();
    this.body.bind( ‘post-load’, { self: self }, self.checkViewportOnLoad );
    } else if ( type == ‘click’ ) {
    this.element.append( self.handle );
    this.element.delegate( ‘#infinite-handle’, ‘click.infinity’, function() {
    // Handle the handle
    $( ‘#infinite-handle’ ).remove();
    // Fire the refresh
    self.refresh();
    });
    }
    };

    /**
    * Check whether we should fetch any additional posts.
    */
    Scroller.prototype.check = function() {
    var bottom = this.window.scrollTop() + this.window.height(),
    threshold = this.element.offset().top + this.element.outerHeight(false) – this.window.height();

    threshold = Math.round( threshold * 0.75 );

    return bottom > threshold;
    };

    /**
    * Renders the results from a successful response.
    */
    Scroller.prototype.render = function( response ) {
    this.body.addClass( ‘infinity-success’ );

    // Check if we can wrap the html
    this.element.append( response.html );

    this.body.trigger( ‘post-load’ );
    this.ready = true;
    };

    /**
    * Returns the object used to query for new posts.
    */
    Scroller.prototype.query = function() {
    return {
    page : this.page,
    currentday : this.currentday,
    order : this.order,
    scripts : window.infiniteScroll.settings.scripts,
    styles : window.infiniteScroll.settings.styles,
    query_args : window.infiniteScroll.settings.query_args,
    last_post_date : window.infiniteScroll.settings.last_post_date,
    };
    };

    /**
    * Scroll back to top.
    */
    Scroller.prototype.gotop = function() {
    var blog = $( ‘#infinity-blog-title’ );

    blog.attr( ‘title’, totop );

    // Scroll to top on blog title
    blog.bind( ‘click’, function( e ) {
    $( ‘html, body’ ).animate( { scrollTop: 0 }, ‘fast’ );
    e.preventDefault();
    });
    };

    /**
    * The infinite footer.
    */
    Scroller.prototype.thefooter = function() {
    var self = this,
    width;

    // Check if we have an id for the page wrapper
    if ( $.type( this.footer.wrap ) === “string” ) {
    width = $( ‘body #’ + this.footer.wrap ).outerWidth( false );

    // Make the footer match the width of the page
    if ( width > 479 )
    this.footer.find( ‘.container’ ).css( ‘width’, width );
    }

    // Reveal footer
    if ( this.window.scrollTop() >= 350 )
    self.footer.animate( { ‘bottom’: 0 }, ‘fast’ );
    else if ( this.window.scrollTop() < 350 )
    self.footer.animate( { ‘bottom’: ‘-50px’ }, ‘fast’ );
    };

    /**
    * Controls the flow of the refresh. Don’t mess.
    */
    Scroller.prototype.refresh = function() {
    var self = this,
    query, jqxhr, load, loader, color;

    // If we’re disabled, ready, or don’t pass the check, bail.
    if ( this.disabled || ! this.ready || ! this.check() )
    return;

    // Let’s get going — set ready to false to prevent
    // multiple refreshes from occurring at once.
    this.ready = false;

    // Create a loader element to show it’s working.
    loader = ‘<span class=”infinite-loader”></span>’;
    this.element.append( loader );

    loader = this.element.find( ‘.infinite-loader’ );
    color = loader.css( ‘color’ );

    try {
    loader.spin( ‘medium-left’, color );
    } catch ( error ) { }

    // Generate our query vars.
    query = $.extend({
    action: ‘infinite_scroll’
    }, this.query() );

    // Fire the ajax request.
    jqxhr = $.get( infiniteScroll.settings.ajaxurl, query );

    // Allow refreshes to occur again if an error is triggered.
    jqxhr.fail( function() {
    loader.hide();
    self.ready = true;
    });

    // Success handler
    jqxhr.done( function( response ) {
    // On success, let’s hide the loader circle.
    loader.hide();

    // Check for and parse our response.
    if ( ! response )
    return;

    response = $.parseJSON( response );

    if ( ! response || ! response.type )
    return;

    // If there are no remaining posts…
    if ( response.type == ’empty’ ) {
    // Disable the scroller.
    self.disabled = true;
    // Update body classes, allowing the footer to return to static positioning
    self.body.addClass( ‘infinity-end’ ).removeClass( ‘infinity-success’ );

    // If we’ve succeeded…
    } else if ( response.type == ‘success’ ) {
    // If additional scripts are required by the incoming set of posts, parse them
    if ( response.scripts ) {
    $( response.scripts ).each( function() {
    // Add script handle to list of those already parsed
    window.infiniteScroll.settings.scripts.push( this.handle );

    // Output extra data, if present
    if ( this.extra_data ) {
    var data = document.createElement(‘script’),
    dataContent = document.createTextNode( “//<![CDATA[ \n” + this.extra_data + “\n//]]>” );

    data.type = ‘text/javascript’;
    data.appendChild( dataContent );

    document.getElementsByTagName( this.footer ? ‘body’ : ‘head’ )[0].appendChild(data);
    }

    // Build script tag and append to DOM in requested location
    var script = document.createElement(‘script’);
    script.type = ‘text/javascript’;
    script.src = this.src;
    script.id = this.handle;
    document.getElementsByTagName( this.footer ? ‘body’ : ‘head’ )[0].appendChild(script);
    } );
    }

    // If additional stylesheets are required by the incoming set of posts, parse them
    if ( response.styles ) {
    $( response.styles ).each( function() {
    // Add stylesheet handle to list of those already parsed
    window.infiniteScroll.settings.styles.push( this.handle );

    // Build link tag
    var style = document.createElement(‘link’);
    style.rel = ‘stylesheet’;
    style.href = this.src;
    style.id = this.handle + ‘-css’;

    // Destroy link tag if a conditional statement is present and either the browser isn’t IE, or the conditional doesn’t evaluate true
    if ( this.conditional && ( ! isIE || ! eval( this.conditional.replace( /%ver/g, IEVersion ) ) ) )
    var style = false;

    // Append link tag if necessary
    if ( style )
    document.getElementsByTagName(‘head’)[0].appendChild(style);
    } );
    }

    // Increment the page number
    self.page++;

    // Record pageview in WP Stats, if available.
    if ( stats )
    new Image().src = document.location.protocol + ‘//stats.wordpress.com/g.gif?’ + stats + ‘&post=0&baba=’ + Math.random();

    // Add new posts to the postflair object
    if ( ‘object’ == typeof response.postflair && ‘object’ == typeof WPCOM_sharing_counts )
    WPCOM_sharing_counts = $.extend( WPCOM_sharing_counts, response.postflair );

    // Render the results
    self.render.apply( self, arguments );

    // If ‘click’ type and there are still posts to fetch, add back the handle
    if ( type == ‘click’ && !response.lastbatch )
    self.element.append( self.handle );

    // Update currentday to the latest value returned from the server
    if (response.currentday)
    self.currentday = response.currentday;

    // Fire Google Analytics pageview
    if ( self.google_analytics && ‘object’ == typeof _gaq )
    _gaq.push([‘_trackPageview’, self.history.path.replace( /%d/, self.page ) ]);
    }
    });

    return jqxhr;
    };

    /**
    * Trigger IS to load additional posts if the initial posts don’t fill the window.
    * On large displays, or when posts are very short, the viewport may not be filled with posts, so we overcome this by loading additional posts when IS initializes.
    */
    Scroller.prototype.ensureFilledViewport = function() {
    var self = this,
    windowHeight = self.window.height(),
    postsHeight = self.element.height()
    aveSetHeight = 0,
    wrapperQty = 0;

    // Account for situations where postsHeight is 0 because child list elements are floated
    if ( postsHeight === 0 ) {
    $( self.element.selector + ‘ > li’ ).each( function() {
    postsHeight += $( this ).height();
    } );

    if ( postsHeight === 0 ) {
    self.body.unbind( ‘post-load’, self.checkViewportOnLoad );
    return;
    }
    }

    // Calculate average height of a set of posts to prevent more posts than needed from being loaded.
    $( ‘.’ + self.wrapperClass ).each( function() {
    aveSetHeight += $( this ).height();
    wrapperQty++;
    } );

    if ( wrapperQty > 0 )
    aveSetHeight = aveSetHeight / wrapperQty;
    else
    aveSetHeight = 0;

    // Load more posts if space permits, otherwise stop checking for a full viewport
    if ( postsHeight < windowHeight && ( postsHeight + aveSetHeight < windowHeight ) ) {
    self.ready = true;
    self.refresh();
    }
    else {
    self.body.unbind( ‘post-load’, self.checkViewportOnLoad );
    }
    }

    /**
    * Event handler for ensureFilledViewport(), tied to the post-load trigger.
    * Necessary to ensure that the variable this contains the scroller when used in ensureFilledViewport(). Since this function is tied to an event, this becomes the DOM element the event is tied to.
    */
    Scroller.prototype.checkViewportOnLoad = function( ev ) {
    ev.data.self.ensureFilledViewport();
    }

    /**
    * Identify archive page that corresponds to majority of posts shown in the current browser window.
    */
    Scroller.prototype.determineURL = function () {
    var self = window.infiniteScroll.scroller,
    windowTop = $( window ).scrollTop(),
    windowBottom = windowTop + $( window ).height(),
    windowSize = windowBottom – windowTop,
    setsInView = [],
    pageNum = false;

    // Find out which sets are in view
    $( ‘.’ + self.wrapperClass ).each( function() {
    var id = $( this ).attr( ‘id’ ),
    setTop = $( this ).offset().top,
    setHeight = $( this ).outerHeight( false ),
    setBottom = 0,
    setPageNum = $( this ).data( ‘page-num’ );

    // Account for containers that have no height because their children are floated elements.
    if ( 0 == setHeight ) {
    $( ‘> *’, this ).each( function() {
    setHeight += $( this ).outerHeight( false );
    } );
    }

    // Determine position of bottom of set by adding its height to the scroll position of its top.
    setBottom = setTop + setHeight;

    // Populate setsInView object. While this logic could all be combined into a single conditional statement, this is easier to understand.
    if ( setTop < windowTop && setBottom > windowBottom ) { // top of set is above window, bottom is below
    setsInView.push({‘id’: id, ‘top’: setTop, ‘bottom’: setBottom, ‘pageNum’: setPageNum });
    }
    else if( setTop > windowTop && setTop < windowBottom ) { // top of set is between top (gt) and bottom (lt)
    setsInView.push({‘id’: id, ‘top’: setTop, ‘bottom’: setBottom, ‘pageNum’: setPageNum });
    }
    else if( setBottom > windowTop && setBottom < windowBottom ) { // bottom of set is between top (gt) and bottom (lt)
    setsInView.push({‘id’: id, ‘top’: setTop, ‘bottom’: setBottom, ‘pageNum’: setPageNum });
    }
    } );

    // Parse number of sets found in view in an attempt to update the URL to match the set that comprises the majority of the window.
    if ( 0 == setsInView.length ) {
    pageNum = -1;
    }
    else if ( 1 == setsInView.length ) {
    var setData = setsInView.pop();

    // If the first set of IS posts is in the same view as the posts loaded in the template by WordPress, determine how much of the view is comprised of IS-loaded posts
    if ( ( ( windowBottom – setData.top ) / windowSize ) < 0.5 )
    pageNum = -1;
    else
    pageNum = setData.pageNum;
    }
    else {
    var majorityPercentageInView = 0;

    // Identify the IS set that comprises the majority of the current window and set the URL to it.
    $.each( setsInView, function( i, setData ) {
    var topInView = 0,
    bottomInView = 0,
    percentOfView = 0;

    // Figure percentage of view the current set represents
    if ( setData.top > windowTop && setData.top < windowBottom )
    topInView = ( windowBottom – setData.top ) / windowSize;

    if ( setData.bottom > windowTop && setData.bottom < windowBottom )
    bottomInView = ( setData.bottom – windowTop ) / windowSize;

    // Figure out largest percentage of view for current set
    if ( topInView >= bottomInView )
    percentOfView = topInView;
    else if ( bottomInView >= topInView )
    percentOfView = bottomInView;

    // Does current set’s percentage of view supplant the largest previously-found set?
    if ( percentOfView > majorityPercentageInView ) {
    pageNum = setData.pageNum;
    majorityPercentageInView = percentOfView;
    }
    } );
    }

    // If a page number could be determined, update the URL
    // -1 indicates that the original requested URL should be used.
    if ( ‘number’ == typeof pageNum ) {
    if ( pageNum != -1 )
    pageNum++;

    self.updateURL( pageNum );
    }
    }

    /**
    * Update address bar to reflect archive page URL for a given page number.
    * Checks if URL is different to prevent pollution of browser history.
    */
    Scroller.prototype.updateURL = function( page ) {
    var self = this,
    offset = self.offset > 0 ? self.offset – 1 : 0,
    pageSlug = -1 == page ? self.origURL : window.location.protocol + ‘//’ + self.history.host + self.history.path.replace( /%d/, page + offset ) + self.history.parameters;

    if ( window.location.href != pageSlug )
    history.pushState( null, null, pageSlug );
    }

    /**
    * Ready, set, go!
    */
    $( document ).ready( function() {
    // Check for our variables
    if ( ‘object’ != typeof infiniteScroll )
    return;

    // Set ajaxurl (for brevity)
    ajaxurl = infiniteScroll.settings.ajaxurl;

    // Set stats, used for tracking stats
    stats = infiniteScroll.settings.stats;

    // Define what type of infinity we have, grab text for click-handle
    type = infiniteScroll.settings.type;
    text = infiniteScroll.settings.text;
    totop = infiniteScroll.settings.totop;

    // Initialize the scroller (with the ID of the element from the theme)
    infiniteScroll.scroller = new Scroller( infiniteScroll.settings );

    /**
    * Monitor user scroll activity to update URL to correspond to archive page for current set of IS posts
    * IE only supports pushState() in v10 and above, so don’t bother if those conditions aren’t met.
    */
    if ( ! isIE || ( isIE && IEVersion >= 10 ) ) {
    $( window ).bind( ‘scroll’, function() {
    clearTimeout( timer );
    timer = setTimeout( infiniteScroll.scroller.determineURL , 100 );
    });
    }
    });

    })(jQuery); // Close closure

    _________________________________________________________________
    _________________________________________________________________

    Thread Starter crmacdonald1

    (@crmacdonald1)

    _________________________________________________________________
    _________________________________________________________________

    …\wp-content\plugins\jetpack\modules\infinite-scroll\infinity.js

    (function($){ // Open closure

    // Local vars
    var Scroller, ajaxurl, stats, type, text, totop, timer;

    // IE requires special handling
    var isIE = ( -1 != navigator.userAgent.search( ‘MSIE’ ) );
    if ( isIE ) {
    var IEVersion = navigator.userAgent.match(/MSIE\s?(\d+)\.?\d*;/);
    var IEVersion = parseInt( IEVersion[1] );
    }

    /**
    * Loads new posts when users scroll near the bottom of the page.
    */
    Scroller = function( settings ) {
    var self = this;

    // Initialize our variables
    this.id = settings.id;
    this.body = $( document.body );
    this.window = $( window );
    this.element = $( ‘#’ + settings.id );
    this.wrapperClass = settings.wrapper_class;
    this.ready = true;
    this.disabled = false;
    this.page = 1;
    this.offset = settings.offset;
    this.currentday = settings.currentday;
    this.order = settings.order;
    this.throttle = false;
    this.handle = ‘<div id=”infinite-handle”><span>’ + text.replace( ‘\\’, ” ) + ‘</span></div>’;
    this.google_analytics = settings.google_analytics;
    this.history = settings.history;
    this.origURL = window.location.href;

    // Footer settings
    this.footer = $( ‘#infinite-footer’ );
    this.footer.wrap = settings.footer;

    // We have two type of infinite scroll
    // cases ‘scroll’ and ‘click’

    if ( type == ‘scroll’ ) {
    // Bind refresh to the scroll event
    // Throttle to check for such case every 300ms

    // On event the case becomes a fact
    this.window.bind( ‘scroll.infinity’, function() {
    this.throttle = true;
    });

    // Go back top method
    self.gotop();

    setInterval( function() {
    if ( this.throttle ) {
    // Once the case is the case, the action occurs and the fact is no more
    this.throttle = false;
    // Reveal or hide footer
    self.thefooter();
    // Fire the refresh
    self.refresh();
    }
    }, 300 );

    // Ensure that enough posts are loaded to fill the initial viewport, to compensate for short posts and large displays.
    self.ensureFilledViewport();
    this.body.bind( ‘post-load’, { self: self }, self.checkViewportOnLoad );
    } else if ( type == ‘click’ ) {
    this.element.append( self.handle );
    this.element.delegate( ‘#infinite-handle’, ‘click.infinity’, function() {
    // Handle the handle
    $( ‘#infinite-handle’ ).remove();
    // Fire the refresh
    self.refresh();
    });
    }
    };

    /**
    * Check whether we should fetch any additional posts.
    */
    Scroller.prototype.check = function() {
    var bottom = this.window.scrollTop() + this.window.height(),
    threshold = this.element.offset().top + this.element.outerHeight(false) – this.window.height();

    threshold = Math.round( threshold * 0.75 );

    return bottom > threshold;
    };

    /**
    * Renders the results from a successful response.
    */
    Scroller.prototype.render = function( response ) {
    this.body.addClass( ‘infinity-success’ );

    // Check if we can wrap the html
    this.element.append( response.html );

    this.body.trigger( ‘post-load’ );
    this.ready = true;
    };

    /**
    * Returns the object used to query for new posts.
    */
    Scroller.prototype.query = function() {
    return {
    page : this.page,
    currentday : this.currentday,
    order : this.order,
    scripts : window.infiniteScroll.settings.scripts,
    styles : window.infiniteScroll.settings.styles,
    query_args : window.infiniteScroll.settings.query_args,
    last_post_date : window.infiniteScroll.settings.last_post_date,
    };
    };

    /**
    * Scroll back to top.
    */
    Scroller.prototype.gotop = function() {
    var blog = $( ‘#infinity-blog-title’ );

    blog.attr( ‘title’, totop );

    // Scroll to top on blog title
    blog.bind( ‘click’, function( e ) {
    $( ‘html, body’ ).animate( { scrollTop: 0 }, ‘fast’ );
    e.preventDefault();
    });
    };

    /**
    * The infinite footer.
    */
    Scroller.prototype.thefooter = function() {
    var self = this,
    width;

    // Check if we have an id for the page wrapper
    if ( $.type( this.footer.wrap ) === “string” ) {
    width = $( ‘body #’ + this.footer.wrap ).outerWidth( false );

    // Make the footer match the width of the page
    if ( width > 479 )
    this.footer.find( ‘.container’ ).css( ‘width’, width );
    }

    // Reveal footer
    if ( this.window.scrollTop() >= 350 )
    self.footer.animate( { ‘bottom’: 0 }, ‘fast’ );
    else if ( this.window.scrollTop() < 350 )
    self.footer.animate( { ‘bottom’: ‘-50px’ }, ‘fast’ );
    };

    /**
    * Controls the flow of the refresh. Don’t mess.
    */
    Scroller.prototype.refresh = function() {
    var self = this,
    query, jqxhr, load, loader, color;

    // If we’re disabled, ready, or don’t pass the check, bail.
    if ( this.disabled || ! this.ready || ! this.check() )
    return;

    // Let’s get going — set ready to false to prevent
    // multiple refreshes from occurring at once.
    this.ready = false;

    // Create a loader element to show it’s working.
    loader = ‘<span class=”infinite-loader”></span>’;
    this.element.append( loader );

    loader = this.element.find( ‘.infinite-loader’ );
    color = loader.css( ‘color’ );

    try {
    loader.spin( ‘medium-left’, color );
    } catch ( error ) { }

    // Generate our query vars.
    query = $.extend({
    action: ‘infinite_scroll’
    }, this.query() );

    // Fire the ajax request.
    jqxhr = $.get( infiniteScroll.settings.ajaxurl, query );

    // Allow refreshes to occur again if an error is triggered.
    jqxhr.fail( function() {
    loader.hide();
    self.ready = true;
    });

    // Success handler
    jqxhr.done( function( response ) {
    // On success, let’s hide the loader circle.
    loader.hide();

    // Check for and parse our response.
    if ( ! response )
    return;

    response = $.parseJSON( response );

    if ( ! response || ! response.type )
    return;

    // If there are no remaining posts…
    if ( response.type == ’empty’ ) {
    // Disable the scroller.
    self.disabled = true;
    // Update body classes, allowing the footer to return to static positioning
    self.body.addClass( ‘infinity-end’ ).removeClass( ‘infinity-success’ );

    // If we’ve succeeded…
    } else if ( response.type == ‘success’ ) {
    // If additional scripts are required by the incoming set of posts, parse them
    if ( response.scripts ) {
    $( response.scripts ).each( function() {
    // Add script handle to list of those already parsed
    window.infiniteScroll.settings.scripts.push( this.handle );

    // Output extra data, if present
    if ( this.extra_data ) {
    var data = document.createElement(‘script’),
    dataContent = document.createTextNode( “//<![CDATA[ \n” + this.extra_data + “\n//]]>” );

    data.type = ‘text/javascript’;
    data.appendChild( dataContent );

    document.getElementsByTagName( this.footer ? ‘body’ : ‘head’ )[0].appendChild(data);
    }

    // Build script tag and append to DOM in requested location
    var script = document.createElement(‘script’);
    script.type = ‘text/javascript’;
    script.src = this.src;
    script.id = this.handle;
    document.getElementsByTagName( this.footer ? ‘body’ : ‘head’ )[0].appendChild(script);
    } );
    }

    // If additional stylesheets are required by the incoming set of posts, parse them
    if ( response.styles ) {
    $( response.styles ).each( function() {
    // Add stylesheet handle to list of those already parsed
    window.infiniteScroll.settings.styles.push( this.handle );

    // Build link tag
    var style = document.createElement(‘link’);
    style.rel = ‘stylesheet’;
    style.href = this.src;
    style.id = this.handle + ‘-css’;

    // Destroy link tag if a conditional statement is present and either the browser isn’t IE, or the conditional doesn’t evaluate true
    if ( this.conditional && ( ! isIE || ! eval( this.conditional.replace( /%ver/g, IEVersion ) ) ) )
    var style = false;

    // Append link tag if necessary
    if ( style )
    document.getElementsByTagName(‘head’)[0].appendChild(style);
    } );
    }

    // Increment the page number
    self.page++;

    // Record pageview in WP Stats, if available.
    if ( stats )
    new Image().src = document.location.protocol + ‘//stats.wordpress.com/g.gif?’ + stats + ‘&post=0&baba=’ + Math.random();

    // Add new posts to the postflair object
    if ( ‘object’ == typeof response.postflair && ‘object’ == typeof WPCOM_sharing_counts )
    WPCOM_sharing_counts = $.extend( WPCOM_sharing_counts, response.postflair );

    // Render the results
    self.render.apply( self, arguments );

    // If ‘click’ type and there are still posts to fetch, add back the handle
    if ( type == ‘click’ && !response.lastbatch )
    self.element.append( self.handle );

    // Update currentday to the latest value returned from the server
    if (response.currentday)
    self.currentday = response.currentday;

    // Fire Google Analytics pageview
    if ( self.google_analytics && ‘object’ == typeof _gaq )
    _gaq.push([‘_trackPageview’, self.history.path.replace( /%d/, self.page ) ]);
    }
    });

    return jqxhr;
    };

    /**
    * Trigger IS to load additional posts if the initial posts don’t fill the window.
    * On large displays, or when posts are very short, the viewport may not be filled with posts, so we overcome this by loading additional posts when IS initializes.
    */
    Scroller.prototype.ensureFilledViewport = function() {
    var self = this,
    windowHeight = self.window.height(),
    postsHeight = self.element.height()
    aveSetHeight = 0,
    wrapperQty = 0;

    // Account for situations where postsHeight is 0 because child list elements are floated
    if ( postsHeight === 0 ) {
    $( self.element.selector + ‘ > li’ ).each( function() {
    postsHeight += $( this ).height();
    } );

    if ( postsHeight === 0 ) {
    self.body.unbind( ‘post-load’, self.checkViewportOnLoad );
    return;
    }
    }

    // Calculate average height of a set of posts to prevent more posts than needed from being loaded.
    $( ‘.’ + self.wrapperClass ).each( function() {
    aveSetHeight += $( this ).height();
    wrapperQty++;
    } );

    if ( wrapperQty > 0 )
    aveSetHeight = aveSetHeight / wrapperQty;
    else
    aveSetHeight = 0;

    // Load more posts if space permits, otherwise stop checking for a full viewport
    if ( postsHeight < windowHeight && ( postsHeight + aveSetHeight < windowHeight ) ) {
    self.ready = true;
    self.refresh();
    }
    else {
    self.body.unbind( ‘post-load’, self.checkViewportOnLoad );
    }
    }

    /**
    * Event handler for ensureFilledViewport(), tied to the post-load trigger.
    * Necessary to ensure that the variable this contains the scroller when used in ensureFilledViewport(). Since this function is tied to an event, this becomes the DOM element the event is tied to.
    */
    Scroller.prototype.checkViewportOnLoad = function( ev ) {
    ev.data.self.ensureFilledViewport();
    }

    /**
    * Identify archive page that corresponds to majority of posts shown in the current browser window.
    */
    Scroller.prototype.determineURL = function () {
    var self = window.infiniteScroll.scroller,
    windowTop = $( window ).scrollTop(),
    windowBottom = windowTop + $( window ).height(),
    windowSize = windowBottom – windowTop,
    setsInView = [],
    pageNum = false;

    // Find out which sets are in view
    $( ‘.’ + self.wrapperClass ).each( function() {
    var id = $( this ).attr( ‘id’ ),
    setTop = $( this ).offset().top,
    setHeight = $( this ).outerHeight( false ),
    setBottom = 0,
    setPageNum = $( this ).data( ‘page-num’ );

    // Account for containers that have no height because their children are floated elements.
    if ( 0 == setHeight ) {
    $( ‘> *’, this ).each( function() {
    setHeight += $( this ).outerHeight( false );
    } );
    }

    // Determine position of bottom of set by adding its height to the scroll position of its top.
    setBottom = setTop + setHeight;

    // Populate setsInView object. While this logic could all be combined into a single conditional statement, this is easier to understand.
    if ( setTop < windowTop && setBottom > windowBottom ) { // top of set is above window, bottom is below
    setsInView.push({‘id’: id, ‘top’: setTop, ‘bottom’: setBottom, ‘pageNum’: setPageNum });
    }
    else if( setTop > windowTop && setTop < windowBottom ) { // top of set is between top (gt) and bottom (lt)
    setsInView.push({‘id’: id, ‘top’: setTop, ‘bottom’: setBottom, ‘pageNum’: setPageNum });
    }
    else if( setBottom > windowTop && setBottom < windowBottom ) { // bottom of set is between top (gt) and bottom (lt)
    setsInView.push({‘id’: id, ‘top’: setTop, ‘bottom’: setBottom, ‘pageNum’: setPageNum });
    }
    } );

    // Parse number of sets found in view in an attempt to update the URL to match the set that comprises the majority of the window.
    if ( 0 == setsInView.length ) {
    pageNum = -1;
    }
    else if ( 1 == setsInView.length ) {
    var setData = setsInView.pop();

    // If the first set of IS posts is in the same view as the posts loaded in the template by WordPress, determine how much of the view is comprised of IS-loaded posts
    if ( ( ( windowBottom – setData.top ) / windowSize ) < 0.5 )
    pageNum = -1;
    else
    pageNum = setData.pageNum;
    }
    else {
    var majorityPercentageInView = 0;

    // Identify the IS set that comprises the majority of the current window and set the URL to it.
    $.each( setsInView, function( i, setData ) {
    var topInView = 0,
    bottomInView = 0,
    percentOfView = 0;

    // Figure percentage of view the current set represents
    if ( setData.top > windowTop && setData.top < windowBottom )
    topInView = ( windowBottom – setData.top ) / windowSize;

    if ( setData.bottom > windowTop && setData.bottom < windowBottom )
    bottomInView = ( setData.bottom – windowTop ) / windowSize;

    // Figure out largest percentage of view for current set
    if ( topInView >= bottomInView )
    percentOfView = topInView;
    else if ( bottomInView >= topInView )
    percentOfView = bottomInView;

    // Does current set’s percentage of view supplant the largest previously-found set?
    if ( percentOfView > majorityPercentageInView ) {
    pageNum = setData.pageNum;
    majorityPercentageInView = percentOfView;
    }
    } );
    }

    // If a page number could be determined, update the URL
    // -1 indicates that the original requested URL should be used.
    if ( ‘number’ == typeof pageNum ) {
    if ( pageNum != -1 )
    pageNum++;

    self.updateURL( pageNum );
    }
    }

    /**
    * Update address bar to reflect archive page URL for a given page number.
    * Checks if URL is different to prevent pollution of browser history.
    */
    Scroller.prototype.updateURL = function( page ) {
    var self = this,
    offset = self.offset > 0 ? self.offset – 1 : 0,
    pageSlug = -1 == page ? self.origURL : window.location.protocol + ‘//’ + self.history.host + self.history.path.replace( /%d/, page + offset ) + self.history.parameters;

    if ( window.location.href != pageSlug )
    history.pushState( null, null, pageSlug );
    }

    /**
    * Ready, set, go!
    */
    $( document ).ready( function() {
    // Check for our variables
    if ( ‘object’ != typeof infiniteScroll )
    return;

    // Set ajaxurl (for brevity)
    ajaxurl = infiniteScroll.settings.ajaxurl;

    // Set stats, used for tracking stats
    stats = infiniteScroll.settings.stats;

    // Define what type of infinity we have, grab text for click-handle
    type = infiniteScroll.settings.type;
    text = infiniteScroll.settings.text;
    totop = infiniteScroll.settings.totop;

    // Initialize the scroller (with the ID of the element from the theme)
    infiniteScroll.scroller = new Scroller( infiniteScroll.settings );

    /**
    * Monitor user scroll activity to update URL to correspond to archive page for current set of IS posts
    * IE only supports pushState() in v10 and above, so don’t bother if those conditions aren’t met.
    */
    if ( ! isIE || ( isIE && IEVersion >= 10 ) ) {
    $( window ).bind( ‘scroll’, function() {
    clearTimeout( timer );
    timer = setTimeout( infiniteScroll.scroller.determineURL , 100 );
    });
    }
    });

    })(jQuery); // Close closure

    _________________________________________________________________
    _________________________________________________________________

    Thread Starter crmacdonald1

    (@crmacdonald1)

    _________________________________________________________________
    _________________________________________________________________

    …\wp-content\plugins\jetpack\modules\infinite-scroll\infinity.js

    (function($){ // Open closure

    // Local vars
    var Scroller, ajaxurl, stats, type, text, totop, timer;

    // IE requires special handling
    var isIE = ( -1 != navigator.userAgent.search( ‘MSIE’ ) );
    if ( isIE ) {
    var IEVersion = navigator.userAgent.match(/MSIE\s?(\d+)\.?\d*;/);
    var IEVersion = parseInt( IEVersion[1] );
    }

    /**
    * Loads new posts when users scroll near the bottom of the page.
    */
    Scroller = function( settings ) {
    var self = this;

    // Initialize our variables
    this.id = settings.id;
    this.body = $( document.body );
    this.window = $( window );
    this.element = $( ‘#’ + settings.id );
    this.wrapperClass = settings.wrapper_class;
    this.ready = true;
    this.disabled = false;
    this.page = 1;
    this.offset = settings.offset;
    this.currentday = settings.currentday;
    this.order = settings.order;
    this.throttle = false;
    this.handle = ‘<div id=”infinite-handle”><span>’ + text.replace( ‘\\’, ” ) + ‘</span></div>’;
    this.google_analytics = settings.google_analytics;
    this.history = settings.history;
    this.origURL = window.location.href;

    // Footer settings
    this.footer = $( ‘#infinite-footer’ );
    this.footer.wrap = settings.footer;

    // We have two type of infinite scroll
    // cases ‘scroll’ and ‘click’

    if ( type == ‘scroll’ ) {
    // Bind refresh to the scroll event
    // Throttle to check for such case every 300ms

    // On event the case becomes a fact
    this.window.bind( ‘scroll.infinity’, function() {
    this.throttle = true;
    });

    // Go back top method
    self.gotop();

    setInterval( function() {
    if ( this.throttle ) {
    // Once the case is the case, the action occurs and the fact is no more
    this.throttle = false;
    // Reveal or hide footer
    self.thefooter();
    // Fire the refresh
    self.refresh();
    }
    }, 300 );

    // Ensure that enough posts are loaded to fill the initial viewport, to compensate for short posts and large displays.
    self.ensureFilledViewport();
    this.body.bind( ‘post-load’, { self: self }, self.checkViewportOnLoad );
    } else if ( type == ‘click’ ) {
    this.element.append( self.handle );
    this.element.delegate( ‘#infinite-handle’, ‘click.infinity’, function() {
    // Handle the handle
    $( ‘#infinite-handle’ ).remove();
    // Fire the refresh
    self.refresh();
    });
    }
    };

    /**
    * Check whether we should fetch any additional posts.
    */
    Scroller.prototype.check = function() {
    var bottom = this.window.scrollTop() + this.window.height(),
    threshold = this.element.offset().top + this.element.outerHeight(false) – this.window.height();

    threshold = Math.round( threshold * 0.75 );

    return bottom > threshold;
    };

    /**
    * Renders the results from a successful response.
    */
    Scroller.prototype.render = function( response ) {
    this.body.addClass( ‘infinity-success’ );

    // Check if we can wrap the html
    this.element.append( response.html );

    this.body.trigger( ‘post-load’ );
    this.ready = true;
    };

    /**
    * Returns the object used to query for new posts.
    */
    Scroller.prototype.query = function() {
    return {
    page : this.page,
    currentday : this.currentday,
    order : this.order,
    scripts : window.infiniteScroll.settings.scripts,
    styles : window.infiniteScroll.settings.styles,
    query_args : window.infiniteScroll.settings.query_args,
    last_post_date : window.infiniteScroll.settings.last_post_date,
    };
    };

    /**
    * Scroll back to top.
    */
    Scroller.prototype.gotop = function() {
    var blog = $( ‘#infinity-blog-title’ );

    blog.attr( ‘title’, totop );

    // Scroll to top on blog title
    blog.bind( ‘click’, function( e ) {
    $( ‘html, body’ ).animate( { scrollTop: 0 }, ‘fast’ );
    e.preventDefault();
    });
    };

    /**
    * The infinite footer.
    */
    Scroller.prototype.thefooter = function() {
    var self = this,
    width;

    // Check if we have an id for the page wrapper
    if ( $.type( this.footer.wrap ) === “string” ) {
    width = $( ‘body #’ + this.footer.wrap ).outerWidth( false );

    // Make the footer match the width of the page
    if ( width > 479 )
    this.footer.find( ‘.container’ ).css( ‘width’, width );
    }

    // Reveal footer
    if ( this.window.scrollTop() >= 350 )
    self.footer.animate( { ‘bottom’: 0 }, ‘fast’ );
    else if ( this.window.scrollTop() < 350 )
    self.footer.animate( { ‘bottom’: ‘-50px’ }, ‘fast’ );
    };

    /**
    * Controls the flow of the refresh. Don’t mess.
    */
    Scroller.prototype.refresh = function() {
    var self = this,
    query, jqxhr, load, loader, color;

    // If we’re disabled, ready, or don’t pass the check, bail.
    if ( this.disabled || ! this.ready || ! this.check() )
    return;

    // Let’s get going — set ready to false to prevent
    // multiple refreshes from occurring at once.
    this.ready = false;

    // Create a loader element to show it’s working.
    loader = ‘<span class=”infinite-loader”></span>’;
    this.element.append( loader );

    loader = this.element.find( ‘.infinite-loader’ );
    color = loader.css( ‘color’ );

    try {
    loader.spin( ‘medium-left’, color );
    } catch ( error ) { }

    // Generate our query vars.
    query = $.extend({
    action: ‘infinite_scroll’
    }, this.query() );

    // Fire the ajax request.
    jqxhr = $.get( infiniteScroll.settings.ajaxurl, query );

    // Allow refreshes to occur again if an error is triggered.
    jqxhr.fail( function() {
    loader.hide();
    self.ready = true;
    });

    // Success handler
    jqxhr.done( function( response ) {
    // On success, let’s hide the loader circle.
    loader.hide();

    // Check for and parse our response.
    if ( ! response )
    return;

    response = $.parseJSON( response );

    if ( ! response || ! response.type )
    return;

    // If there are no remaining posts…
    if ( response.type == ’empty’ ) {
    // Disable the scroller.
    self.disabled = true;
    // Update body classes, allowing the footer to return to static positioning
    self.body.addClass( ‘infinity-end’ ).removeClass( ‘infinity-success’ );

    // If we’ve succeeded…
    } else if ( response.type == ‘success’ ) {
    // If additional scripts are required by the incoming set of posts, parse them
    if ( response.scripts ) {
    $( response.scripts ).each( function() {
    // Add script handle to list of those already parsed
    window.infiniteScroll.settings.scripts.push( this.handle );

    // Output extra data, if present
    if ( this.extra_data ) {
    var data = document.createElement(‘script’),
    dataContent = document.createTextNode( “//<![CDATA[ \n” + this.extra_data + “\n//]]>” );

    data.type = ‘text/javascript’;
    data.appendChild( dataContent );

    document.getElementsByTagName( this.footer ? ‘body’ : ‘head’ )[0].appendChild(data);
    }

    // Build script tag and append to DOM in requested location
    var script = document.createElement(‘script’);
    script.type = ‘text/javascript’;
    script.src = this.src;
    script.id = this.handle;
    document.getElementsByTagName( this.footer ? ‘body’ : ‘head’ )[0].appendChild(script);
    } );
    }

    // If additional stylesheets are required by the incoming set of posts, parse them
    if ( response.styles ) {
    $( response.styles ).each( function() {
    // Add stylesheet handle to list of those already parsed
    window.infiniteScroll.settings.styles.push( this.handle );

    // Build link tag
    var style = document.createElement(‘link’);
    style.rel = ‘stylesheet’;
    style.href = this.src;
    style.id = this.handle + ‘-css’;

    // Destroy link tag if a conditional statement is present and either the browser isn’t IE, or the conditional doesn’t evaluate true
    if ( this.conditional && ( ! isIE || ! eval( this.conditional.replace( /%ver/g, IEVersion ) ) ) )
    var style = false;

    // Append link tag if necessary
    if ( style )
    document.getElementsByTagName(‘head’)[0].appendChild(style);
    } );
    }

    // Increment the page number
    self.page++;

    // Record pageview in WP Stats, if available.
    if ( stats )
    new Image().src = document.location.protocol + ‘//stats.wordpress.com/g.gif?’ + stats + ‘&post=0&baba=’ + Math.random();

    // Add new posts to the postflair object
    if ( ‘object’ == typeof response.postflair && ‘object’ == typeof WPCOM_sharing_counts )
    WPCOM_sharing_counts = $.extend( WPCOM_sharing_counts, response.postflair );

    // Render the results
    self.render.apply( self, arguments );

    // If ‘click’ type and there are still posts to fetch, add back the handle
    if ( type == ‘click’ && !response.lastbatch )
    self.element.append( self.handle );

    // Update currentday to the latest value returned from the server
    if (response.currentday)
    self.currentday = response.currentday;

    // Fire Google Analytics pageview
    if ( self.google_analytics && ‘object’ == typeof _gaq )
    _gaq.push([‘_trackPageview’, self.history.path.replace( /%d/, self.page ) ]);
    }
    });

    return jqxhr;
    };

    /**
    * Trigger IS to load additional posts if the initial posts don’t fill the window.
    * On large displays, or when posts are very short, the viewport may not be filled with posts, so we overcome this by loading additional posts when IS initializes.
    */
    Scroller.prototype.ensureFilledViewport = function() {
    var self = this,
    windowHeight = self.window.height(),
    postsHeight = self.element.height()
    aveSetHeight = 0,
    wrapperQty = 0;

    // Account for situations where postsHeight is 0 because child list elements are floated
    if ( postsHeight === 0 ) {
    $( self.element.selector + ‘ > li’ ).each( function() {
    postsHeight += $( this ).height();
    } );

    if ( postsHeight === 0 ) {
    self.body.unbind( ‘post-load’, self.checkViewportOnLoad );
    return;
    }
    }

    // Calculate average height of a set of posts to prevent more posts than needed from being loaded.
    $( ‘.’ + self.wrapperClass ).each( function() {
    aveSetHeight += $( this ).height();
    wrapperQty++;
    } );

    if ( wrapperQty > 0 )
    aveSetHeight = aveSetHeight / wrapperQty;
    else
    aveSetHeight = 0;

    // Load more posts if space permits, otherwise stop checking for a full viewport
    if ( postsHeight < windowHeight && ( postsHeight + aveSetHeight < windowHeight ) ) {
    self.ready = true;
    self.refresh();
    }
    else {
    self.body.unbind( ‘post-load’, self.checkViewportOnLoad );
    }
    }

    /**
    * Event handler for ensureFilledViewport(), tied to the post-load trigger.
    * Necessary to ensure that the variable this contains the scroller when used in ensureFilledViewport(). Since this function is tied to an event, this becomes the DOM element the event is tied to.
    */
    Scroller.prototype.checkViewportOnLoad = function( ev ) {
    ev.data.self.ensureFilledViewport();
    }

    /**
    * Identify archive page that corresponds to majority of posts shown in the current browser window.
    */
    Scroller.prototype.determineURL = function () {
    var self = window.infiniteScroll.scroller,
    windowTop = $( window ).scrollTop(),
    windowBottom = windowTop + $( window ).height(),
    windowSize = windowBottom – windowTop,
    setsInView = [],
    pageNum = false;

    // Find out which sets are in view
    $( ‘.’ + self.wrapperClass ).each( function() {
    var id = $( this ).attr( ‘id’ ),
    setTop = $( this ).offset().top,
    setHeight = $( this ).outerHeight( false ),
    setBottom = 0,
    setPageNum = $( this ).data( ‘page-num’ );

    // Account for containers that have no height because their children are floated elements.
    if ( 0 == setHeight ) {
    $( ‘> *’, this ).each( function() {
    setHeight += $( this ).outerHeight( false );
    } );
    }

    // Determine position of bottom of set by adding its height to the scroll position of its top.
    setBottom = setTop + setHeight;

    // Populate setsInView object. While this logic could all be combined into a single conditional statement, this is easier to understand.
    if ( setTop < windowTop && setBottom > windowBottom ) { // top of set is above window, bottom is below
    setsInView.push({‘id’: id, ‘top’: setTop, ‘bottom’: setBottom, ‘pageNum’: setPageNum });
    }
    else if( setTop > windowTop && setTop < windowBottom ) { // top of set is between top (gt) and bottom (lt)
    setsInView.push({‘id’: id, ‘top’: setTop, ‘bottom’: setBottom, ‘pageNum’: setPageNum });
    }
    else if( setBottom > windowTop && setBottom < windowBottom ) { // bottom of set is between top (gt) and bottom (lt)
    setsInView.push({‘id’: id, ‘top’: setTop, ‘bottom’: setBottom, ‘pageNum’: setPageNum });
    }
    } );

    // Parse number of sets found in view in an attempt to update the URL to match the set that comprises the majority of the window.
    if ( 0 == setsInView.length ) {
    pageNum = -1;
    }
    else if ( 1 == setsInView.length ) {
    var setData = setsInView.pop();

    // If the first set of IS posts is in the same view as the posts loaded in the template by WordPress, determine how much of the view is comprised of IS-loaded posts
    if ( ( ( windowBottom – setData.top ) / windowSize ) < 0.5 )
    pageNum = -1;
    else
    pageNum = setData.pageNum;
    }
    else {
    var majorityPercentageInView = 0;

    // Identify the IS set that comprises the majority of the current window and set the URL to it.
    $.each( setsInView, function( i, setData ) {
    var topInView = 0,
    bottomInView = 0,
    percentOfView = 0;

    // Figure percentage of view the current set represents
    if ( setData.top > windowTop && setData.top < windowBottom )
    topInView = ( windowBottom – setData.top ) / windowSize;

    if ( setData.bottom > windowTop && setData.bottom < windowBottom )
    bottomInView = ( setData.bottom – windowTop ) / windowSize;

    // Figure out largest percentage of view for current set
    if ( topInView >= bottomInView )
    percentOfView = topInView;
    else if ( bottomInView >= topInView )
    percentOfView = bottomInView;

    // Does current set’s percentage of view supplant the largest previously-found set?
    if ( percentOfView > majorityPercentageInView ) {
    pageNum = setData.pageNum;
    majorityPercentageInView = percentOfView;
    }
    } );
    }

    // If a page number could be determined, update the URL
    // -1 indicates that the original requested URL should be used.
    if ( ‘number’ == typeof pageNum ) {
    if ( pageNum != -1 )
    pageNum++;

    self.updateURL( pageNum );
    }
    }

    /**
    * Update address bar to reflect archive page URL for a given page number.
    * Checks if URL is different to prevent pollution of browser history.
    */
    Scroller.prototype.updateURL = function( page ) {
    var self = this,
    offset = self.offset > 0 ? self.offset – 1 : 0,
    pageSlug = -1 == page ? self.origURL : window.location.protocol + ‘//’ + self.history.host + self.history.path.replace( /%d/, page + offset ) + self.history.parameters;

    if ( window.location.href != pageSlug )
    history.pushState( null, null, pageSlug );
    }

    /**
    * Ready, set, go!
    */
    $( document ).ready( function() {
    // Check for our variables
    if ( ‘object’ != typeof infiniteScroll )
    return;

    // Set ajaxurl (for brevity)
    ajaxurl = infiniteScroll.settings.ajaxurl;

    // Set stats, used for tracking stats
    stats = infiniteScroll.settings.stats;

    // Define what type of infinity we have, grab text for click-handle
    type = infiniteScroll.settings.type;
    text = infiniteScroll.settings.text;
    totop = infiniteScroll.settings.totop;

    // Initialize the scroller (with the ID of the element from the theme)
    infiniteScroll.scroller = new Scroller( infiniteScroll.settings );

    /**
    * Monitor user scroll activity to update URL to correspond to archive page for current set of IS posts
    * IE only supports pushState() in v10 and above, so don’t bother if those conditions aren’t met.
    */
    if ( ! isIE || ( isIE && IEVersion >= 10 ) ) {
    $( window ).bind( ‘scroll’, function() {
    clearTimeout( timer );
    timer = setTimeout( infiniteScroll.scroller.determineURL , 100 );
    });
    }
    });

    })(jQuery); // Close closure

    ________________________________________________________________
    ________________________________________________________________

    Thread Starter crmacdonald1

    (@crmacdonald1)

    _________________________________________________________________
    _________________________________________________________________

    …\wp-content\plugins\woocommerce\i18n\makepot\not-gettexted.php

    <?php
    /**
    * Console application, which extracts or replaces strings for
    * translation, which cannot be gettexted
    *
    * @version $Id: not-gettexted.php 19275 2012-02-10 17:47:42Z nacin $
    * @package wordpress-i18n
    * @subpackage tools
    */

    // see: https://php.net/tokenizer
    if ( ! defined(‘T_ML_COMMENT’) )
    define(‘T_ML_COMMENT’, T_COMMENT);
    else
    define(‘T_DOC_COMMENT’, T_ML_COMMENT);

    require_once dirname( __FILE__ ) . ‘/pomo/po.php’;
    require_once dirname( __FILE__ ) . ‘/pomo/mo.php’;

    class NotGettexted {
    var $enable_logging = false;

    var $STAGE_OUTSIDE = 0;
    var $STAGE_START_COMMENT = 1;
    var $STAGE_WHITESPACE_BEFORE = 2;
    var $STAGE_STRING = 3;
    var $STAGE_WHITESPACE_AFTER = 4;
    var $STAGE_END_COMMENT = 4;

    var $commands = array(‘extract’ => ‘command_extract’, ‘replace’ => ‘command_replace’ );

    function logmsg() {
    $args = func_get_args();
    if ($this->enable_logging) error_log(implode(‘ ‘, $args));
    }

    function stderr($msg, $nl=true) {
    fwrite(STDERR, $msg.($nl? “\n” : “”));
    }

    function cli_die($msg) {
    $this->stderr($msg);
    exit(1);
    }

    function unchanged_token($token, $s=”) {
    return is_array($token)? $token[1] : $token;
    }

    function ignore_token($token, $s=”) {
    return ”;
    }

    function list_php_files($dir) {
    $files = array();
    $items = scandir( $dir );
    foreach ( (array) $items as $item ) {
    $full_item = $dir . ‘/’ . $item;
    if (‘.’ == $item || ‘..’ == $item)
    continue;
    if (‘.php’ == substr($item, -4))
    $files[] = $full_item;
    if (is_dir($full_item))
    $files += array_merge($files, NotGettexted::list_php_files($full_item, $files));
    }
    return $files;
    }

    function make_string_aggregator($global_array_name, $filename) {
    $a = $global_array_name;
    return create_function(‘$string, $comment_id, $line_number’, ‘global $’.$a.’; $’.$a.'[] = array($string, $comment_id, ‘.var_export($filename, true).’, $line_number);’);
    }

    function make_mo_replacer($global_mo_name) {
    $m = $global_mo_name;
    return create_function(‘$token, $string’, ‘global $’.$m.’; return var_export($’.$m.’->translate($string), true);’);
    }

    function walk_tokens(&$tokens, $string_action, $other_action, $register_action=null) {

    $current_comment_id = ”;
    $current_string = ”;
    $current_string_line = 0;

    $result = ”;
    $line = 1;

    foreach($tokens as $token) {
    if (is_array($token)) {
    list($id, $text) = $token;
    $line += substr_count($text, “\n”);
    if ((T_ML_COMMENT == $id || T_COMMENT == $id) && preg_match(‘|/\*\s*(/?WP_I18N_[a-z_]+)\s*\*/|i’, $text, $matches)) {
    if ($this->STAGE_OUTSIDE == $stage) {
    $stage = $this->STAGE_START_COMMENT;
    $current_comment_id = $matches[1];
    $this->logmsg(‘start comment’, $current_comment_id);
    $result .= call_user_func($other_action, $token);
    continue;
    }
    if ($this->STAGE_START_COMMENT <= $stage && $stage <= $this->STAGE_WHITESPACE_AFTER && ‘/’.$current_comment_id == $matches[1]) {
    $stage = $this->STAGE_END_COMMENT;
    $this->logmsg(‘end comment’, $current_comment_id);
    $result .= call_user_func($other_action, $token);
    if (!is_null($register_action)) call_user_func($register_action, $current_string, $current_comment_id, $current_string_line);
    continue;
    }
    } else if (T_CONSTANT_ENCAPSED_STRING == $id) {
    if ($this->STAGE_START_COMMENT <= $stage && $stage < $this->STAGE_WHITESPACE_AFTER) {
    eval(‘$current_string=’.$text.’;’);
    $this->logmsg(‘string’, $current_string);
    $current_string_line = $line;
    $result .= call_user_func($string_action, $token, $current_string);
    continue;
    }
    } else if (T_WHITESPACE == $id) {
    if ($this->STAGE_START_COMMENT <= $stage && $stage < $this->STAGE_STRING) {
    $stage = $this->STAGE_WHITESPACE_BEFORE;
    $this->logmsg(‘whitespace before’);
    $result .= call_user_func($other_action, $token);
    continue;
    }
    if ($this->STAGE_STRING < $stage && $stage < $this->STAGE_END_COMMENT) {
    $stage = $this->STAGE_WHITESPACE_AFTER;
    $this->logmsg(‘whitespace after’);
    $result .= call_user_func($other_action, $token);
    continue;
    }
    }
    }
    $result .= call_user_func($other_action, $token);
    $stage = $this->STAGE_OUTSIDE;
    $current_comment_id = ”;
    $current_string = ”;
    $current_string_line = 0;
    }
    return $result;
    }

    function command_extract() {
    $args = func_get_args();
    $pot_filename = $args[0];
    if (isset($args[1]) && is_array($args[1]))
    $filenames = $args[1];
    else
    $filenames = array_slice($args, 1);

    $global_name = ‘__entries_’.mt_rand(1, 1000);
    $GLOBALS[$global_name] = array();

    foreach($filenames as $filename) {
    $tokens = token_get_all(file_get_contents($filename));
    $aggregator = $this->make_string_aggregator($global_name, $filename);
    $this->walk_tokens($tokens, array(&$this, ‘ignore_token’), array(&$this, ‘ignore_token’), $aggregator);
    }

    $potf = ‘-‘ == $pot_filename? STDOUT : @fopen($pot_filename, ‘a’);
    if (false === $potf) {
    $this->cli_die(“Couldn’t open pot file: $pot_filename”);
    }

    foreach($GLOBALS[$global_name] as $item) {
    @list($string, $comment_id, $filename, $line_number) = $item;
    $filename = isset($filename)? preg_replace(‘|^\./|’, ”, $filename) : ”;
    $ref_line_number = isset($line_number)? “:$line_number” : ”;
    $args = array(
    ‘singular’ => $string,
    ‘extracted_comments’ => “Not gettexted string $comment_id”,
    ‘references’ => array(“$filename$ref_line_number”),
    );
    $entry = new Translation_Entry($args);
    fwrite($potf, “\n”.PO::export_entry($entry).”\n”);
    }
    if (‘-‘ != $pot_filename) fclose($potf);
    return true;
    }

    function command_replace() {
    $args = func_get_args();
    $mo_filename = $args[0];
    if (isset($args[1]) && is_array($args[1]))
    $filenames = $args[1];
    else
    $filenames = array_slice($args, 1);

    $global_name = ‘__mo_’.mt_rand(1, 1000);
    $GLOBALS[$global_name] = new MO();
    $replacer = $this->make_mo_replacer($global_name);

    $res = $GLOBALS[$global_name]->import_from_file($mo_filename);
    if (false === $res) {
    $this->cli_die(“Couldn’t read MO file ‘$mo_filename’!”);
    }
    foreach($filenames as $filename) {
    $source = file_get_contents($filename);
    if ( strlen($source) > 150000 ) continue;
    $tokens = token_get_all($source);
    $new_file = $this->walk_tokens($tokens, $replacer, array(&$this, ‘unchanged_token’));
    $f = fopen($filename, ‘w’);
    fwrite($f, $new_file);
    fclose($f);
    }
    return true;
    }

    function usage() {
    $this->stderr(‘php i18n-comments.php COMMAND OUTPUTFILE INPUTFILES’);
    $this->stderr(‘Extracts and replaces strings, which cannot be gettexted’);
    $this->stderr(‘Commands:’);
    $this->stderr(‘ extract POTFILE PHPFILES appends the strings to POTFILE’);
    $this->stderr(‘ replace MOFILE PHPFILES replaces strings in PHPFILES with translations from MOFILE’);
    }

    function cli() {
    global $argv, $commands;
    if (count($argv) < 4 || !in_array($argv[1], array_keys($this->commands))) {
    $this->usage();
    exit(1);
    }
    call_user_func_array(array(&$this, $this->commands[$argv[1]]), array_slice($argv, 2));
    }
    }

    // run the CLI only if the file
    // wasn’t included
    $included_files = get_included_files();
    if ( $included_files[0] == __FILE__ ) {

    /**
    * Note: this file is locked by default since it should not be publicly accessible
    * on a live website. You can unlock it by temporarily removing the following line.
    */
    exit( ‘Locked’ );

    error_reporting(E_ALL);
    $not_gettexted = new NotGettexted;
    $not_gettexted->cli();
    }

    _________________________________________________________________
    _________________________________________________________________

    Thread Starter crmacdonald1

    (@crmacdonald1)

    _________________________________________________________________
    _________________________________________________________________

    …\wp-content\plugins\woocommerce\i18n\makepot\extract\extract.php

    <?php
    require_once dirname( __FILE__ ) . ‘/../pomo/entry.php’;
    require_once dirname( __FILE__ ) . ‘/../pomo/translations.php’;

    class StringExtractor {

    var $rules = array();
    var $comment_prefix = ‘translators:’;

    function __construct( $rules = array() ) {
    $this->rules = $rules;
    }

    function extract_from_directory( $dir, $excludes = array(), $includes = array(), $prefix = ” ) {
    $old_cwd = getcwd();
    chdir( $dir );
    $translations = new Translations;
    $file_names = (array) scandir( ‘.’ );
    foreach ( $file_names as $file_name ) {
    if ( ‘.’ == $file_name || ‘..’ == $file_name ) continue;
    if ( preg_match( ‘/\.php$/’, $file_name ) && $this->does_file_name_match( $prefix . $file_name, $excludes, $includes ) ) {
    $t = $this->extract_from_file( $file_name, $prefix );
    $translations->merge_originals_with( $t );
    }
    if ( is_dir( $file_name ) ) {
    $t = $this->extract_from_directory( $file_name, $excludes, $includes, $prefix . $file_name . ‘/’ );
    $translations->merge_originals_with( $t );
    }
    }
    chdir( $old_cwd );
    return $translations;
    }

    function extract_from_file( $file_name, $prefix ) {
    $code = file_get_contents( $file_name );
    return $this->extract_entries( $code, $prefix . $file_name );
    }

    function does_file_name_match( $path, $excludes, $includes ) {
    if ( $includes ) {
    $matched_any_include = false;
    foreach( $includes as $include ) {
    if ( preg_match( ‘|^’.$include.’$|’, $path ) ) {
    $matched_any_include = true;
    break;
    }
    }
    if ( !$matched_any_include ) return false;
    }
    if ( $excludes ) {
    foreach( $excludes as $exclude ) {
    if ( preg_match( ‘|^’.$exclude.’$|’, $path ) ) {
    return false;
    }
    }
    }
    return true;
    }

    function entry_from_call( $call, $file_name ) {
    $rule = isset( $this->rules[$call[‘name’]] )? $this->rules[$call[‘name’]] : null;
    if ( !$rule ) return null;
    $entry = new Translation_Entry;
    $multiple = array();
    $complete = false;
    for( $i = 0; $i < count( $rule ); ++$i ) {
    if ( $rule[$i] && ( !isset( $call[‘args’][$i] ) || !is_string( $call[‘args’][$i] ) || ” == $call[‘args’][$i] ) ) return false;
    switch( $rule[$i] ) {
    case ‘string’:
    if ( $complete ) {
    $multiple[] = $entry;
    $entry = new Translation_Entry;
    $complete = false;
    }
    $entry->singular = $call[‘args’][$i];
    $complete = true;
    break;
    case ‘singular’:
    if ( $complete ) {
    $multiple[] = $entry;
    $entry = new Translation_Entry;
    $complete = false;
    }
    $entry->singular = $call[‘args’][$i];
    $entry->is_plural = true;
    break;
    case ‘plural’:
    $entry->plural = $call[‘args’][$i];
    $entry->is_plural = true;
    $complete = true;
    break;
    case ‘context’:
    $entry->context = $call[‘args’][$i];
    foreach( $multiple as &$single_entry ) {
    $single_entry->context = $entry->context;
    }
    break;
    }
    }
    if ( isset( $call[‘line’] ) && $call[‘line’] ) {
    $references = array( $file_name . ‘:’ . $call[‘line’] );
    $entry->references = $references;
    foreach( $multiple as &$single_entry ) {
    $single_entry->references = $references;
    }
    }
    if ( isset( $call[‘comment’] ) && $call[‘comment’] ) {
    $comments = rtrim( $call[‘comment’] ) . “\n”;
    $entry->extracted_comments = $comments;
    foreach( $multiple as &$single_entry ) {
    $single_entry->extracted_comments = $comments;
    }
    }
    if ( $multiple && $entry ) {
    $multiple[] = $entry;
    return $multiple;
    }

    return $entry;
    }

    function extract_entries( $code, $file_name ) {
    $translations = new Translations;
    $function_calls = $this->find_function_calls( array_keys( $this->rules ), $code );
    foreach( $function_calls as $call ) {
    $entry = $this->entry_from_call( $call, $file_name );
    if ( is_array( $entry ) )
    foreach( $entry as $single_entry )
    $translations->add_entry_or_merge( $single_entry );
    elseif ( $entry)
    $translations->add_entry_or_merge( $entry );
    }
    return $translations;
    }

    /**
    * Finds all function calls in $code and returns an array with an associative array for each function:
    * – name – name of the function
    * – args – array for the function arguments. Each string literal is represented by itself, other arguments are represented by null.
    * – line – line number
    */
    function find_function_calls( $function_names, $code ) {
    $tokens = token_get_all( $code );
    $function_calls = array();
    $latest_comment = false;
    $in_func = false;
    foreach( $tokens as $token ) {
    $id = $text = null;
    if ( is_array( $token ) ) list( $id, $text, $line ) = $token;
    if ( T_WHITESPACE == $id ) continue;
    if ( T_STRING == $id && in_array( $text, $function_names ) && !$in_func ) {
    $in_func = true;
    $paren_level = -1;
    $args = array();
    $func_name = $text;
    $func_line = $line;
    $func_comment = $latest_comment? $latest_comment : ”;

    $just_got_into_func = true;
    $latest_comment = false;
    continue;
    }
    if ( T_COMMENT == $id ) {
    $text = trim( preg_replace( ‘%^/\*|//%’, ”, preg_replace( ‘%\*/$%’, ”, $text ) ) );
    if ( 0 === strpos( $text, $this->comment_prefix ) ) {
    $latest_comment = $text;
    }
    }
    if ( !$in_func ) continue;
    if ( ‘(‘ == $token ) {
    $paren_level++;
    if ( 0 == $paren_level ) { // start of first argument
    $just_got_into_func = false;
    $current_argument = null;
    $current_argument_is_just_literal = true;
    }
    continue;
    }
    if ( $just_got_into_func ) {
    // there wasn’t a opening paren just after the function name — this means it is not a function
    $in_func = false;
    $just_got_into_func = false;
    }
    if ( ‘)’ == $token ) {
    if ( 0 == $paren_level ) {
    $in_func = false;
    $args[] = $current_argument;
    $call = array( ‘name’ => $func_name, ‘args’ => $args, ‘line’ => $func_line );
    if ( $func_comment ) $call[‘comment’] = $func_comment;
    $function_calls[] = $call;
    }
    $paren_level–;
    continue;
    }
    if ( ‘,’ == $token && 0 == $paren_level ) {
    $args[] = $current_argument;
    $current_argument = null;
    $current_argument_is_just_literal = true;
    continue;
    }
    if ( T_CONSTANT_ENCAPSED_STRING == $id && $current_argument_is_just_literal ) {
    // we can use eval safely, because we are sure $text is just a string literal
    eval(‘$current_argument = ‘.$text.’;’
    );
    continue;
    }
    $current_argument_is_just_literal = false;
    $current_argument = null;
    }
    return $function_calls;
    }
    }

    _________________________________________________________________
    _________________________________________________________________

    Thread Starter crmacdonald1

    (@crmacdonald1)

    My pasting of the coding is a bit convoluted, sorry.

    The Plugin shows me these long lists of coding, then when I click on the “Potential Threats in File: Found[1]” (which is clickable), the Plugin highlights/ bold a specific line of text (which is what I kept highlight for you guys– all of them being “EVAL”).

    Basically, I wish to know if I should delete ALL of the coding, or just the specific part of the coding/ text that the Plugin has highlighted/ bolded.

    I realize you guys are probably busy, however, any help or support on this would be GREATLY appreciated! I’m learning as I go here.

    Thanks guys!! Again, apologies for the length.

    Plugin Author Eli

    (@scheeeli)

    No, don’t delete these “Potential Threats”. If you download the latest definition update then you should only be concerned with “Known Threats”, which my plugin will remove automatically.

    If there are still “Potential Threats” after you download the latest definition update then you can send me your WP Admin login and I will look through them and either whitelist them or add then to my definition update.

    Thread Starter crmacdonald1

    (@crmacdonald1)

    Thanks! I have downloaded the latest definition update, and I still have a few “Potential Threats” come up.

    How do I go about sending you my WP Admin login information. And what information do you need specifically?

    Plugin Author Eli

    (@scheeeli)

    If you want to mail me the WP Admin login, password, and URL, then I can login and check those potential threats for you.

    eli AT gotmls DOT net

    Thread Starter crmacdonald1

    (@crmacdonald1)

    Thanks! Just sent you an email*

    Plugin Author Eli

    (@scheeeli)

    Thanks for the login. I looked through the four remaining potential threats and they are all fine. The eval function can be used to execute encoded text and thus help to conceal malicious code, but there are many legitimate usages of the eval function too. That is why those four files were marked as potential threat. I have whitelisted them in your admin so that they will not get flagged again unless changed or upgraded. What you really need to look out for are the Known Threats, but I don’t see any of those on your site.

    Let me know if you need any more help.

    Aloha, Eli.

    Thread Starter crmacdonald1

    (@crmacdonald1)

    Thank you for your help! I truly appreciate you taking the time to do so.

    Cheers!
    -Chris

Viewing 13 replies - 1 through 13 (of 13 total)
  • The topic ‘Great Plugin! Found "potential threats" – question* (apologies for the length!)’ is closed to new replies.