/ json-test.php
json-test.php
1 <?php 2 /** 3 * JSON Dumper 4 * Dumps a thread into a .json file. 5 */ 6 7 if( !isset( $in_imgboard ) ) die( 'No direct access' ); 8 9 if( META_BOARD ) { 10 include_once 'plugins/enhance_q.php'; 11 } 12 13 function generate_thread_json( $threadid, $return = false, $replies = false, $for_catalogue = false, $tail = 0 ) 14 { 15 global $log, $thread_unique_ips; 16 if( !$log[$threadid] ) log_cache( 0, $threadid ); 17 $carr = array(); 18 19 $op = $log[$threadid]; 20 foreach( $op['children'] as $key => $val ) { 21 $carr[] = $key; 22 } 23 24 sort( $carr, SORT_NATURAL ); 25 26 $count = count( $carr ) + 1; 27 $replycount = $op['replycount']; 28 29 $build = ''; 30 $json = array(); 31 $extra = array(); 32 $imagecount = $op['imgreplycount']; 33 $tail_images = 0; 34 35 $extra['replies'] = $replycount; 36 $extra['images'] = $imagecount; 37 38 // Not inside a thread 39 if ($replies !== false) { 40 if ($replycount - $replies > 0) { 41 for ($i = $replycount - $replies; $i < $replycount; $i++) { 42 if ($log[$carr[$i]]['fsize'] && !$log[$carr[$i]]['filedeleted']) { 43 $tail_images++; 44 } 45 } 46 47 $extra['omitted_posts'] = $replycount - $replies; 48 $extra['omitted_images'] = $imagecount - $tail_images; 49 } 50 } 51 // Inside a thread 52 else if (SHOW_THREAD_UNIQUES) { 53 if ($thread_unique_ips) { 54 $unique_ips = (int)$thread_unique_ips; 55 } 56 else { 57 $unique_ips = get_unique_ip_count($threadid); 58 } 59 60 if ($unique_ips) { 61 $extra['unique_ips'] = $unique_ips; 62 } 63 } 64 65 //if( $replycount >= MAX_RES && !$op['permaage'] ) $extra['bumplimit'] = 1; 66 //if( $imagecount >= MAX_IMGRES && !$op['sticky'] ) $extra['imagelimit'] = 1; 67 68 $i = 1; 69 70 if ($op['semantic_url'] !== '') { 71 $extra['semantic_url'] = $op['semantic_url']; 72 } 73 74 if ($replies !== false) { 75 $i = $count - $replies; 76 77 if ($i < 1) { 78 $i = 1; 79 } 80 } 81 82 if ($for_catalogue) { 83 $json = generate_post_json( $op, $threadid, $extra ); // we do op before replies 84 if ($replycount > 0) { 85 $json['last_replies'] = array(); 86 for( ; $i < $count; $i++ ) { 87 if( isset( $log[$carr[$i - 1]] ) ) { 88 $var = $log[$carr[$i - 1]]; 89 $json['last_replies'][] = generate_post_json( $var, $threadid ); 90 } 91 } 92 if (META_BOARD) { 93 $capcode_replies = generate_capcode_replies($op['children']); 94 95 if ($capcode_replies) { 96 $json['capcode_replies'] = $capcode_replies; 97 } 98 } 99 } 100 101 $json['last_modified'] = (int)$log[$threadid]['last_modified']; 102 103 return $json; 104 } 105 else if ($tail) { 106 $json[] = generate_op_tail_json($op, $extra); 107 108 $lim = $count - $tail; 109 110 $tail_id = 0; 111 112 for (; $i < $count; $i++ ) { 113 if (isset($log[$carr[$i - 1]])) { 114 $var = $log[$carr[$i - 1]]; 115 if ($i < $lim) { 116 $tail_id = (int)$var['no']; 117 } 118 else { 119 $json[] = generate_post_json($var, $threadid); 120 } 121 } 122 } 123 124 $json[0]['tail_size'] = $tail; 125 $json[0]['tail_id'] = $tail_id; 126 127 $temp = array('posts' => $json); 128 } 129 else { 130 $json[] = generate_post_json( $op, $threadid, $extra ); // we do op before replies 131 132 $tailSize = get_json_tail_size($threadid); 133 134 if ($tailSize) { 135 $json[0]['tail_size'] = $tailSize; 136 } 137 138 for( ; $i < $count; $i++ ) { 139 if( isset( $log[$carr[$i - 1]] ) ) { 140 $var = $log[$carr[$i - 1]]; 141 $json[] = generate_post_json( $var, $threadid ); 142 } 143 } 144 145 if (META_BOARD) { 146 $capcode_replies = generate_capcode_replies($op['children']); 147 148 if ($capcode_replies) { 149 $json[0]['capcode_replies'] = $capcode_replies; 150 } 151 } 152 153 $temp = array('posts' => $json); 154 } 155 156 if( $return ) return $temp; 157 158 unset( $json ); 159 160 if (!$tail) { 161 $filename = RES_DIR . $threadid . '.json'; 162 } 163 else { 164 $filename = RES_DIR . $threadid . '-tail.json'; 165 } 166 $page = json_encode($temp); 167 print_page( $filename, $page, 0, 0 ); 168 169 return true; 170 } 171 172 function generate_capcode_replies($replies) { 173 global $log; 174 175 $capcode_replies = array( 176 'admin' => array(), 177 'developer' => array(), 178 'mod' => array() 179 ); 180 181 $has_capcode_replies = false; 182 183 foreach ($replies as $no => $val) { 184 if (!isset($log[$no])) { 185 continue; 186 } 187 $json_post = $log[$no]; 188 if ($json_post['capcode'] === 'none') { 189 continue; 190 } 191 if ($json_post['capcode'] === 'admin_highlight') { 192 $json_capcode = 'admin'; 193 } 194 else { 195 $json_capcode = $json_post['capcode']; 196 } 197 $capcode_replies[$json_capcode][] = (int)$no; 198 $has_capcode_replies = true; 199 } 200 201 if ($has_capcode_replies) { 202 $ret = array(); 203 foreach ($capcode_replies as $key => $value) { 204 if (empty($value)) { 205 continue; 206 } 207 $ret[$key] = $value; 208 } 209 return $ret; 210 } 211 else { 212 return null; 213 } 214 } 215 216 function post_json_force_type( &$post ) 217 { 218 static $post_intern = array( 219 'no' => 'integer', 220 'resto' => 'integer', 221 'sticky' => 'integer', 222 'closed' => 'integer', 223 'archived' => 'integer', 224 'now' => 'string', 225 'time' => 'integer', 226 'name' => 'string', 227 'trip' => 'string', 228 'id' => 'string', 229 'capcode' => 'string', 230 'country' => 'string', 231 'country_name' => 'string', 232 'sub' => 'string', 233 'com' => 'string', 234 'tim' => 'integer', 235 'filename' => 'string', 236 'ext' => 'string', 237 'fsize' => 'integer', 238 'md5' => 'string', 239 'w' => 'integer', 240 'h' => 'integer', 241 'tn_w' => 'integer', 242 'tn_h' => 'integer', 243 'filedeleted' => 'integer', 244 'spoiler' => 'integer', 245 'custom_spoiler' => 'integer', 246 'omitted_posts' => 'integer', 247 'omitted_images' => 'integer', 248 'replies' => 'integer', 249 'images' => 'integer', 250 'bumplimit' => 'integer', 251 'imagelimit' => 'integer', 252 'last_modified' => 'integer', 253 'archived_on' => 'integer', 254 'since4pass' => 'integer', 255 'm_img' => 'integer' 256 ); 257 258 259 foreach( $post as $key => $val) { 260 if( isset( $post_intern[$key] ) ) { 261 settype( $post[$key], $post_intern[$key] ); 262 } 263 } 264 } 265 266 function generate_op_tail_json($op, $extra) { 267 $ary = array(); 268 269 $ary['no'] = (int)$op['no']; 270 271 $ary['bumplimit'] = (int)$op['bumplimit']; 272 $ary['imagelimit'] = (int)$op['imagelimit']; 273 274 if ($op['sticky']) { 275 $ary['sticky'] = 1; 276 if ($op['undead']) { 277 $ary['sticky_cap'] = STICKY_CAP; 278 } 279 } 280 281 if ($op['closed']) { 282 $ary['closed'] = 1; 283 } 284 285 if ($op['archived']) { 286 $ary['archived'] = 1; 287 } 288 289 $ary['replies'] = (int)$extra['replies']; 290 $ary['images'] = (int)$extra['images']; 291 292 if (isset($extra['unique_ips'])) { 293 $ary['unique_ips'] = (int)$extra['unique_ips']; 294 } 295 296 if (SPOILERS) { 297 $ary['custom_spoiler'] = (int)SPOILER_NUM; 298 } 299 300 return $ary; 301 } 302 303 function generate_post_json( $var, $threadid, $extra = array(), $banskip = false ) 304 { 305 $COUNTRY_FLAG_ARR = array( 306 'sp', 307 'int', 308 ); 309 310 $FORCED_ANON_ARR = array( 311 'b', 312 'soc' 313 ); 314 315 $META_BOARD_ARR = array( 316 'q' 317 ); 318 319 if (UPLOAD_BOARD) { 320 $FLASH_TAGS = array( 321 0 => 'Hentai', 322 1 => 'Japanese', 323 2 => 'Anime', 324 3 => 'Game', 325 4 => 'Other', 326 5 => 'Loop', 327 6 => 'Porn', 328 ); 329 } 330 331 $SHOW_COUNTRY_FLAGS = $banskip ? in_array( $var['board'], $COUNTRY_FLAG_ARR ) : SHOW_COUNTRY_FLAGS; 332 $ENABLE_BOARD_FLAGS = $banskip ? false : ENABLE_BOARD_FLAGS; 333 $META_BOARD = $banskip ? in_array( $var['board'], $META_BOARD_ARR ) : META_BOARD; 334 $FORCED_ANON = $banskip ? in_array( $var['board'], $FORCED_ANON_ARR ) : FORCED_ANON; 335 336 if ($ENABLE_BOARD_FLAGS) { 337 $board_flags_array = get_board_flags_array(); 338 } 339 340 $country = $var['country']; 341 342 if ($ENABLE_BOARD_FLAGS && isset($board_flags_array[$var['board_flag']])) { 343 $board_flag = $var['board_flag']; 344 } 345 else { 346 $board_flag = ''; 347 } 348 349 if( $banskip && $var['ext'] ) { 350 $salt = file_get_contents( '/www/keys/legacy.salt' ); 351 $no = $var['no']; 352 353 $hash = sha1( $var['board'] . $no . $salt ); 354 $var['thumb'] = $hash; 355 } 356 357 $intern_host = $var['host']; 358 359 $unset = array( 360 'permasage', 361 'host', 362 'pwd', 363 'children', 364 'imgreplycount', 365 'replycount', 366 'last_modified', 367 'root', 368 '4pass_id' 369 ); 370 371 if ($banskip) { 372 $unset[] = 'protected'; 373 $unset[] = 'ua'; 374 } 375 376 $nunset = $unset; 377 378 $var['tim'] = (int)$var['tim']; 379 380 if( $var['filedeleted'] == 1 || !$var['ext'] ) { 381 $arr = array( 382 'tim', 383 'w', 384 'h', 385 'tn_w', 386 'tn_h', 387 'filename', 388 'ext', 389 'md5', 390 'fsize', 391 'tmd5' 392 ); 393 394 foreach( $arr as $key ) { 395 unset( $var[$key] ); 396 } 397 } 398 else { 399 // FIXME 400 $var['filename'] = mb_convert_encoding($var['filename'], 'UTF-8', 'UTF-8'); 401 } 402 403 // FIXME 404 $var['com'] = mb_convert_encoding($var['com'], 'UTF-8', 'UTF-8'); 405 406 if( !$var['filedeleted'] ) $nunset[] = 'filedeleted'; 407 408 // trim it up 409 foreach( $nunset as $key ) { 410 unset( $var[$key] ); 411 } 412 413 $is_archived = $var['archived']; 414 415 if( $var['resto'] ) { 416 unset( $var['sticky'] ); 417 unset( $var['closed'] ); 418 unset( $var['archived'] ); 419 } 420 else { 421 if (!$var['archived']) { 422 unset($var['archived']); 423 unset($var['archived_on']); 424 } 425 426 if (!$var['closed']) { 427 unset($var['closed']); 428 } 429 430 if (!$var['sticky']) { 431 unset($var['sticky']); 432 } 433 else { 434 if ($var['undead']) { 435 $var['sticky_cap'] = (int)STICKY_CAP; 436 } 437 unset( $var['bumplimit'], $var['imagelimit'] ); 438 } 439 440 if ($var['permaage']) { 441 unset( $var['bumplimit'] ); 442 } 443 } 444 445 if (!$var['m_img']) { 446 unset($var['m_img']); 447 } 448 449 if (!$var['since4pass']) { 450 unset($var['since4pass']); 451 } 452 // April 2024 453 else if ($var['since4pass'] >= 10000) { 454 $_stock = april_2024_get_stock_from_s4p($var['since4pass']); 455 456 if ($_stock) { 457 $var['xa24'] = $_stock; 458 } 459 460 unset($var['since4pass']); 461 } 462 463 unset($var['permaage'], $var['undead']); 464 465 // clean up names 466 if( strpos( $var['name'], '</span> <span class="postertrip">' ) !== false ) { 467 $name = explode( '</span> <span class="postertrip">', $var['name'] ); 468 $var['name'] = $name[0]; 469 $var['trip'] = $name[1]; 470 471 if( $var['trip'] && !$var['name'] ) unset( $var['name'] ); 472 } 473 474 if( !$banskip && SPOILERS && !$var['resto'] ) $var['custom_spoiler'] = (int)SPOILER_NUM; 475 476 $var['spoiler'] = 0; 477 if( strpos( $var['sub'], 'SPOILER<>' ) === 0 ) { 478 $var['sub'] = substr( $var['sub'], 9 ); 479 if( !$var['sub'] ) $var['sub'] = ''; 480 $var['spoiler'] = 1; 481 } else { 482 unset( $var['spoiler'] ); 483 } 484 485 if( $var['sub'] && !$var['resto'] && UPLOAD_BOARD ) { 486 if( preg_match( '/^(\d+)\|/', $var['sub'], $tag_matches ) ) { 487 $var['tag'] = $FLASH_TAGS[(int)$tag_matches[1]]; 488 $var['sub'] = preg_replace( '/^(\d+)\|/', '', $var['sub'] ); 489 } 490 } 491 492 if ( !$banskip ) { 493 if( !$var['id'] || $is_archived ) { 494 unset( $var['id'] ); 495 } elseif( $var['id'] && $var['no'] == $threadid && $var['capcode'] === 'none') { 496 $var['id'] = generate_uid( $var['no'], $var['time'], $intern_host ); 497 } 498 } 499 500 if ($var['capcode'] == 'none') { 501 if ($ENABLE_BOARD_FLAGS && $board_flag) { 502 unset($var['country']); 503 $var['flag_name'] = board_flag_code_to_name($board_flag); 504 } 505 else if ($SHOW_COUNTRY_FLAGS) { 506 unset( $var['board_flag'] ); 507 $var['country_name'] = country_code_to_name($country); 508 } 509 else { 510 unset($var['country']); 511 unset($var['country_name']); 512 unset($var['board_flag']); 513 } 514 } 515 else { 516 unset($var['country']); 517 unset($var['country_name']); 518 unset($var['board_flag']); 519 } 520 521 if( ( $FORCED_ANON || $META_BOARD ) && ( $var['capcode'] != 'admin' && $var['capcode'] != 'admin_hl' ) ) { 522 unset( $var['trip'] ); 523 $var['name'] = 'Anonymous'; 524 } 525 526 if( $var['capcode'] == 'none' ) unset( $var['capcode'] ); 527 if( !$banskip ) $var['com'] = auto_link( $var['com'], $threadid ); 528 if( !$banskip && isset( $var['md5'] ) ) $var['md5'] = base64_encode( pack( 'H*', $var['md5'] ) ); 529 530 if( $var['com'] == '' ) unset( $var['com'] ); 531 if(isset($var['email'])) unset( $var['email'] ); 532 if( $var['sub'] == '' ) unset( $var['sub'] ); 533 534 if( !empty( $extra ) ) { 535 foreach( $extra as $key => $val ) { 536 $var[$key] = $val; 537 } 538 } 539 540 post_json_force_type( $var ); 541 542 /// XXX: CHANGE TO TRIM WHITESPACE 543 return $var; 544 } 545 546 function generate_index_json( $return = false ) 547 { 548 549 global $log, $index_rbl; 550 log_cache( 0, 0 ); // generate all threads 551 552 $threads = $log['THREADS']; 553 554 $threadcount = count( $threads ); 555 556 // figure out how many replies to print 557 if (defined('REPLIES_SHOWN')) { 558 $replies_shown = REPLIES_SHOWN; 559 } 560 else { 561 $replies_shown = 5; 562 } 563 564 // Loop through every page 565 for( $page = 0; $page < $threadcount; $page += DEF_PAGES ) { 566 $file_page_num = $page / DEF_PAGES + 1; 567 568 if (PAGE_MAX && $file_page_num > PAGE_MAX) { 569 break; 570 } 571 572 $thread = $page; 573 $json = array(); 574 575 if( floor( $page / DEF_PAGES ) > $index_rbl ) return; 576 577 for( $i = $thread; $i < $thread + DEF_PAGES; $i++ ) { 578 list( $_unused, $threadid ) = each( $threads ); 579 580 if( !$threadid ) break; 581 582 if ($log[$threadid]['sticky'] == 1) { 583 $replies = min(1, $replies_shown); 584 } 585 else { 586 $replies = $replies_shown; 587 } 588 589 $json[] = generate_thread_json( $threadid, true, $replies ); 590 } 591 592 if( empty( $json ) ) return true; // we've reached the point of no return 593 594 $temp = json_encode( array('threads' => $json) ); 595 596 $filename = INDEX_DIR . ($page / DEF_PAGES + 1) . '.json'; 597 print_page( $filename, $temp, 0, 0 ); 598 } 599 600 return true; 601 } 602 603 // ↓ STICK IT TO THE MAN 604 function generate_board_catalogue() 605 { 606 //$json = generate_index_json( true ); 607 608 global $log, $index_rbl; 609 log_cache( 0, 0 ); // generate all threads 610 611 $threads = $log['THREADS']; 612 $threadcount = count( $threads ); 613 $curpage = 0; 614 615 $json = array(); 616 617 if (defined('REPLIES_SHOWN')) { 618 $replies_shown = REPLIES_SHOWN; 619 } 620 else { 621 $replies_shown = 5; 622 } 623 624 for( $page = 0; $page < $threadcount; $page += DEF_PAGES ) { 625 // Loop through each page... 626 627 $thispage = $page; 628 629 for( $i = $thispage; $i < $thispage + DEF_PAGES; $i++ ) { 630 list( $_unused, $threadid ) = each( $threads ); 631 632 if( !$threadid ) break; 633 634 if ($log[$threadid]['sticky'] == 1) { 635 $replies = min(1, $replies_shown); 636 } 637 else { 638 $replies = $replies_shown; 639 } 640 641 $json[$curpage][] = generate_thread_json( $threadid, false, $replies, true ); 642 643 } 644 645 $curpage++; 646 } 647 648 $build = array(); 649 650 foreach( $json as $page => $threads ) { 651 $thread = array( 652 'page' => $page + 1, 653 'threads' => $threads 654 ); 655 $build[] = $thread; 656 } 657 658 $page = json_encode($build); 659 print_page( INDEX_DIR . 'catalog.json', $page, 0, 0 ); 660 } 661 662 function generate_board_threads_json() 663 { 664 global $log; 665 log_cache( 0, 0 ); 666 667 $threads = $log['THREADS']; 668 $threadcount = count( $threads ); 669 $curpage = 0; 670 $json = array(); 671 672 for( $page = 0; $page < $threadcount; $page += DEF_PAGES ) { 673 $thispage = $page; 674 675 for( $i = $thispage; $i < $thispage + DEF_PAGES; $i++ ) { 676 list( $_unused, $threadid ) = each( $threads ); 677 678 if( !$threadid ) break; 679 680 $arr = array( 681 'no' => $threadid, 682 'last_modified' => $log[$threadid]['last_modified'], 683 'replies' => $log[$threadid]['replycount'] 684 ); 685 686 post_json_force_type($arr); 687 688 $json[$curpage][] = $arr; 689 690 } 691 692 $curpage++; 693 } 694 695 foreach( $json as $page => $threads ) { 696 697 $build[] = array( 698 'page' => $page + 1, 699 'threads' => $threads 700 ); 701 } 702 703 $page = json_encode( $build ); 704 print_page( INDEX_DIR . 'threads.json', $page, 0, 0 ); 705 } 706 707 function generate_board_archived_json() { 708 $query = "SELECT no FROM `" . BOARD_DIR . "` WHERE archived = 1 AND resto = 0 ORDER BY no ASC"; 709 710 $res = mysql_board_call($query); 711 712 if (!$res) { 713 return false; 714 } 715 716 $threads = array(); 717 718 while ($tid = mysql_fetch_row($res)[0]) { 719 $threads[] = $tid; 720 } 721 722 $page = '[' . implode(',', $threads) . ']'; 723 724 print_page(INDEX_DIR . 'archive.json', $page, 0, 0); 725 }