<?php

require_once('Transformer.php');

class 
HTML extends Transformer {
  
  private 
$xpath;

  public function 
transform() {
    
$xmlDoc  = new DOMDocument();
    
    if (!
$xmlDoc->loadXML($this->xmlContents)) {
      throw new 
Exception("Unable to DOMify XML (XML looks like: ".$this->xmlContents.')');
    }
    
$this->xpath   = new DOMXPath($xmlDoc);
        
    
header('Content-type: text/html; charset=UTF-8');

    
// maybe there was an error, so let's check it
    
$messages $this->xpath->query("/results/message");
    if (
$messages->length 0) {
      
$message $messages->item(0)->nodeValue;
      
      
// if the message says we need a username and password, then generate a
      // form that lets the user supply the credentials
      
$matchString 'This Dapp requires a username and password';
      if (
substr($message,0,strlen($matchString)) == $matchString) {
        
?>
        <html>
          <head>
            <style style="text/css">
              body, table {
                font-family:arial;
                font-size:10pt;
              }
              body {
                background-color: #ffffff;
              }
            </style>
          </head>
          <body>
            <p>
              This Dapp requires that you log into the remote website.  Please 
              supply your username and password for the remote website.
            </p>
            <script src="/prototype.js" type="text/javascript"></script>
            <script type="text/javascript">
              function encryptThenSubmit() {
                  document.getElementById('encryptSubmitButton').value='Please wait';
                  
                var username = document.getElementById('username_raw').value;
                var password = document.getElementById('password_raw').value;
                
                var url = 'http://<?php echo $_SERVER['SERVER_NAME'];?>'+
                          '/encrypt-credentials.jsp';
                var par = 'username='+encodeURIComponent(username)+'&'+
                          'password='+encodeURIComponent(password);
                var myAjax = new Ajax.Request(
                  url,
                  {
                    method: 'post',
                    parameters: par,
                    onComplete: function(originalRequest) { 
                                  var encValues;
                                  eval("encValues = "+originalRequest.responseText);
                                  document.getElementById('username_enc').value = encValues['username'];
                                  document.getElementById('password_enc').value = encValues['password'];
                                  document.getElementById('loginForm').submit();
                                }
                  }
                
                );
                
                
                return false;
              }
            </script>
            <form id="loginForm" 
                  action="<?php echo $_SERVER['REQUEST_URI'];?>
                  method="post" 
                  onsubmit="return encryptThenSubmit();">
              <table>
                <tr>
                  <td>Username:</td>
                  <td><input size="50" type="text" id="username_raw" /></td>
                </tr>
                <tr>
                  <td>Password: </td>
                  <td><input size="50" type="password" id="password_raw" /></td>
                </tr>
                <tr>
                  <td colspan="2" style="text-align:right;">
                    <input type="hidden" name="username" id="username_enc" />
                    <input type="hidden" name="password" id="password_enc" />
                    <input type="hidden" name="encryptionAlg" value="1" />
                  
                    <input type="submit" value="Submit" id="encryptSubmitButton"/>
                  </td>
                </tr>
              </table>
            </form>
          </body>
        </html>
        <?php
        
exit;
      }
      else {
        echo 
$message;
        exit;
      }
    }
        
    
// start HTML
    
?>
    <html>
      <head>
        <title>
          HTML Transformation for Dapp: 
          <?php echo $this->xpath->query("/elements/dapper/dappTitle")->item(0)->nodeValue;?>
        </title>
        <style>
          body {
            font-family: arial;
            font-size: 10pt;
            line-height: 20px;
            background-color:#ffffff;
          }
          h1 {
            color: #5050a0;
            font-weight: bold;
            font-size: 20pt;
            margin-top:0px;
          }
          div.groupDiv {
            <?php if (empty($this->extraArgs['smallMode'])) { ?>
              width: 80%;
              border: 1px solid #5050a0;
              left:50%;
              margin-left:-40%;
            <?php } else { ?>
              width: 95%;
            <?php ?>
            padding: 10px;
            margin-bottom:10px;
            overflow:hidden;
            position:relative;
          }
          <?php if (empty($this->extraArgs['smallMode'])) { ?>
            div.even {
              background-color: #ddddff;
            }
            div.odd {
              background-color: #bbbbff;
            }
          <?php ?>
          div.dappHeader {
            width:80%;
            left:50%;
            margin-left:-40%;
            position:relative;
            margin-top:20px;
          }
        </style>
        <script src="/prototype.js" type="text/javascript"></script>
      </head>
      <body>
    <?php
    
    
// collect the groups and fields
    
$xmlRoot $xmlDoc->documentElement;    
    
$this->printDappResults($xmlRoot1);
    
    
// end HTML
    
echo '</body>';
    echo 
'</html>';
  }
  
  private function 
printDappResults($xmlRoot$level$previousGroup null) {
   
    
// get dapp details
    
$dappDetails = array();
    
$urlNodes $this->xpath->evaluate("./dapper/urls/url",$xmlRoot);
    
$dappUrls = array();
    for (
$i=0$i<$urlNodes->length$i++) {
      
$dappUrls[] = '<a href="'.$urlNodes->item($i)->nodeValue.'">'.
                                
$urlNodes->item($i)->nodeValue.'</a>';
    }
    
$dappDetails['Dapp Title']  = $this->xpath->evaluate("./dapper/dappTitle",$xmlRoot)->item(0)->nodeValue;
    
$dappDetails['Built from URLs'] = '<ul><li>'.join('</li><li>',$dappUrls).'</li></ul>';
    
$dappDetails['Application URL'] = $this->xpath->evaluate("./dapper/applyToUrl",$xmlRoot)->item(0)->nodeValue;
    
$dappDetails['Application URL'] = '<a href="'.$dappDetails['Application URL'].'">'.$dappDetails['Application URL'].'</a>';
    
$dappDetails['Execution Time']  = $this->xpath->evaluate("./dapper/executionTime",$xmlRoot)->item(0)->nodeValue.' seconds';
    if (
$this->xpath->evaluate("./dapper/totalExecutionTime",$xmlRoot)->item(0))
      
$dappDetails['Execution Time'] .= ' ('.$this->xpath->evaluate("./dapper/totalExecutionTime",$xmlRoot)->item(0)->nodeValue.' seconds)';

    
$groupsOrFields $xmlRoot->childNodes;
    
$groupNodes     = array();
    
$fieldNodes     = array();
    for (
$i=0$i<$groupsOrFields->length$i++) {
      
$childNode $groupsOrFields->item($i);

      if (
$childNode->nodeType != XML_ELEMENT_NODE)
        continue;

      if (
$childNode->getAttribute('type') == 'group')
        
$groupNodes[] = $childNode;
      elseif (
$childNode->getAttribute('type') == 'field')
        
$fieldNodes[] = $childNode;
    }

    
// print dapp details
    
if (empty($this->extraArgs['smallMode'])) {
      
$id md5(microtime(true).$dappDetails['Dapp Title']);
      echo 
'<div class="dappHeader">';
      echo 
'<h1>'.$dappDetails['Dapp Title'].(isset($previousGroup) ? ' for '.$previousGroup '');
      echo 
' <span style="font-size:10px;">(<a href="#" onclick="Element.toggle(\''.$id.'\');return false;">details</a>)</span>';
      echo 
'</h1>';
      echo 
'</div>';
      echo 
'<div class="groupDiv '.($level == 'even' 'odd').'" style="display:none;" id="'.$id.'">';
      foreach (
$dappDetails as $desc => $val) {
        echo 
'<nobr><b>'.$desc.':</b> '.$val.'</nobr><br/>';
      }
      echo 
'</div>';
    }

    
// print the groups
    
$i 0;
    foreach (
$groupNodes as $groupNode) {
      
$i++;
      
$thisId $i;
      
      
$class  'groupDiv '.($level == 'even' 'odd');
      if (!empty(
$this->extraArgs['microFormat']))
        
$class .= ' '.$groupNode->getAttribute('groupName');

      echo 
'<div class="'.$class.'">';
      echo 
'<h1>'.str_replace('_',' ',$groupNode->tagName);
      echo 
' <span style="font-size:10px;">(<a href="#" onclick="Element.toggle(\''.$thisId.'\');return false;">collapse</a>)</span>';
      echo 
'</h1>';
      echo 
'<div id="'.$thisId.'">';
      
$fields $groupNode->childNodes;
      for (
$j=0$j<$fields->length$j++) {
        
$this->printField($fields->item($j), $level$groupNode->tagName);
      }
      echo 
'</div>';
      echo 
'</div>';      
    }
    
    
// print the fields
    
if (sizeof($fieldNodes)) {
      echo 
'<div class="groupDiv '.($level == 'even' 'odd').'">';
      foreach (
$fieldNodes as $fieldNode) {
        
$this->printField($fieldNode$level);
      }
      echo 
'</div>';
    }    
    
  }
  
  private function 
printField($fieldNode$level$previousGroup null) {
    if (
$fieldNode->nodeType != XML_ELEMENT_NODE)
      return;

    if (
$fieldNode->getAttribute('type') == 'field') {
      
$display $fieldNode->nodeValue;
      if (!
trim($display))
        
$display 'No value';
      if (
$fieldNode->getAttribute('href'))
        
$display '<a href="'.$fieldNode->getAttribute('href').'">'.
                   
$display.
                   
'</a>';
      if (
$fieldNode->getAttribute('src') &&
          
$fieldNode->getAttribute('originalElement') == 'img')
        
$display '<img src="'.$fieldNode->getAttribute('src').'" />';
      echo 
'<div style="padding-bottom:8px;clear:both;">';
      echo 
'<div style="display:inline;float:left;font-weight:bold;width:100px;margin-right:5px;">';
      echo 
$fieldNode->getAttribute('fieldName');
      echo 
':</div>';
      
      
// the content of the field itself
      
echo '<div>';
      if (!empty(
$this->extraArgs['microFormat']))
        echo 
'<span class="'.$fieldNode->getAttribute('fieldName').'">'.$display.'</span>';
      else
        echo 
$display;
      
      
// XXX: ADS DEMO
      
if ($fieldNode->getAttribute('ads')) {
        
$adIds explode(',',$fieldNode->getAttribute('ads'));
        
        
// right now we only care about 1 ad, not all the ads
        
$adIndex rand(0,count($adIds)-1);
        
$adNode $this->xpath->query('//ad[id="'.$adIds[$adIndex].'"]');
        if (
$adNode->length 0) {
          echo 
' (Ad: ';
          echo 
'<a href="'.$adNode->item(0)->getElementsByTagName('link')->item(0)->nodeValue.'">';
          echo 
$adNode->item(0)->getElementsByTagName('content')->item(0)->nodeValue;
          echo 
'</a>';
          echo 
')';
        }
        else {
          echo 
' (AD IS BROKEN!)';
        }
      }
      
      echo 
'</div>';
      
      
      echo 
'</div>';
    }
    elseif (
$fieldNode->tagName == 'elements') {
      
$this->printDappResults($fieldNode$level+1$previousGroup);
    }
  }

  public static function 
getDetails() {
    
$details = array();
    
    
$details['args']['smallMode']   = array('type'     => USER_CHECKBOX,
                                            
'required' => false,
                                            
'value'    => 1,
                                            
'display'  => 'Small Mode ');
    
    
$details['args']['microFormat'] = array('type'     => USER_CHECKBOX,
                                            
'required' => false,
                                            
'value'    => 1,
                                            
'display'  => 'Microformat Mode ');
    
    
$details['description'] = 'Transforms the output of a Dapp in human '.
                              
'readable form, suitable for viewing in a web '.
                              
'browser';
                             
    return 
$details;
  }

}

?>