/ lib / oekaki-test.php
oekaki-test.php
  1  <?php
  2  
  3  // $file: $_FILES array entry for the .tgkr file
  4  // returns true if the replay file is valid,
  5  // false if the replay should be ignored, and errors out in all other cases.
  6  function oekaki_validate_replay($file) {
  7    $max_size = 6 * 1024 * 1024;
  8    $max_data_size = 15 * 1024 * 1024; // uncompresed size
  9    
 10    if ($file['error'] > 0) {
 11      error(S_FAILEDUPLOAD);
 12    }
 13    
 14    if ($file['size'] === 0) {
 15      error(S_NOREC);
 16    }
 17    
 18    if ($file['size'] > $max_size) {
 19      error(S_TOOLARGE);
 20    }
 21    
 22    $tmp_file = $file['tmp_name'];
 23    
 24    if (is_uploaded_file($tmp_file) !== true) {
 25      error(S_FAILEDUPLOAD);
 26    }
 27    
 28    // Check the actual data now
 29    
 30    $f = fopen($tmp_file, 'rb');
 31    
 32    $magic = fread($f, 4);
 33    
 34    $decompressed_size = fread($f, 4);
 35    
 36    fread($f, 4); // version numbers
 37    
 38    $compressed_data = fread($f, $file['size'] - 12);
 39    
 40    fclose($f);
 41    
 42    if ($magic !== "\x54\x47\x4B\x01") { // TGK 0x01
 43      error(S_NOREC);
 44    }
 45    
 46    $decompressed_size = (int)unpack('N', $decompressed_size)[1];
 47    
 48    if (!$decompressed_size || $decompressed_size <= 0) {
 49      error(S_NOREC);
 50    }
 51    
 52    if ($decompressed_size > $max_data_size) {
 53      return false;
 54    }
 55    
 56    if (!$compressed_data) {
 57      error(S_NOREC);
 58    }
 59    
 60    $data = gzinflate($compressed_data, $decompressed_size);
 61    
 62    if ($data === false) {
 63      error(S_NOREC);
 64    }
 65    
 66    $meta_size = (int)unpack('n', $data)[1];
 67    
 68    if (!$meta_size) {
 69      return false;
 70    }
 71    
 72    // tool count (byte), tool entry size (byte)
 73    $tool_meta = unpack('C2', substr($data, $meta_size, 2));
 74    
 75    if (!$tool_meta || !(int)$tool_meta[1] || !(int)$tool_meta[2]) {
 76      return false;
 77    }
 78    
 79    $events_pos = $meta_size + ((int)$tool_meta[1]) * ((int)$tool_meta[2]) + 2;
 80    
 81    $event_count = (int)unpack('N', substr($data, $events_pos, 4))[1];
 82    
 83    if (!$event_count || $event_count > 8640000) {
 84      return false;
 85    }
 86    
 87    $prelude_type = unpack('C', substr($data, $events_pos + 4, 1));
 88    
 89    if ($prelude_type === false || (int)$prelude_type[1] !== 0) {
 90      return false;
 91    }
 92    
 93    $conclusion_type = unpack('C', substr($data, -5, 1));
 94    
 95    if ($conclusion_type === false || (int)$conclusion_type[1] !== 255) {
 96      return false;
 97    }
 98    
 99    return true;
100  }
101  
102  function oekaki_get_valid_src_pid($src_pid, $board, $thread_id) {
103    $src_pid = (int)$src_pid;
104  
105    if ($src_pid < 1) {
106      return null;
107    }
108  
109    $thread_id = (int)$thread_id;
110  
111    if ($thread_id < 1) {
112      return null;
113    }
114    
115    $sql = "SELECT no FROM `%s` WHERE no = $src_pid AND (resto = $thread_id OR resto = 0) AND tim != 0 LIMIT 1";
116    
117    $res = mysql_board_call($sql, $board);
118    
119    if (!$res || mysql_num_rows($res) !== 1) {
120      return null;
121    }
122    
123    return $src_pid;
124  }
125  
126  function oekaki_format_info($time, $replay_tim, $src_pid) {
127    $time = (int)$time;
128    
129    if ($time < 1 || $time > 5184000) { // 60 days
130      return '';
131    }
132    
133    if ($time < 60) {
134      $time_str = $time . 's';
135    }
136    else if ($time < 3600) {
137      $time_str = round($time / 60) . 'm';
138    }
139    else {
140      $time_str = (int)($time / 3600) . 'h ' . round(($time % 3600) / 60) . 'm';
141    }
142    
143    if ($replay_tim && !$src_pid) {
144      $replay_tim = (int)$replay_tim;
145      $replay_link = ", Replay: <a href=\"javascript:oeReplay($replay_tim);\">View</a>";
146    }
147    else {
148      $replay_link = '';
149    }
150    
151    if ($src_pid) {
152      $src_pid = (int)$src_pid;
153      $src_link = ", Source: &gt;&gt;$src_pid";
154    }
155    else {
156      $src_link = '';
157    }
158    
159    return "<br><br><small><b>Oekaki Post</b> (Time: $time_str" . $replay_link . $src_link . ")</small>";
160  }