<?php
    
# Tomenet log colour converter
    # Version 0.82b
    # Author MRy

    # Version 0.82b: Fixed fixed-width fonts by adding more options. Tested with Firefox 13 Portable (wine) and Chromium 19 (linux)
    #    - Notes: Firefox _can not_ zoom fixed space fonts properly, whereas chromium can.

    # Version 0.82a: Pastebin support (!)

    # Version 0.81b added simple file handler for urls (http:// and .txt required!)
    #    - http://shell.nullcore.fi/~djwolf/tomenet/?file=http://shell.nullcore.fi/~djwolf/tomenet/tomenetrocks.txt&fixed=1 for example :)

    # Version 0.80 replaces hacks and parsing, splitting them into functions. Fixed-space font also possible.

    # Version 0.51 replaces flicker hacks

    # Version 0.42 adds adjustable delay (use with /?delay=milliseconds, defaults to 100ms)

    # Version 0.41 replaces $t[$o] with substring($t,$o,1) as older php version (5.2.9) has a bug. Would work fine with 5.4.4 though.

    # Version 0.4 includes character flicker
    # - Slight bug on inscriptions again

    # Version 0.3 includes a hack for inscriptions

    # Version 0.2 includes javascript for flickers :)

    # Version 0.1 known issues:
    # - Colours might be bit off, need readjusting :)
    # - Textarea field is small and ugly
    # - If pasting lots of text to textarea, nothing might happen. Maybe browser issue (tried with Chromium 19.0.1084.56)

    
if (isset($_GET["mode"]) == "source") die(highlight_file(__FILE__1));            // Show source code

    
if (isset($_GET["delay"])) $delay htmlspecialchars($_GET["delay"]);             // Set delay with /?delay=number
    
else $delay 100;
        
    if ((isset(
$_POST["fixed"])) || (isset($_GET["fixed"]))) $fixed htmlspecialchars($_POST["fixed"]) || htmlspecialchars($_GET["fixed"]);
    else 
$fixed 0;

    if (isset(
$_GET["file"])) {
        
$f htmlspecialchars($_GET["file"]);                        // Strip special chars
        
if (    (strrchr($f,".") == ".txt") &&                        // Require .txt file
            
(substr($f,0,7) == "http://")) {                    // Require http:// url
            
$fparsing "url";
        }
        elseif ((
substr($f,7,12) == "pastebin.com") ||                    // Hack: Pastebin support (!)
            
(substr($f,0,12) == "pastebin.com")) {
            
$fparsing "pastebin";
        }                    
        else die(
"<pre>Invalid file or address: ".$f."</pre>");
        if (
substr($f,0,7) != "http://"$f "http://".$f;
        if (
false !== ($fhandle fopen($f,"rb"))) {                    // Open stream
            
while (!feof($fhandle)) {
                if (
$fparsing == "url"$text .= str_replace("\r","",htmlspecialchars(fread($fhandle,8192)));    // Normal .txt files are parsed completely
                
elseif ($fparsing == "pastebin") {                                // Pastebin is parsed from html site, taking source from textarea.
                    
$fadjust 4;                                        // htmlspecialchars makes 4 bytes of garbage.
                    
$fbuff .= str_replace("\r","",htmlspecialchars(fread($fhandle,8192)));            // Read site to buffer
                    
$spos strpos(trim($fbuff),htmlspecialchars("<textarea id=\"paste_code\""));        // Get position for textarea (if in buffer)
                    
if ((false !== $spos) && (!isset($epos))) {                        // If start position in buffer and end position not received
                        
$rpos strpos(trim($fbuff),htmlspecialchars(">"),$spos);            // Start reading from this position, ignoring tags and stuff.
                        
$epos strpos(trim($fbuff),htmlspecialchars("</textarea>"),$rpos);                // End position
                        
if (false !== $epos$text .= substr(trim($fbuff),$rpos+$fadjust,($epos-$rpos)-$fadjust);    // If found end position, add text to buffer
                        
else unset($epos);                                        // Not quite sure if should add it anyway...
                    
}
                }
            }
            
fclose($fhandle);        
        }
        else die(
"<pre>No such file at address ".$f."</pre>");
    }

    elseif ((isset(
$_POST["log"])) && ($_POST["log"] != "")) $text str_replace("\r","",htmlspecialchars($_POST["log"])); 
    else 
$text "{w&#91;Zeam&#93; {BInput text below and click convert{A :)";

    function 
str_replace_limit($search,$replace,$subject,$limit,&$count null) {        // Took this function from php.net
        
$count 0;
        if (
$limit <= 0) return $subject;
        
$occurrences substr_count($subject,$search);
        if (
$occurrences === 0) return $subject;
        else if (
$occurrences <= $limit) return str_replace($search,$replace,$subject,$count);
        
//Do limited replace
        
$position 0;
        
//Iterate through occurrences until we get to the last occurrence of $search we're going to replace
        
for ($i 0$i $limit$i++)
        
$position strpos($subject,$search,$position) + strlen($search);
        
$substring substr($subject,0,$position 1);
        
$substring str_replace($search,$replace,$substring,$count);
        return 
substr_replace($subject,$substring,0,$position+1);
    }

    function 
str_replace_limit_reverse($search,$replace,$subject,$limit,&$count null)    // Took this function from php.net
    
{
        
$count 0;
        
$search strrev($search);
        
$replace strrev($replace);
        
$subject strrev($subject);
        return 
strrev(str_replace_limit($search,$replace,$subject,$limit,$count));
    }

    function 
tomenet_hack_inscription($str) {                                // Function to hack inscriptions.
        
$text explode("\n",$str);
        unset(
$str);
        foreach(
$text as $n => $l) {                                    // Hack for character colouring and extra long line breaking.
            
if (    (substr($text[$n+1],0,1) == chr(32)) &&                        // Multi-line inscription starts with space
                
(strlen($text[$n]) != 0)) {                            // Hack: But only if current line isnt empty (mostly occurring with x2 on beginning of dump)
                    
$text[$n] = $text[$n].substr(trim($text[$n+1]),2);            // Add trimmed second line without colour code to previous line
                    
unset($text[$n+1]);                            // Delete the second line from array
            
}
            if (    (
substr($text[$n],-2,1) == "}") ||                        // Single-line inscription (with a dot or other char in end)
                
(substr($text[$n],-12,1) == "}") ||                        // Single-line inscription (on a pile)
                
(substr($text[$n],-6,1) == "}") ||                        // Single-line inscription (on a slot)
                
(substr($text[$n],-1,1) == "}") ||                         // Single-line inscription
                
(substr($text[$n],2,8) == "You sold") ||                    // Hack: When selling item
                
(substr($text[$n],2,9) == "You see a")) {                    // Hack: When seeing item (maybe not required)
                
$temp $text[$n];
                
$amount = (substr_count($temp,"{",0));                        // Hack: Count amount of {'s
                
if ($amount == 2$amount 1; else $amount 2;                // Hack: Count of 2 becomes 1, others 2.
                
$temp str_replace_limit_reverse("{","{{",$temp,$amount)."";            // Hack: Counting from back, replace 1-2 {'s with {{
                
$text[$n] = $temp;                            
            }
            if (isset(
$text[$n])) $ret .= $text[$n]."{w<br />\n";                    // Recombine text from array.
        
}
        return 
$ret;                                            // Return string
    
}

    function 
tomenet_parse_flicker($str) {                        // Function to parse tomenet generated colour string to proper one
        
if (!isset($str)) return 0;                        // If string was not set, return 0
        
$str "{w{w".$str;                            // Hack: add two white colours in start of the line (so lines without color codes will be white)
        
$str2 $str;                                // Copy string to Temporary variable

        
$flickers "MAchCHaSmeLfpI";                        // These colours are parsed
        
$colours "wWgGdDobByuUrR";                        // Some colours that might require special hack. (atm exception is slate for inventory paste w/o inscription)

        
while (false !== ($i strpos($str,"{",$i+1))) {            // While we find colour code indicators from string
            
$colour substr($str,$i+1,1);                    // Grab colour
            
$char substr($str,$i+2,1);                    // Grab character
            
$end strpos($str,"{",$i+1);                    // Repeat until next colour code
            
if (!$end$end strlen($str);                    // Or stop in end of line
            
if (($colour == "x") || ($colour == "{")) {            // Hack: If colour code is x or { (x isnt really used even in the hack at the moment)
                
$end strpos($str,"\n",$i);                // Stop colouring until linefeed
                
if (false !== (strchr($colours,$char))) $str3 .= "{";    // Hack: Stop colouring items owned by other persons
                
$str3 .= "{";
                while (
$i $end-2) {                    // Loop until end
                    
$char substr($str2,$i+2,1);            // Grab char
                    
$str3 .= $char;                    // Add char to string
                    
$i++;            
                }

            }
            elseif (
false !== (strchr($flickers,$colour))) {        // If colour code is findable in flicker string
                
while ($i $end-2) {                    // Loop until end
                    
$char substr($str,$i+2,1);            // Grab char
                    
$str3 .= "{".$colour.$char;            // Parse string
                    
$i++;                        
                
                }
            }
            else {                                
// If colour code isnt flickering one
                
$str3 .= "{".$colour;                    // Add one colour code indicator
                
while ($i $end-2) {                    // Loop until end
                    
$char substr($str2,$i+2,1);            // Grab char
                    
$str3 .= $char;                    // Add char to string
                    
$i++;            
                }
            }
        }
        return 
$str3;                                // Return string
    
}


    
$replace = array(
        
"{{" => "{",                                    // Hack: Make {{'s look like {, overriding colouring below and looking like original messages
        
"{d" => "</span><span style=\"color:#000000\">",                // Normal colours
        
"{s" => "</span><span style=\"color:#9d9d9d\">",
        
"{w" => "</span><span style=\"color:#ffffff\">",
        
"{o" => "</span><span style=\"color:#ff8d00\">"
        
"{r" => "</span><span style=\"color:#b70000\">",
        
"{g" => "</span><span style=\"color:#009d44\">",
        
"{b" => "</span><span style=\"color:#0000ff\">",
        
"{u" => "</span><span style=\"color:#8d6600\">",
        
"{D" => "</span><span style=\"color:#747474\">",
        
"{W" => "</span><span style=\"color:#d7d7d7\">",
        
"{v" => "</span><span style=\"color:#af00ff\">",
        
"{y" => "</span><span style=\"color:#ffff00\">"
        
"{R" => "</span><span style=\"color:#ff3030\">"
        
"{G" => "</span><span style=\"color:#00ff00\">",
        
"{B" => "</span><span style=\"color:#00ffff\">",
        
"{U" => "</span><span style=\"color:#c79d55\">",
        
"{e" => "</span><span class=\"elec\">",                        // Flicker classes
        
"{f" => "</span><span class=\"fire\">",
        
"{L" => "</span><span class=\"ligh\">",
        
"{a" => "</span><span class=\"acid\">",
        
"{c" => "</span><span class=\"cold\">",
        
"{I" => "</span><span class=\"invu\">",
        
"{m" => "</span><span class=\"mult\">",
        
"{h" => "</span><span class=\"half\">",
        
"{p" => "</span><span class=\"pois\">",
        
"{A" => "</span><span class=\"dark\">",
        
"{S" => "</span><span class=\"soun\">",
        
"{M" => "</span><span class=\"dist\">",
        
"{C" => "</span><span class=\"conf\">",
        
"{H" => "</span><span class=\"shar\">",
        
#"\n" => "<br />\n</span><span style=\"color:#f0f0f0\"></span>"            // Not used at the moment
    
);

    
$prereplace = array(                                    // Hacks for > and < characters. Mainly for arena events. Adds extra space.
        
"&lt;"    => "< ",
        
"&gt;"    => " >"
    
);

    
$origtext $text;

    
$text strtr(
            
tomenet_parse_flicker(                            // Parse flicker codes
                
tomenet_hack_inscription(                    // Excecute inscription hack
                    
strtr(                            // Hacks for < and > characters
                        
$text,$prereplace                
                    
)
                )
            ),
$replace                                // Replace colour codes with span-elements
        
);

?>
<!DOCTYPE html>
<HTML>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>TomeNET log converter ver 0.82b</title>
<style type="text/css">
div#logfield {
    color:#f0f0f0;
    background-color:#000000;
    <?php if($fixed) echo("font-family:\"Courier New\",Courier,courier,Monospace,monospace");?>
}
textarea { 
    resize:both; 
    width:60em;
    height:10em;
    <?php if($fixed) echo("font-family:\"Courier New\",Courier,courier,Monospace,monospace");?>
}
h1 {
    font-size:1em;
}
</style>

<script language="javascript" type="text/javascript">
    var flick = Array(                                // Order that flicker data is in next array (shortened to 4 chars)
        'fire',                                    // Fiery flicker is 1st data set in flickdata array etc...
        'elec',                                    // Electricity flicker etc.
        'ligh',
        'acid',
        'cold',
        'invu',
        'mult',
        'half',
        'pois',
        'dark',
        'soun',
        'dist',
        'conf',
        'shar'
    );    

    var flickdata = Array(                                                // Data for flickers, edit this for better looking flickers!
        Array( '#b70000', '#b70000', '#b70000', '#ff3030', '#ff3030', '#ffff00' ),                // The amount of same colour code makes it "more probable" to appear
        Array( '#0000ff', '#0000ff', '#0000ff', '#00ffff', '#00ffff', '#ffffff' ),                // so you can have "mostly blue" flicker with occasional accents etc
        Array( '#ff8d00', '#ff8d00', '#ffff00' ),
        Array( '#747474', '#747474', '#d7d7d7' ),
        Array( '#d7d7d7', '#d7d7d7', '#ffffff' ),                                
        Array( '#af00ff', '#ff3030', '#00ffff', '#00ff00', '#ffff00' ),                        // Invulnerability... Bright colours mostly ?
        Array( '#8d6600', '#9d9d9d', '#d7d7d7', '#0000ff', '#009d44', '#ffff00', "#ff0000", "#00ffff" ),    // Multi
        Array( '#00ff00', '#9d9d9d', '#ffffff', '#009d44', '#ffff00', "#ff3030", "#ff0000" ),            // Half-multi
        Array( '#009d44', '#009d44', '#00ff00' ),
        Array( '#9d9d9d', '#747474', '#747474' ),
        Array( '#c79d55', '#c79d55', '#ffff00' ),
        Array( '#ff3030', '#af00ff', '#ff8d00' ),                                // Distr shield
        Array( '#c79d55', '#c79d55', '#8d6600' ),
        Array( '#747474', '#747474', '#8d6600' )
    );

    function flicker() {
        for(d = 0; d < flick.length; d++){                        // Loop through flick array for different flickers
            
            var e = document.getElementsByClassName(flick[d]);            // Get every element with same type of flicker
                for(i = 0; i < e.length; i++){                    // Loop through every element
                    var r = Math.round(flickdata[d].length * Math.random() );        // Choose random flicker colour of corresponding flickdata
                    e[i].style.color = flickdata[d][r];            // Apply colour
             }  
        }
    } 
    
    function do_flicker() {
        flicker();
    }

    setInterval( 'do_flicker()', <?php echo($delay); ?> );                            // Do the flicker with 100ms (default) intervals.
</script>

</head>
<body>
<h1>TomeNET Log Converter v.0.82b</h1>
<div id="logfield">
<span>
<?php echo($text); ?>
</span>
</div>
<form method="POST">
<textarea name="log"><?php echo($origtext);?></textarea>
<br />
<input type="checkbox" value="fixed" name="fixed" <?php if($fixed) echo ("checked");?>>Use fixed-size font
<br />
<input type="submit" value="convert" name="convert">
</form>
<a href="?mode=source">Show source code</a>
<br />
Get <a href="http://shell.nullcore.fi/~djwolf/tomenet/template.txt">template.txt file</a> 
or <a href="http://shell.nullcore.fi/~djwolf/tomenet/template2.txt">full-length logdump file</a> for trying out the converter.
<br />
<br />
Options as url parameter:
<ul>
<li>/?delay=100, sets delay of 100ms</li>
<li>/?fixed=1, sets fixed font size</li>
<li>/?file=http://url/file.txt, opens file.txt from url</li>
<li>/?file=http://pastebin.com/yourpaste, opens yourpaste from pastebin.com</li>
</ul>
It is also possible to combine multiple parameters by using ?file=http://yoururl/yourfile.txt&fixed=1 for example.
</body>
</HTML>