<?php

/* ********************************************************************
 * PHF-Get - 0.4.0 (beta)
 * Copyright (C) 2022 - GreyWyvern
 *
 * Licenced under the BSD Licence
 *  - https://greywyvern.com/code/bsd.txt
 *
 ******************************************************************* */

class PHF_Component {
  private 
$purl;
  private 
$body;
  private 
$info;

  public 
$parent false;
  public 
$url;
  public 
$type '';
  public 
$forcetype '';
  public 
$accept = array();
  public 
$error;
  public 
$output;

  public function 
__construct($url) {
    
$this->url preg_replace('/#.*$/'''trim($url));

    
// Output is the URL until we can swap it for a data: URI
    
$this->output $url;

    if (
strpos($url'data:') === 0) {


    } else if (
preg_match('/^https?:\/\/([^\/?#]*)([^?#]*)(\?([^#]*))?(#(.*))?/'$this->url)) {

      
$this->purl parse_url($url);

    } else {

      
$this->error 'Unsupported URL';

    }
  }

  public function 
executePHF($depth 0) {
    global 
$_PHF;

    if (
$this->error) return false;

    
// Go back through all parents. If this URL is found, this is a
    // circular reference chain. Break it.
    
$parent $this->parent;
    while (
$parent !== false) {
      if (
$parent->url == $this->url) {

        return 
false;
      }
      
$parent $parent->parent;
    } 

    
// This URL is already in the cache
    
if (isset($_PHF->cache[$this->url])) {

      
$this->output $_PHF->cache[$this->url];
      return 
false;
    }

    
// Bail out if deeper than the depth limit
    
if ($depth >= $_PHF->depth_limit) {

      return 
false;
    }


    
$this->getURL();

    
// No info was gathered
    
if (!$this->info) return false;
    if (
$this->info['http_code'] != 200) return false;
    if (!
$this->body) return false;

    
// If an error occurred, log it for later
    
if ($this->error) {

      
$_PHF->errors[] = $this->error;
      return 
false;
    }

    
// Find the type of this document
    
foreach ($_PHF->types as $mimetype => $extension) {
      if (
preg_match('/\b'.preg_quote($mimetype'/').'\b/'$this->info['content_type'])) {
        
$this->type $mimetype;

        
// Restrict to approved mime-types
        
if (count($this->accept)) {
          if (!
in_array($this->type$this->accept)) {

            return 
false;

          } else if (
$this->forcetype) {

            
$this->type $this->forcetype;
          }
        }
        break;
      }
    }

    
// Search for links in this document depending on type
    
switch ($this->type) {
      case 
'text/html':
      case 
'application/xhtml+xml':

        
/* ***** <BASE> *********************************** */
        
if (preg_match('/<base\s[^>]*>/i'$this->body$base)) {
          if (
preg_match('/ href=(["\'])(.+?)\1/'$base[0], $url)) {
            
$url[2] = $this->createChildURL($url[2]);
            
$this->purl parse_url($url[2]);
          }
          
$this->body str_replace($base[0], ''$this->body);
        }

        
/* ***** <FRAMESET> ************************************** */
        
if (preg_match('/<frameset[^>]*>(.*?)<\/frameset>/si'$this->body$frameset)) {
          
preg_match_all('/<frame\s[^>]+>/i'$frameset[0], $frames);
          foreach (
$frames[0] as $frame) {
            
$newframe $frame;
            if (
preg_match('/\ssrc=(["\'])(.+?)\1/'$frame$url)) {
              
$data = new PHF_Component($this->createChildURL(html_entity_decode($url[2])));
              
$data->parent = &$this;
              if (
$data->executePHF($depth 1))
                
$newframe str_replace($url[0], ' src="'.$data->output.'"'$newframe);
            }
            
$this->body str_replace($frame$newframe$this->body);
          }
        }

        
/* ***** <META> ****************************************** */
        
preg_match_all('/<meta\s[^>]*>/i'$this->body$metas);
        foreach (
$metas[0] as $meta) {

        }

        
/* ***** <LINK> ****************************************** */
        
preg_match_all('/<link\s[^>]+>/i'$this->body$links);
        foreach (
$links[0] as $link) {
          
$newlink $link;
          if (
preg_match('/ rel=(["\'])stylesheet\1/'$link)) {
            if (
preg_match('/\shref=(["\'])(.+?)\1/'$link$url)) {
              
$data = new PHF_Component($this->createChildURL(html_entity_decode($url[2])));
              
$data->parent = &$this;
              
$data->accept = array('text/plain''text/css');
              
$data->forcetype 'text/css';
              if (
$data->executePHF($depth 1))
                
$newlink str_replace($url[0], ' href="'.$data->output.'"'$newlink);
            }
          } else if (
preg_match('/ rel=(["\'])(shortcut )?icon\1/'$link)) {
            if (
preg_match('/\shref=(["\'])(.+?)\1/'$link$url)) {
              
$data = new PHF_Component($this->createChildURL(html_entity_decode($url[2])));
              
$data->parent = &$this;
              
$data->accept = array(
                
'image/bitmap''image/gif''image/ico''image/icon''image/jpeg',
                
'image/png''image/svg+xml''image/tiff''image/vnd.microsoft.icon',
                
'image/webp' 'image/x-bitmap''image/x-icon'
              
);
              if (
$data->executePHF($depth 1))
                
$newlink str_replace($url[0], ' href="'.$data->output.'"'$newlink);
            }
          }
          
$this->body str_replace($link$newlink$this->body);
        }

        
/* ***** <?xml-stylesheet ?-> **************************** */
        
if ($this->type == 'application/xhtml+xml') {
          
preg_match_all('/<\?xml-stylesheet\s[^>]+\?'.'>/i'$this->body$xmls);
          foreach (
$xmls[0] as $xml) {
            
$newxml $xml;
            if (
preg_match('/\shref=(["\'])(.+?)\1/'$xml$url)) {
              
$data = new PHF_Component($this->createChildURL(html_entity_decode($url[2])));
              
$data->parent = &$this;
              
$data->accept = array('text/plain''text/css');
              
$data->forcetype 'text/css';
              if (
$data->executePHF($depth 1))
                
$newlink str_replace($url[0], ' href="'.$data->output.'"'$newxml);
            }
            
$this->body str_replace($xml$newxml$this->body);
          }
        }

        
/* ***** <STYLE> ***************************************** */
        
preg_match_all('/<style[^>]*>(.*?)<\/style>/si'$this->body$styles);
        foreach (
$styles[0] as $style) {
          
$newstyle $style;
          
preg_match_all('/([\s:])url\(([^#][^\)]+)\)/i'$style$urls);
          foreach (
$urls[2] as $key => $url) {
            
$data = new PHF_Component($this->createChildURL($url));
            
$data->parent = &$this;
            if (
$data->executePHF($depth 1))
              
$newstyle str_replace($urls[0][$key], $urls[1][$key].'url('.$data->output.')'$newstyle);
          }
          
preg_match_all('/@import\s+(["\'])(.+?)\1/i'$style$imports);
          foreach (
$imports[2] as $key => $import) {
            
$data = new PHF_Component($this->createChildURL($import));
            
$data->parent = &$this;
            
$data->accept = array('text/plain''text/css');
            
$data->forcetype 'text/css';
            if (
$data->executePHF($depth 1))
              
$newstyle str_replace($imports[0][$key], '@import "'.$data->output.'"'$newstyle);
          }
          
$this->body str_replace($style$newstyle$this->body);
        }

        
/* ***** <____ STYLE=""> ********************************* */
        
preg_match_all('/(<[^>]+\sstyle=)(["\'])(.+?)\2/i'$this->body$styles);
        foreach (
$styles[3] as $key => $style) {
          
$newstyle $style;
          
preg_match_all('/([\s:])url\(([^#]["\']?)([^\)]+)\2\)/i'$style$urls);
          foreach (
$urls[3] as $key => $url) {
            
$data = new PHF_Component($this->createChildURL(html_entity_decode($url)));
            
$data->parent = &$this;
            if (
$data->executePHF($depth 1))
              
$newstyle str_replace($urls[0][$key], $urls[1][$key].'url('.$data->output.')'$newstyle);
          }
          
preg_match_all('/@import\s+(["\'])(.+?)\1/i'$style$imports);
          foreach (
$imports[2] as $key => $import) {
            
$data = new PHF_Component($this->createChildURL(html_entity_decode($import)));
            
$data->parent = &$this;
            
$data->accept = array('text/plain''text/css');
            
$data->forcetype 'text/css';
            if (
$data->executePHF($depth 1))
              
$newstyle str_replace($imports[0][$key], '@import "'.$data->output.'"'$newstyle);
          }
          
$this->body str_replace($style$newstyle$this->body);
        }

        
/* ***** <SCRIPT> **************************************** */
        
preg_match_all('/<script\s[^>]+>(\s*<\/script>)?/i'$this->body$scripts);
        foreach (
$scripts[0] as $script) {
          
$newscript $script;
          if (
preg_match('/\ssrc=(["\'])(.+?)\1/'$script$url)) {
            
$data = new PHF_Component($this->createChildURL(html_entity_decode($url[2])));
            
$data->parent = &$this;
            
$data->accept = array('text/plain''text/javascript''application/javascript''application/x-javascript');
            
$data->forcetype 'text/javascript';
            if (
$data->executePHF($depth 1))
              
$newscript str_replace($url[0], ' src="'.$data->output.'"'$newscript);
          }
          
$this->body str_replace($script$newscript$this->body);
        }

        
/* ***** <IFRAME> **************************************** */
        
preg_match_all('/<iframe\s[^>]+>/i'$this->body$iframes);
        foreach (
$iframes[0] as $iframe) {
          
$newiframe $iframe;
          if (
preg_match('/\ssrc=(["\'])(.+?)\1/'$iframe$url)) {
            
$data = new PHF_Component($this->createChildURL(html_entity_decode($url[2])));
            
$data->parent = &$this;
            if (
$data->executePHF($depth 1))
              
$newiframe str_replace($url[0], ' src="'.$data->output.'"'$newiframe);
          }
          
$this->body str_replace($iframe$newiframe$this->body);
        }

        
/* ***** <IMG> ******************************************* */
        
preg_match_all('/<img\s[^>]+>/i'$this->body$imgs);
        foreach (
$imgs[0] as $img) {
          
$newimg $img;
          if (
preg_match('/\ssrc=(["\'])(.+?)\1/'$img$url)) {
            
$data = new PHF_Component($this->createChildURL(html_entity_decode($url[2])));
            
$data->parent = &$this;
            
$data->accept = array(
              
'image/bitmap''image/gif''image/ico''image/icon''image/jpeg',
              
'image/png''image/svg+xml''image/tiff''image/vnd.microsoft.icon',
              
'image/webp' 'image/x-bitmap''image/x-icon'
            
);
            if (
$data->executePHF($depth 1))
              
$newimg str_replace($url[0], ' src="'.$data->output.'"'$newimg);
          }
          if (
preg_match('/\ssrcset=(["\'])(.+?)\1/'$img$urlset)) {
            
$urls explode(','$urlset[2]);
            
$newurlset $urlset[2];
            foreach (
$urls as $url) {
              
$url preg_replace('/ [\d.]+[wx]/'''$url);
              
$data = new PHF_Component($this->createChildURL(html_entity_decode($url)));
              
$data->parent = &$this;
              
$data->accept = array(
                
'image/bitmap''image/gif''image/ico''image/icon''image/jpeg',
                
'image/png''image/svg+xml''image/tiff''image/vnd.microsoft.icon',
                
'image/webp' 'image/x-bitmap''image/x-icon'
              
);
              if (
$data->executePHF($depth 1))
                
$newurlset str_replace($url$data->output$newurlset);
            }
            
$newimg str_replace($urlset[2], $newurlset$newimg);
          }
          
$this->body str_replace($img$newimg$this->body);
        }

        
/* ***** <INPUT TYPE="IMAGE"> **************************** */
        
preg_match_all('/<input\s[^>]+>/i'$this->body$inputs);
        foreach (
$inputs[0] as $input) {
          
$newinput $input;
          if (
preg_match('/ type=(["\'])image\1/'$input)) {
            if (
preg_match('/\ssrc=(["\'])(.+?)\1/'$input$url)) {
              
$data = new PHF_Component($this->createChildURL(html_entity_decode($url[2])));
              
$data->parent = &$this;
              
$data->accept = array(
                
'image/bitmap''image/gif''image/ico''image/icon''image/jpeg',
                
'image/png''image/svg+xml''image/tiff''image/vnd.microsoft.icon',
                
'image/webp' 'image/x-bitmap''image/x-icon'
              
);
              if (
$data->executePHF($depth 1))
                
$newinput str_replace($url[0], ' src="'.$data->output.'"'$newinput);
            }
            
$this->body str_replace($input$newinput$this->body);
          }
        }

        
/* ***** <____ BACKGROUND=""> **************************** */
        
preg_match_all('/(<[^>]+\sbackground=)(["\'])(.+?)\2/i'$this->body$backgrounds);
        foreach (
$backgrounds[3] as $key => $background) {
          
$data = new PHF_Component($this->createChildURL(html_entity_decode($background)));
          
$data->parent = &$this;
          
$data->accept = array(
            
'image/bitmap''image/gif''image/ico''image/icon''image/jpeg',
            
'image/png''image/svg+xml''image/tiff''image/vnd.microsoft.icon',
            
'image/webp' 'image/x-bitmap''image/x-icon'
          
);
          if (
$data->executePHF($depth 1))
            
$this->body str_replace($backgrounds[0][$key], $backgrounds[1][$key].'"'.$data->output.'"'$this->body);
        }


        
// Add a <BASE> tag that correctly targets links to the original location
        
if (preg_match('/<head[^>]*>/i'$this->body$head))
          
$this->body str_replace($head[0], $head[0]."\n".'<base href="'.$this->url.'">'$this->body);

        break;

      case 
'text/xml':
      case 
'image/svg+xml':
      case 
'application/xml':

        
/* ***** <?xml-stylesheet ?-> **************************** */
        
preg_match_all('/<\?xml-stylesheet\s[^>]+\?>/i'$this->body$xmls);
        foreach (
$xmls[0] as $xml) {
          
$newxml $xml;
          if (
preg_match('/\shref=(["\'])(.+?)\1/'$xml$url)) {
            
$data = new PHF_Component($this->createChildURL(html_entity_decode($url[2])));
            
$data->parent = &$this;
            
$data->accept = array('text/plain''text/css');
            
$data->forcetype 'text/css';
            if (
$data->executePHF($depth 1))
              
$newlink str_replace($url[0], ' href="'.$data->output.'"'$newxml);
          }
          
$this->body str_replace($xml$newxml$this->body);
        }

        
/* ***** <STYLE> ***************************************** */
        
preg_match_all('/<style[^>]*>(.*?)<\/style>/si'$this->body$styles);
        foreach (
$styles[0] as $style) {
          
$newstyle $style;
          
preg_match_all('/([\s:])url\(([^#][^\)]+)\)/i'$style$urls);
          foreach (
$urls[2] as $key => $url) {
            
$data = new PHF_Component($this->createChildURL($url));
            
$data->parent = &$this;
            if (
$data->executePHF($depth 1))
              
$newstyle str_replace($urls[0][$key], $urls[1][$key].'url('.$data->output.')'$newstyle);
          }
          
preg_match_all('/@import\s+(["\'])(.+?)\1/i'$style$imports);
          foreach (
$imports[2] as $key => $import) {
            
$data = new PHF_Component($this->createChildURL($import));
            
$data->parent = &$this;
            
$data->accept = array('text/plain''text/css');
            
$data->forcetype 'text/css';
            if (
$data->executePHF($depth 1))
              
$newstyle str_replace($imports[0][$key], '@import "'.$data->output.'"'$newstyle);
          }
          
$this->body str_replace($style$newstyle$this->body);
        }

        
/* ***** <____ STYLE=""> ********************************* */
        
preg_match_all('/(<[^>]+\sstyle=)(["\'])(.+?)\2/i'$this->body$styles);
        foreach (
$styles[3] as $key => $style) {
          
$newstyle $style;
          
preg_match_all('/([\s:])url\(([^#]["\']?)([^\)]+)\2\)/i'$style$urls);
          foreach (
$urls[3] as $key => $url) {
            
$data = new PHF_Component($this->createChildURL(html_entity_decode($url)));
            
$data->parent = &$this;
            if (
$data->executePHF($depth 1))
              
$newstyle str_replace($urls[0][$key], $urls[1][$key].'url('.$data->output.')'$newstyle);
          }
          
preg_match_all('/@import\s+(["\'])(.+?)\1/i'$style$imports);
          foreach (
$imports[2] as $key => $import) {
            
$data = new PHF_Component($this->createChildURL(html_entity_decode($import)));
            
$data->parent = &$this;
            
$data->accept = array('text/plain''text/css');
            
$data->forcetype 'text/css';
            if (
$data->executePHF($depth 1))
              
$newstyle str_replace($imports[0][$key], '@import "'.$data->output.'"'$newstyle);
          }
          
$this->body str_replace($style$newstyle$this->body);
        }
        break;

      case 
'text/css':

        
/* ***** url() ******************************************* */
        
preg_match_all('/([\s:])url\(([^#]["\']?)([^\)]+)\2\)/i'$this->body$urls);
        foreach (
$urls[3] as $key => $url) {
          
$data = new PHF_Component($this->createChildURL($url));
          
$data->parent = &$this;
          if (
$data->executePHF($depth 1))
            
$this->body str_replace($urls[0][$key], $urls[1][$key].'url('.$data->output.')'$this->body);
        }

        
/* ***** @import "" ************************************** */
        
preg_match_all('/@import\s+(["\'])(.+?)\1/i'$this->body$imports);
        foreach (
$imports[2] as $key => $import) {
          
$data = new PHF_Component($this->createChildURL($import));
          
$data->parent = &$this;
          
$data->accept = array('text/plain''text/css');
          
$data->forcetype 'text/css';
          if (
$data->executePHF($depth 1))
            
$this->body str_replace($imports[0][$key], '@import "'.$data->output.'"'$this->body);
        }
        break;

      case 
'text/javascript':
      case 
'application/javascript':
      case 
'application/x-javascript':
        
// No parsing for links in javascript
        
break;

      case 
'':
        
// Unknown mime-type, should log this



        
return false;

      default:
        
// Binary and other no-parse formats

    
}

    if (
$depth) {
      if (
$this->type == 'text/css') {
        
$this->body str_replace(array("\n""\r"), ' '$this->body);
        
$this->body preg_replace('/ {2,}/'' '$this->body);
        
$this->output 'data:'.$this->type.','.htmlspecialchars(rawurlencode($this->body));
      } else 
$this->output 'data:'.$this->type.';base64,'.base64_encode($this->body);


      
$_PHF->cache[$this->url] = $this->output;

    
// Export top level data as-is without encoding
    
} else {
      
$this->output $this->body;


    }
    return 
true;
  }

  
/* ******************************************************************
   * Take a relative or absolute URL and return an absolute URL based
   * on the current working directory
   */
  
private function createChildURL($url) {
    
$url trim($url);

    if (!
$url || strpos($url'data:') === 0) {
      
$child $url;

    
// Relative to scheme
    
} else if (strpos($url'//') === 0) {
      
$child $this->purl['scheme'].':'.$url;

    
// Relative to root
    
} else if (strpos($url'/') === 0) {
      
$child $this->purl['scheme'].'://'.$this->purl['host'].((isset($this->purl['port'])) ? ':'.$this->purl['port'] : '').$url;

    
// Relative to current directory
    
} else if (!preg_match('/^http/'$url)) {
      if (!isset(
$this->purl['path'])) $this->purl['path'] = '';
      
$path preg_replace('/\/[^\/]*$/''/'$this->purl['path']);
      
$child $this->purl['scheme'].'://'.$this->purl['host'].((isset($this->purl['port'])) ? ':'.$this->purl['port'] : '').$path.$url;

    
// Absolute URL
    
} else $child $url;

    return 
$child;
  }

  
/* ******************************************************************
   * Use cURL to fetch a URL and account for any redirects or errors
   */
  
private function getURL() {
    global 
$_PHF;

    if (
strpos($this->url'data:') === 0) {

      
$data explode(','preg_replace('/^data:/'''$this->url), 2);

      if (isset(
$data[1])) {
        if (
preg_match('/([a-z]+\/[a-z0-9.+_-]+)(;[a-z]+=[^,]+)?(;base64)?/i'$data[0], $mime)) {
          if (
in_array($mime[1], array('text/html''application/xhtml+xml''text/xml''image/svg+xml''application/xml''text/css'))) {
            
$this->body base64_decode(urldecode($data[1]));
            
$this->purl $this->parent->purl;
            
$this->info = array(
              
'http_code' => 200,
              
'redirect_url' => '',
              
'content_type' => trim($data[0])
            );

            return;
          }
        }
      }

    } else {

      
$loop 0;
      
$testurl $this->url;

      do {
        
$ch curl_init($testurl);

        
curl_setopt($chCURLOPT_HEADERfalse);
        
curl_setopt($chCURLOPT_USERAGENT$_PHF->user_agent);
        
curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
        
// curl_setopt($ch, CURLOPT_MAXFILESIZE, $_PHF->max_size);
        
curl_setopt($chCURLOPT_TIMEOUT10);
        
curl_setopt($chCURLOPT_ENCODING'gzip'); 
        
// curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        // curl_setopt($ch, CURLOPT_MAXREDIRS, $_PHF->redirect_limit);
        
curl_setopt($chCURLOPT_PROTOCOLSCURLPROTO_HTTP CURLPROTO_HTTPS);
        
curl_setopt($chCURLOPT_NOPROGRESSfalse);
        
curl_setopt($chCURLOPT_PROGRESSFUNCTION, function($ch$dls$dl$uls$ul) {
          global 
$_PHF;

          if (
$dls $_PHF->max_size || $dl $_PHF->max_size) return 1;

          
$info curl_getinfo($ch);
          if (
$info['redirect_url']) return 1;
          if (
$info['http_code'] && $info['http_code'] >= 400) return 1;

          return 
0;
        });

        
$body curl_exec($ch);
        
$this->error curl_error($ch);
        
$this->info curl_getinfo($ch);

        while (
strpos($body"\x1f\x8b") === 0)
          
$body gzinflate(substr($body10));

        
curl_close($ch);

        if (
$this->info['redirect_url']) {
          if (++
$loop $_PHF->redirect_limit) {

            
$this->error 'Redirect loop encountered at: '.$this->url;
            return;
          }
          
$testurl $this->createChildURL($this->info['redirect_url']);

        } else if (
$this->info['http_code'] != 200) {

          
$this->error 'HTTP error: ('.$this->info['http_code'].')';


          return;

        } else if (
$this->error == 'Callback aborted') {

          
$this->error 'Maximum file size exceeded at URL: '.$this->url;
          return;

        } else if (
$this->error) {

          return;
        }

      } while (
$this->info['redirect_url']);

      if (
$testurl != $this->url) {

        
$this->url $testurl;
        
$this->purl parse_url($this->url);
      }


      
$this->body $body;
    }
  }
}


class 
PHF_Get extends PHF_Component {
  private 
$version '0.4.0 (beta)';

  public 
$user_agent '';
  public 
$max_size 524288;
  public 
$depth_limit 10;
  public 
$redirect_limit 10;
  public 
$errors = array();
  public 
$cache = array();
  public 
$types = array(
    
'application/font-woff' => 'woff',
    
'application/javascript' => 'js',
    
'application/octet-stream' => '',
    
'application/font-sfnt' => 'sfnt',
    
'application/vnd.ms-fontobject'  => 'eot',
    
'application/x-font-ttf' => 'ttf',
    
'application/x-javascript' => 'js',
    
'application/xhtml+xml' => 'xhtml',
    
'application/xml' => 'xml',
    
'font/otf' => 'otf',
    
'font/sfnt' => 'sfnt',
    
'font/ttf' => 'ttf',
    
'font/woff' => 'woff',
    
'font/woff2' => 'woff2',
    
'image/bitmap' => 'bmp',
    
'image/gif' => 'gif',
    
'image/ico' => 'ico',
    
'image/icon' => 'ico',
    
'image/jpeg' => 'jpg',
    
'image/png' => 'png',
    
'image/svg+xml' => 'svg',
    
'image/tiff' => 'tif',
    
'image/vnd.microsoft.icon' => 'ico',
    
'image/webp' => 'webp',
    
'image/x-bitmap' => 'bmp',
    
'image/x-icon' => 'ico',
    
'text/css' => 'css',
    
'text/html' => 'html',
    
'text/javascript' => 'js',
    
'text/plain' => 'txt',
    
'text/xml' => 'xml'
  
);

  public function 
__construct($url) {
    
parent::__construct($url);

    
$this->user_agent 'phf_get '.$this->version;
  }
}


// ***** Usage
$_PHF = new PHF_Get('http://example.com');
$_PHF->user_agent $_SERVER['HTTP_USER_AGENT'];
$_PHF->executePHF();

// Contents of document are now in $_PHF->output
echo $_PHF->output;

// Any errors encountered are in the $_PHF->errors array
var_dump($_PHF->errors);

?>