网站源码为glype1.3
虚拟主机操作系统:windows2003在线代理网,其它网页元素正常显示,只有图片不能显示,图片显示为一个红色的叉。
未选网页加密时,图片的SRC地址也有异常,例如图片链接地址中的“/”显示“%2F”。
网站我就不说出来了,怕被墙。
求哪位大侠能帮帮我把类似“%2F”转换成浏览器能识别的“/”,感谢!glype1.3下载地址:http://www.glype.com/

解决方案 »

  1.   

    正则替换好了。
    中文可以urldecode
      

  2.   

    parser.php第一部分
    <?php
    /*******************************************************************
    * Glype is copyright and trade 2007-2012 UpsideOut, Inc. d/b/a Glype
    * and/or its licensors, successors and assigners. All rights reserved.
    *
    * Use of Glype is subject to the terms of the Software License Agreement.
    * http://www.glype.com/license.php
    *******************************************************************
    * This is the parser for the proxy - changes the original 'raw'
    * document so that everything (images, links, etc.) is rerouted to
    * be downloaded via the proxy script instead of directly.
    ******************************************************************/class parser { # State of javascript parser - null for parse everything, false
    # for parse all non-standard overrides, or (array) with specifics
    private $jsFlagState;

    # Browsing options (Remove Scripts, etc.)
    private $htmlOptions; # Constructor accepts options and saves them in the object
    function __construct($htmlOptions, $jsFlags) {
    $this->jsFlagState = $jsFlags;
    $this->htmlOptions = $htmlOptions;
    }
    /*****************************************************************
    * HTML parsers - main parsing function splits up document into
    * component parts ('normal' HTML, scripts and styles)
    ******************************************************************/

    function HTMLDocument($input, $insert='', $inject=false, $footer='') { #
    # Apply parsing that only needs to be done once..
    # # Remove titles if option is enabled
    if ( $this->htmlOptions['stripTitle'] ) {
    $input = preg_replace('#<title.*?</title>#is', '', $input, 1);
    $input = preg_replace('#<meta[^>]*name=["\']title["\'][^>]*>#is', '', $input, 1);
    } # Remove and record a <base> href
    $input = preg_replace_callback('#<base href\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(1)\\1|)[^>]*>#i', 'html_stripBase', $input, 1); # Proxy url= values in meta redirects
    $input = preg_replace_callback('#content\s*=\s*(["\\\'])?[0-9]+\s*;\s*url=([\\\'"]|&\#39;)?((?(?<=")[^"]+|(?(?<=\\\')[^\\\']+|[^\\\'" >]+)))(?(2)\\2|)(?(1)\\1|)#i', 'html_metaRefresh', $input, 1); # Process forms
    $input = preg_replace_callback('#<form([^>]*)>(.*?)</form>#is', 'html_form', $input);

    # Remove scripts blocks (avoids individual processing below)
    if ( $this->htmlOptions['stripJS'] ) {
    $input = preg_replace('#<script[^>]*>.*?</script>#is', '', $input);
    }


    #
    # Split up the document into its different types and parse them
    # # Build up new document into this var
    $new   = '';
    $offset = 0; # Find instances of script or style blocks
    while ( preg_match('#<(s(?:cript|tyle))[^>]*>#i', $input, $match, PREG_OFFSET_CAPTURE, $offset) ) { # What type of block is this?
    $block = strtolower($match[1][0]); # Start position of content
    $outerStart = $match[0][1];
    $innerStart = $outerStart + strlen($match[0][0]); # Determine type of end tag and find it's position
    $endTag  = "</$block>";
    $innerEnd = stripos($input, $endTag, $innerStart);
    if ($innerEnd===false) {
    $endTag  = "</";
    $innerEnd = stripos($input, $endTag, $innerStart);
    if ($innerEnd===false) {
    $input = preg_replace('#<script[^>]*>.*?$#is', '', $input);
    break;
    }
    }
    $outerEnd = $innerEnd + strlen($endTag);

    # Parse everything up till here and add to the new document
    $new .= $this->HTML(substr($input, $offset, $innerStart - $offset));

    # Find parsing function
    $parseFunction = $block == 'style' ? 'CSS' : 'JS' ; # Add the parsed block
    $new .= $this->$parseFunction(substr($input, $innerStart, $innerEnd - $innerStart)); # Move offset to new position
    $offset = $innerEnd; }
    # And add the final chunk (between last script/style block and end of doc)
    $new .= $this->HTML(substr($input, $offset)); # Replace input with the updated document
    $input = $new; # Encode the page
    if ( $this->htmlOptions['encodePage'] ) {
    $input = encodePage($input);
    } #
    # Now add our own code bits
    # # Insert our mini form after the <body>
    if ( $insert !== false ) { # Check for a frameset
    if ( ( $useFrames = stripos($input, '<frameset') ) !== false ) { # Flag the frames so only first displays mini-form
    $input = preg_replace_callback('#<frame[^>]+src\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(1)\\1|)#i', 'html_flagFrames', $input); } # Attempt to add after body
    $input = preg_replace('#(<body[^>]*>)#i', '$1' . $insert, $input, 1, $tmp); # Check it inserted and append (if not a frameset)
    if ( ! $tmp && ! $useFrames ) {
    $input = $insert . $input;
    } } # Insert our javascript library
    if ( $inject ) { # Generate javascript to insert
    $inject = injectionJS(); # Add our proxy javascript after <head>
    $input = preg_replace('#(<head[^>]*>)#i', '$1' . $inject, $input, 1, $tmp); # If no <head>, just prepend
    if ( ! $tmp ) {
    $input = $inject . $input;
    } } # Add anything to the footer?
    if ( $footer ) { $input = preg_replace('#(</body[^>]*>)#i', $footer . '$1', $input, 1, $tmp); # If no </body>, just append the footer
    if ( ! $tmp ){
    $input .= $footer;
    } } # Return new document
    return $input; } # Parse HTML sections
    function HTML($input) { # Removing objects? Follow spec and display inner content of object tags instead.
    if ( $this->htmlOptions['stripObjects'] ) { # Remove all object tags (including those deprecated but still common)
    $input = preg_replace('#<(?>object|applet|param|embed)[^>]*>#i', '', $input, -1, $tmp); # Found any? Remove the corresponding end tags
    if ( $tmp ) {
    $input = preg_replace('#</(?>object|applet|param|embed)>#i', '', $input, $tmp);
    } } else { # Parse <param name="movie" value="URL"> tags
    $input = preg_replace_callback('#<param[^>]+value\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(1)\\1|)[^>]*>#i', 'html_paramValue', $input); # To do: proxy object related URLs } # Show content within <noscript> tags
    # (preg_ seems to be faster than 2 str_ireplace() calls)
    if ( $this->htmlOptions['stripJS'] ) {
    $input = preg_replace('#</?noscript>#i', '', $input);
    } # Parse onX events
    $input = preg_replace_callback('#\b(on(?<!\.on)[a-z]{2,20})\s*=\s*([\\\'"])?((?(2)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(2)\\2|)#i', array(&$this, 'html_eventJS'), $input); # Parse style attributes
    $input = preg_replace_callback('#style\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(1)\\1|)#i', array(&$this, 'html_elementCSS'), $input); # Proxy URL attributes - this is the bottleneck but optimized
    # as much as possible (or at least, as much as I can).
    $input = preg_replace_callback('#(?><[A-Z][A-Z0-9]{0,15})(?>\s+[^>\s]+)*?\s*(?>(href|src|background)\s*=(?!\\\\)\s*)(?>([\\\'"])?)((?(2)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^ >]{1,1000}))(?(2)\\2|)#i', 'html_attribute', $input); # Return changed input
    return $input; } # Proxy an onX javascript event
    function html_eventJS($input) {
    return $this->htmlOptions['stripJS'] ? '' : $input[1] . '=' . $input[2] . $this->JS($input[3]) . $input[2];
    } # Proxy a style="CSS" attribute
    function html_elementCSS($input) {
    return 'style=' . $input[1] . $this->CSS($input[2]) . $input[1];
    }
      

  3.   

    parser.php第1部分
    <?php
    /*******************************************************************
    * Glype is copyright and trade 2007-2012 UpsideOut, Inc. d/b/a Glype
    * and/or its licensors, successors and assigners. All rights reserved.
    *
    * Use of Glype is subject to the terms of the Software License Agreement.
    * http://www.glype.com/license.php
    *******************************************************************
    * This is the parser for the proxy - changes the original 'raw'
    * document so that everything (images, links, etc.) is rerouted to
    * be downloaded via the proxy script instead of directly.
    ******************************************************************/class parser { # State of javascript parser - null for parse everything, false
    # for parse all non-standard overrides, or (array) with specifics
    private $jsFlagState;

    # Browsing options (Remove Scripts, etc.)
    private $htmlOptions; # Constructor accepts options and saves them in the object
    function __construct($htmlOptions, $jsFlags) {
    $this->jsFlagState = $jsFlags;
    $this->htmlOptions = $htmlOptions;
    }
    /*****************************************************************
    * HTML parsers - main parsing function splits up document into
    * component parts ('normal' HTML, scripts and styles)
    ******************************************************************/

    function HTMLDocument($input, $insert='', $inject=false, $footer='') { #
    # Apply parsing that only needs to be done once..
    # # Remove titles if option is enabled
    if ( $this->htmlOptions['stripTitle'] ) {
    $input = preg_replace('#<title.*?</title>#is', '', $input, 1);
    $input = preg_replace('#<meta[^>]*name=["\']title["\'][^>]*>#is', '', $input, 1);
    } # Remove and record a <base> href
    $input = preg_replace_callback('#<base href\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(1)\\1|)[^>]*>#i', 'html_stripBase', $input, 1); # Proxy url= values in meta redirects
    $input = preg_replace_callback('#content\s*=\s*(["\\\'])?[0-9]+\s*;\s*url=([\\\'"]|&\#39;)?((?(?<=")[^"]+|(?(?<=\\\')[^\\\']+|[^\\\'" >]+)))(?(2)\\2|)(?(1)\\1|)#i', 'html_metaRefresh', $input, 1); # Process forms
    $input = preg_replace_callback('#<form([^>]*)>(.*?)</form>#is', 'html_form', $input);

    # Remove scripts blocks (avoids individual processing below)
    if ( $this->htmlOptions['stripJS'] ) {
    $input = preg_replace('#<script[^>]*>.*?</script>#is', '', $input);
    }


    #
    # Split up the document into its different types and parse them
    # # Build up new document into this var
    $new   = '';
    $offset = 0; # Find instances of script or style blocks
    while ( preg_match('#<(s(?:cript|tyle))[^>]*>#i', $input, $match, PREG_OFFSET_CAPTURE, $offset) ) { # What type of block is this?
    $block = strtolower($match[1][0]); # Start position of content
    $outerStart = $match[0][1];
    $innerStart = $outerStart + strlen($match[0][0]); # Determine type of end tag and find it's position
    $endTag  = "</$block>";
    $innerEnd = stripos($input, $endTag, $innerStart);
    if ($innerEnd===false) {
    $endTag  = "</";
    $innerEnd = stripos($input, $endTag, $innerStart);
    if ($innerEnd===false) {
    $input = preg_replace('#<script[^>]*>.*?$#is', '', $input);
    break;
    }
    }
    $outerEnd = $innerEnd + strlen($endTag);

    # Parse everything up till here and add to the new document
    $new .= $this->HTML(substr($input, $offset, $innerStart - $offset));

    # Find parsing function
    $parseFunction = $block == 'style' ? 'CSS' : 'JS' ; # Add the parsed block
    $new .= $this->$parseFunction(substr($input, $innerStart, $innerEnd - $innerStart)); # Move offset to new position
    $offset = $innerEnd; } # And add the final chunk (between last script/style block and end of doc)
    $new .= $this->HTML(substr($input, $offset)); # Replace input with the updated document
    $input = $new; # Encode the page
    if ( $this->htmlOptions['encodePage'] ) {
    $input = encodePage($input);
    } #
    # Now add our own code bits
    # # Insert our mini form after the <body>
    if ( $insert !== false ) { # Check for a frameset
    if ( ( $useFrames = stripos($input, '<frameset') ) !== false ) { # Flag the frames so only first displays mini-form
    $input = preg_replace_callback('#<frame[^>]+src\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(1)\\1|)#i', 'html_flagFrames', $input); } # Attempt to add after body
    $input = preg_replace('#(<body[^>]*>)#i', '$1' . $insert, $input, 1, $tmp); # Check it inserted and append (if not a frameset)
    if ( ! $tmp && ! $useFrames ) {
    $input = $insert . $input;
    } } # Insert our javascript library
    if ( $inject ) { # Generate javascript to insert
    $inject = injectionJS(); # Add our proxy javascript after <head>
    $input = preg_replace('#(<head[^>]*>)#i', '$1' . $inject, $input, 1, $tmp); # If no <head>, just prepend
    if ( ! $tmp ) {
    $input = $inject . $input;
    } } # Add anything to the footer?
    if ( $footer ) { $input = preg_replace('#(</body[^>]*>)#i', $footer . '$1', $input, 1, $tmp); # If no </body>, just append the footer
    if ( ! $tmp ){
    $input .= $footer;
    } } # Return new document
    return $input; } # Parse HTML sections
    function HTML($input) { # Removing objects? Follow spec and display inner content of object tags instead.
    if ( $this->htmlOptions['stripObjects'] ) { # Remove all object tags (including those deprecated but still common)
    $input = preg_replace('#<(?>object|applet|param|embed)[^>]*>#i', '', $input, -1, $tmp); # Found any? Remove the corresponding end tags
    if ( $tmp ) {
    $input = preg_replace('#</(?>object|applet|param|embed)>#i', '', $input, $tmp);
    } } else { # Parse <param name="movie" value="URL"> tags
    $input = preg_replace_callback('#<param[^>]+value\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(1)\\1|)[^>]*>#i', 'html_paramValue', $input); # To do: proxy object related URLs } # Show content within <noscript> tags
    # (preg_ seems to be faster than 2 str_ireplace() calls)
    if ( $this->htmlOptions['stripJS'] ) {
    $input = preg_replace('#</?noscript>#i', '', $input);
    } # Parse onX events
    $input = preg_replace_callback('#\b(on(?<!\.on)[a-z]{2,20})\s*=\s*([\\\'"])?((?(2)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(2)\\2|)#i', array(&$this, 'html_eventJS'), $input); # Parse style attributes
    $input = preg_replace_callback('#style\s*=\s*([\\\'"])?((?(1)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^\s"\\\'>]{1,1000}))(?(1)\\1|)#i', array(&$this, 'html_elementCSS'), $input); # Proxy URL attributes - this is the bottleneck but optimized
    # as much as possible (or at least, as much as I can).
    $input = preg_replace_callback('#(?><[A-Z][A-Z0-9]{0,15})(?>\s+[^>\s]+)*?\s*(?>(href|src|background)\s*=(?!\\\\)\s*)(?>([\\\'"])?)((?(2)(?(?<=")[^"]{1,1000}|[^\\\']{1,1000})|[^ >]{1,1000}))(?(2)\\2|)#i', 'html_attribute', $input); # Return changed input
    return $input; } # Proxy an onX javascript event
    function html_eventJS($input) {
    return $this->htmlOptions['stripJS'] ? '' : $input[1] . '=' . $input[2] . $this->JS($input[3]) . $input[2];
    } # Proxy a style="CSS" attribute
    function html_elementCSS($input) {
    return 'style=' . $input[1] . $this->CSS($input[2]) . $input[1];
    }
      

  4.   

    parser.php第2部分
    /*****************************************************************
    * CSS parser - main parsing function
    * CSS parsing is a complicated by the caching of CSS files. We need
    * to consider (A) cross-domain caching and (B) the unique URLs option.
    *  A) If possible, use a relative URL so the saved URLs do not explictly
    *  point to a single domain.
    *  B) There is a second set of callback functions with "_unique" suffixed
    *  and these return the original URL to be reparesed.
    ******************************************************************/ # The URLs depend on the unique and path info settings. The type parameter allows
    # us to specify the unique callbacks.
    function CSS($input, $storeUnique=false) { # What type of parsing is this? Normally we parse any URLs to redirect
    # back through the proxy but not when storing a cache with unique URLs.
    $type = $storeUnique ? '_unique' : ''; # CSS needs proxying the calls to url(), @import and src=''
    $input = preg_replace_callback('#\burl\s*\(\s*[\\\'"]?([^\\\'"\)]+)[\\\'"]?\s*\)#i', 'css_URL' . $type, $input);
    $input = preg_replace_callback('#@import\s*[\\\'"]([^\\\'"\(\)]+)[\\\'"]#i', 'css_import' . $type, $input);
    $input = preg_replace_callback('#\bsrc\s*=\s*([\\\'"])?([^)\\\'"]+)(?(1)\\1|)#i', 'css_src' . $type, $input); # Return changed
    return $input; }
    /*****************************************************************
    * Javascript parser - main parsing function
    *
    * The specific parts that need proxying depends on which javascript
    * functions we've been able to override. On first page load, the browser
    * capabilities are tested to see what we can do client-side and the results
    * sent back to us. This allows us to parse only what we have to.
    * If $CONFIG['override_javascript'] is disabled, all commands are parsed
    * server-side. This will use much more CPU!
    *
    * Commands to proxy only if no override at all:
    *  document.write()
    *  document.writeln()
    *  window.open()
    *  eval()
    *
    * Commands to proxy, regardless of browser capabilities:
    *  location.replace()
    *  .innerHTML=
    *
    * Commands to proxy if the extra "watch" flag is set
    * (the browser doesn't support the .watch() method):
    *  location=
    *  x.location=
    *  location.href=
    *
    * Commands to proxy if the extra "setters" flag is set
    * (the browser doesn't support the __defineSetter__() method):
    *  .src=
    *  .href=
    *  .background=
    *  .action=
    *
    * Commands to proxy if the extra "ajax" flag is set
    * (the browser failed to override the .open() method):
    *  XMLHttpRequest.open()
    ******************************************************************/ function JS($input) { # Stripping?
    if ( $this->htmlOptions['stripJS'] ) {
    return '';
    }

    # Get our flags
    $flags = $this->jsFlagState; # Unless we know we don't need to, apply all the browser-specific flags
    if ( ! is_array($this->jsFlagState) ) {
    $flags = array('ajax', 'watch', 'setters');
    }

    # If override is disabled, add a "base" flag
    if ( $this->jsFlagState === null ) {
    $flags[] = 'base';
    } # Start parsing!
    $search = array();

    # Create shortcuts to various search patterns:
    #   "before"   - matches preceeding character (string of single char) [ignoring whitespace]
    #   "after"   - matches next character (string of single char) [ignoring whitespace]
    #   "id"   - key for identifying the original match (e.g. if we have >1 of the same key)
    $assignmentPattern = array('before'   => '.',   'after' => '='); 
    $methodPattern = array('before'   => '.',   'after' => '(');
    $functionPattern = array('after' => '('); # Configure strings to search for, starting with always replaced commands
    $search['innerHTML'][] = $assignmentPattern;
    $search['location'][]  = array('after' => '.', 'id' => 'replace()');
    # ^ This is only for location.replace() - other forms are handled later # Look for attribute assignments
    if ( in_array('setters', $flags) ) {
    $search['src'][] = $assignmentPattern;
    $search['href'][] = $assignmentPattern;
    $search['action'][] = $assignmentPattern;
    $search['background'][] = $assignmentPattern;
    }

    # Look for location changes
    # location.href will be handled above, location= is handled here
    if ( in_array('watch', $flags) ) {
    $search['location'][] = array('after' => '=', 'id' => 'assignment');
    } # Look for .open() if either AJAX (XMLHttpRequest.open) or
    # base (window.open) flags are present
    if ( in_array('ajax', $flags) || in_array('base', $flags) ) {
    $search['open'][] = $methodPattern;
    }

    # Add the basic code if no override
    if ( in_array('base', $flags) ) {
    $search['eval'][] = $functionPattern;
    $search['writeln'][]   = $methodPattern;
    $search['write'][] = $methodPattern;
    } # Set up starting parameters
    $offset = 0;
    $length = strlen($input);
    $searchStrings = array_keys($search); while ( $offset < $length ) { # Start off by assuming no more items (i.e. the next position
    # of interest is the end of the document)
    $commandPos = $length; # Loop through the search subjects
    foreach ( $searchStrings as $item ) { # Any more instances of this?
    if ( ( $tmp = strpos($input, $item, $offset) ) === false ) { # Nope, skip to next item
    continue; }
    # Closer to the currently held 'next' position?
    if ( $tmp < $commandPos ) { $commandPos = $tmp;
    $command = $item; } } # No matches found? Finish parsing.
    if ( $commandPos == $length ) {
    break;
    }

    # We've found the main point of interest; now use the
    # search parameters to check the surrounding chars to validate
    # the match.
    $valid = false; foreach ( $search[$command] as $pattern ) {

    # Check the preceeding chars
    if ( isset($pattern['before']) && str_checkprev($input, $pattern['before'], $commandPos-1) === false ) {
    continue;
    }

    # Check next chars
    if ( isset($pattern['after']) && ( $postCharPos = str_checknext($input, $pattern['after'], $commandPos + strlen($command), false, true) ) === false ) {
    continue;
    }

    # Still here? Match must be OK so generate a match ID  
    if ( isset($pattern['id']) ) {
    $valid = $command . $pattern['id'];
    } else {
    $valid = $command;
    }

    break;

    }

    # What we do next depends on which match (if any) we've found...
    switch ( $valid ) {

    # Assigment
    case 'src':
    case 'href':
    case 'background':
    case 'action':
    case 'locationassignment':
    case 'innerHTML': # Check our post-char position for = as well (could be equality
    # test rather than assignment, i.e. == )
    if ( ! isset($input[$postCharPos]) || $input[$postCharPos] == '=' ) {
    break;
    } # Find the end of this statement
    $endPos = analyze_js($input, $postCharPos);
    $valueLength = $endPos - $postCharPos; # Produce replacement command
    $replacement = sprintf('parse%s(%s)', $command=='innerHTML' ? 'HTML' : 'URL', substr($input, $postCharPos, $valueLength));

    # Adjust total document length as appropriate
    $length += strlen($replacement);

    # Make the replacement
    $input = substr_replace($input, $replacement, $postCharPos, $valueLength);

    # Move offset up to new position
    $offset = $endPos + 10;

    # Go get next match
    continue 2;


    # Function calls - we don't know for certain if these are in fact members of the
    # appropriate objects (window/XMLHttpRequest for .open(), document for .write() and
    # .writeln) so we won't change anything. Main.js still overrides these functions but
    # does nothing with them by default. We add an extra parameter to tell our override
    # to kick in.
    case 'open':
    case 'write':
    case 'writeln':

    # Find the end position (the closing ")" for the function call)
    $endPos = analyze_js($input, $postCharPos);

    # Insert our additional argument just before that
    $input = substr_replace($input, ',"gl"', $endPos, 0);

    # Adjust the document length
    $length += 5;

    # And move the offset
    $offset = $endPos + 5;

    # Get next match
    continue 2;


    # Eval() is a just as easy since we can just wrap the entire thing in parseJS().
    case 'eval':

    # Ensure this is a call to eval(), not anotherfunctionendingineval()
    if ( isset($input[$commandPos-1]) && strpos('abcdefghijklmnopqrstuvwxyz123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_', $input[$commandPos-1]) !== false ) {
    break;
    }

    # Find the end position (the closing ")" for the function call)
    $endPos = analyze_js($input, $postCharPos);
    $valueLength = $endPos - $postCharPos;

    # Generate our replacement
    $replacement = sprintf('parseJS(%s)', substr($input, $postCharPos, $valueLength));

    # Make the replacement
    $input = substr_replace($input, $replacement, $postCharPos, $valueLength);

    # Adjust the document length
    $length += 9;

    # And move the offset
    $offset = $endPos + 9;
    continue 2;


    # location.replace() is a tricky one. We have the position of the char
    # after . as $postCharPos and need to ensure we're calling replace(), 
    # then parse the entire URL
    case 'locationreplace()': # Validate the match
    if ( ! preg_match('#\Greplace\s*\(#', $input, $tmp, 0, $postCharPos) ) {
    break;
    }