<?php
// -*- coding: sjis -*-

date_default_timezone_set("Asia/Tokyo");

$sitename = "アニ関Wiki過去ログうp支援ツール";
$wiki = "http://anikan.tv/index.php"; error_reporting(0);
$contact = make_wikilink($wiki, "dat保管ページ再構成プロジェクト");

$cookie_file = "cookie.txt";

$host_list = array("hayabusa2.2ch.net", "hayabusa.2ch.net", "uni.2ch.net",
		   "live28.2ch.net", "live24.2ch.net");
$bbs_list = array("livewkwest", "liveanime");
$bbsnames = array("anikan" => array("livewkwest", "西日本", "アニメ関西"),
		  "aniani" => array("liveanime", "アニ実", "(試)アニメ関西"),
		  "sinawa" => array("liveanime", "滋奈和", "滋賀奈良和歌山"));

$ua = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1)";

// ------------------------------------------------------------------------

function show($file)
{ 
  $fp = fopen($file, "r"); $r = "";
  while ($s = fgets($fp)) {
    $s = mb_convert_encoding($s, "UTF-8", "Shift_JIS");
    $s = htmlentities($s, ENT_QUOTES, "UTF-8");
    $s = mb_convert_encoding($s, "Shift_JIS", "UTF-8");
    $r .= $s;
  }
  fclose($fp);
  print "<html><body><hr><pre>{$r}</pre><hr></body></html>\n";
}

function get_dat_anikan($wiki, $page, $key, $refer = "")
{
  $url = "{$wiki}?plugin=attach&pcmd=open&file={$key}.dat.gz&refer={$page}";
  $z = url_get($url);
  $s = gzdecode($z);

  $e = mb_convert_encoding($s, "Shift_JIS", "EUC-JP");
  if (preg_match("/そのファイルは見つかりません/", $e)) {
    return NULL;
  }
  if (preg_match("|<title>アニ関Wiki - FrontPage</title>|", $e)) {
    return NULL;
  }

  return $s;
}

function make_head($host, $bbs, $key, $page, $refer)
{
  $s = "<a href=\"/dat2chex/\">TOP</a>";
  $u = sanitize(make_url($host, $bbs, $key));
  $s .= " <a href=\"{$u}\">元スレ</a>";
  $u = sanitize(make_dat2chex($host, $bbs, $key, $page));
  $s .= " <a href=\"{$u}\">閲覧</a>";
  $u = sanitize(make_cap($host, $bbs, $key, $page));
  $s .= " <a href=\"{$u}\">キャプ</a>";
  return $s;
}

function read_dat($wiki, $host, $bbs, $key, $page, $refer)
{
  if (!$page) {
    if (preg_match("|{$wiki}\?(.+)|", $refer, $m)) {
      $page = $m[1];
    }
  }

  $title = "閲覧";
  $head = make_head($host, $bbs, $key, $page, $refer);

  $s = get_dat_anikan($wiki, $page, $key, $refer);
  if (is_null($s)) {
    $url = sanitize(make_url($host, $bbs, $key));
    $r = "<a href=\"{$url}\">{$url}</a><br>\nのdatが";
    $r .= ($page) ? "{$page}に" : "";
    $r .= "見つかりません.<br>\n";
    $html = "<html><head><title>{$title}</title></head>";
    $html .= "<body bgcolor=#efefef><hr>{$head}<hr>{$r}<hr></body></html>\n";
    print $html; return;
  }

  $r = ""; 
  while (1) {
    $lines = explode("\n", $s); $a = explode("<>", $lines[0]);
    if (count($a) != 5) {
      $r .= "{$u} は壊れてます.<br>\n"; break;
    }
    list($name, $mail, $dateid, $res, $title) = $a;
    $safe_tags = array("<br>", "<b>", "</b>", "&gt;", "&lt;");
    $title = sanitize($title);
    $style = "color:red;font-size:larger;font-weight:normal;";    
    $r .= "<h1 style=\"{$style}\">{$title}</h1>";
    $r .= "<dl>\n";
    foreach ($lines as $i => $line) {
      $a = explode("<>", $line); $i++;
      if (count($a) != 5) {
	continue;
      }
      list($name, $mail, $dateid, $res) = $a;
      if ($dateid == "") {
	break;
      }

      $name = sanitize($name, $safe_tags);
      $mail = sanitize($mail);
      $dateid = sanitize($dateid);
      $res = preg_replace("/(<a.*?>|<\/a>)/", "", $res);
      $res = sanitize($res, $safe_tags);

      $re = "|h?(ttps?://[a-zA-Z0-9!\"#$%&'()/?.,@;:*+-=_~]+)|";
      $res = preg_replace($re, "<a href=\"h\\1\">h\\1</a>", $res);

      $r .=  "<dt>{$i} :";
      if ($mail == "") {
	$r .= "<font color=green><b>{$name}</b></font>:";
      } else {
	$r .= "<a href=\"mailto:{$mail}\"><b>{$name}</b></a>:";
      }
      $r .= "{$dateid}<dd>{$res}<br><br>\n";
    }
    $r .= "</dl>\n";
    break;
  }
  
  $html = "<html><head><title>{$title}</title></head>";
  $html .= "<body bgcolor=#efefef><hr>{$head}<hr>{$r}<hr></body></html>\n";
  print $html;
}

function show_cap($wiki, $host, $bbs, $key, $page, $refer)
{
  $title = "キャプ";
  $head = make_head($host, $bbs, $key, $page, $refer);

  $s = get_dat_anikan($wiki, $page, $key, $refer);
  if (is_null($s)) {
    $url = sanitize(make_url($host, $bbs, $key));
    $r = "<a href=\"{$url}\">{$url}</a><br>\nのdatが";
    $r .= ($page) ? "{$page}に" : "";
    $r .= "見つかりません.<br>\n";
    $html = "<html><head><title>{$title}</title></head>";
    $html .= "<body bgcolor=#efefef><hr>{$head}<hr>{$r}<hr></body></html>\n";
    print $html; return;
  }

  $r = ""; $n = 0;
  while (1) {
    $lines = explode("\n", $s); $a = explode("<>", $lines[0]);
    if (count($a) != 5) {
      $r .= "{$u} は壊れてます.<br>\n"; break;
    }
    list($name, $mail, $dateid, $res, $title) = $a;
    $safe_tags = array("<br>", "<b>", "</b>", "&gt;", "&lt;");
    $title = sanitize($title);
    $style = "color:red;font-size:larger;font-weight:normal;";    
    $r .= "<h1 style=\"{$style}\">{$title}</h1>";
    foreach ($lines as $i => $line) {
      $a = explode("<>", $line); $i++;
      if (count($a) != 5) {
	continue;
      }
      list($name, $mail, $dateid, $res) = $a;
      if ($dateid == "") {
	break;
      }

      $re = "!h?((ttp://[\w\!\"#$%&'()/?.,@;:*+-=_~]+)(jpe?g|gif|png))!";
      if (!preg_match_all($re, $res, $m)) {
	continue;
      }
      foreach ($m[1] as $u) {
	$r .= "<a href=\"h{$u}\" target=\"_blank\">h{$u}</a><br>\n"; $n += 1;
      }
    }
    $r .= "<br><br>\n{$n}枚の画像URLが見つかりました.<br>\n";
    break;
  }
  
  $html = "<html><head><title>{$title}</title></head>";
  $html .= "<body bgcolor=#efefef><hr>{$head}<hr>{$r}<hr></body></html>\n";
  print $html;

}

function edit($wiki, $page, $msg, $orig, $s = NULL)
{
  if (!$s) {
    $s = url_get("{$wiki}?cmd=edit&page={$page}");
  }
  if (!preg_match("/name=\"digest\" value=\"(\w+)\"/", $s, $m)) {
    return "";
  }
  $data = array ("cmd" => "edit", "write" => "",
		 "digest" => $m[1], "page" => $page, "msg" => $msg);
  $boundary = md5(time());
  $s = "--{$boundary}\r\n";
  foreach ($data as $k => $v) {
    $s .= "Content-Disposition: form-data; name=\"{$k}\"\r\n\r\n{$v}\r\n";
    $s .= "--{$boundary}\r\n";
  }
  $n = bytelen($s);

  $cookie = get_cookie();
  $h = $cookie ? "Cookie: {$cookie}\r\n" : "";
  $h .= "Content-Type: multipart/form-data; boundary={$boundary}\r\n";
  $h .= "Content-Length: {$n}\r\n";

  $http_response_header = "";
  $s = url_post($wiki, $h, $s, $http_response_header);
  set_cookie($http_response_header);
  return $s;
}

function attach($wiki, $page, $cont, $name)
{
  $data = array ("plugin" => "attach", "pcmd" => "post", "refer" => $page);
  $boundary = md5(time());
  $s = "--{$boundary}\r\n";
  foreach ($data as $k => $v) {
    $s .= "Content-Disposition: form-data; name=\"{$k}\"\r\n\r\n{$v}\r\n";
    $s .= "--{$boundary}\r\n";
  }
  $s .= "Content-Disposition: form-data;";
  $s .= " name=\"attach_file\"; filename=\"{$name}\"\r\n";
  $s .= "Content-Type: application/octet-stream\r\n";
  $s .= "Content-Transfer-Encoding: binary\r\n\r\n{$cont}\r\n";
  $s .= "--{$boundary}\r\n";
  $n = bytelen($s);

  $cookie = get_cookie();
  $h = $cookie ? "Cookie: {$cookie}\r\n" : "";
  $h .= "Content-Type: multipart/form-data; boundary={$boundary}\r\n";
  $h .= "Content-Length: {$n}\r\n";

  $http_response_header = "";
  $s = url_post($wiki, $h, $s, $http_response_header);
  set_cookie($http_response_header);
  return $s;
}

function akismet($wiki, $rcf, $rrf, $comment, $vars)
{
  $data = array ("cmd" => "akismet", "submitHam" => "GO",
		 "recaptcha_challenge_field" => $rcf,
		 "recaptcha_response_field" => $rrf);
  foreach ($comment as $k => $v) {
    $v = mb_convert_encoding(stripslashes($v), "EUC-JP", "Shift_JIS");
    $data["comment[{$k}]"] = $v;
  }
  foreach ($vars as $k => $v) {
    $v = mb_convert_encoding(stripslashes($v), "EUC-JP", "Shift_JIS");
    $data["vars[{$k}]"] = $v;
  }
  $boundary = md5(time());
  $s = "--{$boundary}\r\n";
  foreach ($data as $k => $v) {
    $s .= "Content-Disposition: form-data; name=\"{$k}\"\r\n\r\n{$v}\r\n";
    $s .= "--{$boundary}\r\n";
  }
  $n = bytelen($s);

  $cookie = get_cookie();
  $h = $cookie ? "Cookie: {$cookie}\r\n" : "";
  $h .= "Content-Type: multipart/form-data; boundary={$boundary}\r\n";
  $h .= "Content-Length: {$n}\r\n";

  $http_response_header = "";
  $s = url_post($wiki, $h, $s, $http_response_header);
  set_cookie($http_response_header);
  return $s;
}

function update($wiki, $host, $bbs, $key, $file = NULL)
{
  if (!is_valid_host($host)) {
    return warn("サーバ名が変です.<br><br>\n");
  }
  if (!is_valid_bbs($bbs)) {
    return warn("板フォルダ名が変です.<br><br>\n");
  }

  $url = make_url($host, $bbs, $key);
  $dat = make_dat($host, $bbs, $key);
  $bak = make_bg($host, $bbs, $key);
  $link = "<a href=\"{$url}\">{$url}</a><br>\ndat取得先: ";

  list($kako, $title0, $n0) = in_kako($host, $bbs, $key);

  //$a = array($file, $dat, $bak, "tv2ch");
  $a = array($file, $bak, "tv2ch");
  $n = -1;
  foreach ($a as $i => $u) {
    if (!$u) {
      continue;
    } else if ($u == "tv2ch") {
      $u = make_tv2ch($host, $bbs, $key);
      $s = get_dat_tv2ch($host, $bbs, $key);
    } else {
      $s = url_get($u);
    }
    if ($file) {
      $link .= "FILE ";
    } else {
      $link .= "<a href=\"{$u}\">{$i}</a> ";
    }
    $re = "/(.*)<>(.*)<>(.*)<>(.*)<>(.*)/";
    if (!preg_match_all($re, $s, $lines, PREG_SET_ORDER)) {
      if ($file) {
	return warn("datが壊れてます.<br><br>\n");
      }
      continue;
    }
    if ($lines[0][1] == "短パンマン ★") {
      continue;
    }
    if ($lines[3][1] == "過去ログ ★") {
      continue;
    }
    $n = count($lines);
    if ($n == $n0) {
      break;
    } else {
      $n = -1;
    }
  }
  $link .= "<br><br>\n";

  if ($n < 0) {
    return warn("datを取得できませんでした.<br>\n") . $link;
  }

  $title = $lines[0][5]; $len = bytelen($title);
  if (($len > 48) or ($len < 1) or ($title != $title0)) {
    return warn("スレタイが変です.({$len}bytes)<br>\n") . $link;
  }
  $link = sanitize($title) . "<br>\n" . $link;

  if (($n < 1000) and !$kako) {
    return warn("1000まで埋まってません.") . "({$n}lines)<br>\n" . $link;
  }

  $entry = make_entry($bbs, $key, $title, $url, $lines[$n-2][3], $n);
  if (!$page = get_page($bbs, $key, $title)) {
    $r = warn("板フォルダ名とスレタイを確認してください.<br>\n") . $link;
    $r .= "正しいスレなら<a href=\"{$wiki}\">Wiki</a>から";
    $r .= "直接添付して下の行をテーブルに追加してください.<br>\n";
    $r .= "追加行:<br>\n" . sanitize($entry) . "<br>\n";
    return $r;
  }

  $z = gzencode($s, 9); $u = make_wikilink($wiki, $page); $r = $link;

  $keys = get_keys_attached($wiki, $page);
  if (in_array($key, $keys)) {
    $r .= "{$u} に同じ名前のdatファイルが添付されてます.<br>\n";
  } else {
    $s = attach($wiki, $page, $z, "{$key}.dat.gz");
    if (($akismet = get_akismet_form($s)) !== false) {
      $r .= "dat添付中にキャプチャ認証にひっかかりました.<br>\n";
      $r .= "{$u} にgzip圧縮したdatを手動で添付してください.<br>\n";
      $r .= "頻繁にひっかかる場合は下記連絡先にコメントしてください.<br>\n";
      //$r .= $akismet;
    } else {
      if (preg_match("/<title>(.*?)<\/title>/", $s, $m)) {
	$r .= mb_convert_encoding("{$m[1]}<br>\n", "Shift_JIS", "EUC-JP");
	$r .= "<!-- ATTACH COMPLETE -->\n";
      } else {
	$r .= warn("{$u} に添付できませんでした.<br>\n");
      }
    }
    //$r .= "※話がまとまるまで添付機能は停止してます.(消せないので)<br>\n";
  }
  
  $s = url_get("{$wiki}?cmd=edit&page={$page}");
  $s = mb_convert_encoding($s, "Shift_JIS", "EUC-JP");
  $q = "<textarea name=\"msg\" rows=\"20\" cols=\"80\">";
  $i = strpos($s, $q) + strlen($q);
  if ($i === false) {
    return warn("{$page} を編集できません.<br><br>\n");
  }
  $q = "</textarea>";
  $j = strpos($s, $q, $i);
  if ($j === false) {
    return warn("{$page} を編集できません.<br><br>\n");
  }
  $msg = html_entity_decode(substr($s, $i, $j - $i));

  if (in_page($entry, $msg)) {
    $r .= "{$u} のテーブルに同じ項目が存在します.<br>\n";
  } else {
    $s = edit($wiki, $page, insert_entry($entry, $msg, $bbs), $msg, $s);
    if (($akismet = get_akismet_form($s)) !== false) {
      $r .= "テーブル追加中にキャプチャ認証にひっかかりました.<br>\n";
      $r .= $akismet;
    } else {
      $s = mb_convert_encoding($s, "Shift_JIS", "EUC-JP");
      if (strpos($wiki, "http://anikan.tv/") === 0) {
	$success = "<title>アニ関Wiki - {$page}</title>";
      } else {
	$success = "<title>{$page} - PukiWiki</title>";
      }
      if (strpos($s, $success) !== false) {
	$r .= "{$u} のテーブルに追加しました.<br>\n";
      } else {
	$f = dump("{$msg}--\n\n{$entry}--\n\n{$s}");
	$r .= warn("{$u} のテーブルに追加できませんでした.");
	$r .= "→ <a href=\"{$f}\">{$f}</a><br>\n";
      }
    }
    $r .= "追加行:<br>\n" . sanitize($entry) . "<br><br>\n";
  }

  return "<hr>{$r}<br>\n";
}

function fetch($wiki, $url)
{
  $s = "";
  $re = "|http://([^/]+)/test/read\.cgi/(\w+)/(\d{10})|";
  for ($i = 0; $i < count($url); $i++) {
    if ($url[$i] == "") {
      continue;
    }
    if (!preg_match($re, $url[$i], $m)) {
      return warn("URLが変です.<br><br>\n");
    }
    $s1 = update($wiki, $m[1], $m[2], $m[3]); $s .= $s1;

    if (preg_match("/<!-- ATTACH COMPLETE -->/m", $s1) > 0) {
      save_update_log($m[1], $m[2], $m[3]);
    }
  }
  return $s;
}

function upload($wiki, $host, $bbs, $name, $tmp_name, $size, $error)
{
  $s = "";
  for ($i = 0; $i < count($tmp_name); $i++) {
    if ($tmp_name[$i] == "") {
      continue;
    }
    if (!is_uploaded_file($tmp_name[$i])) {
      return warn("何かおかしい.<br><br>\n");
    }
    if ($error[$i] != 0) {
      return warn("アップロードに失敗しました.<br><br>\n");
    }
    if (!preg_match("/^(\d{10})\.dat/", $name[$i], $m)) {
      return warn("datファイル名が変です.<br><br>\n");
    }
    if (($size[$i] > 600*1024) || ($size[$i] == 0)) {
      return warn("datファイルサイズが変です.<br><br>\n");
    }
    $s .= update($wiki, $host, $bbs, $m[1], $tmp_name[$i]);
  }
  return $s;
}

function check($wiki, $page, $host)
{
  if (preg_match("/2chdat[\/_]liveanime/", $page)) {
    $bbs = "liveanime";
  } else if (preg_match("/2chdat[\/_]\d+/", $page)) {
    $bbs = "livewkwest";
  } else {
    return warn("ページ名が変です.<br><br>\n");
  }

  if (!is_valid_host($host)) {
    return warn("サーバ名が変です.<br><br>\n");
  }

  $u = make_wikilink($wiki, $page);
  $keys = get_keys_attached($wiki, $page);
  if (is_null($keys)) {
    return warn("{$u} に添付ファイルがありません.<br><br>\n");
  }

  $s = get_source($wiki, $page);
  if (preg_match("|2chdat_\d+-\d+|", $page)) {
    $re = "/^\|(\d{10})\|&ref\(\.\/(\d{10})\.dat\.gz\);\|";
    $re .= "\[\[(.+?):(.+?)\]\](.*?)\|/m";
    if (!preg_match_all($re, $s, $m, PREG_SET_ORDER)) {
      $m = array();
    }
    $old = true;
  } else {
    $m = find_entry($s); $old = false;
  }
  $table = array(); $keys_in_table = array();
  foreach ($m as $x) {
    $table[] = $x[0]; $keys_in_table[] = $x[2];
  }

  $kakolog = get_kakolog($host, $bbs); $s = "";
  foreach ($keys as $k => $key) {
    $i = array_search($key, $keys_in_table);
    if ($i !== false) {
      $entry = $table[$i];
    } else {
      $url = make_url($host, $bbs, $key);
      $title = get_title($kakolog, $key);
      if ($old) {
	$entry = make_entry_old($bbs, $key, $title, $url);
      } else {
	$entry = make_entry($bbs, $key, $title, $url);
      }
    }
    $s = insert_entry($entry, rtrim($s, "\n"), $bbs);
  }

  $r = "{$u} に添付されてるのにテーブルにはないスレを";
  $r .= warn("赤字") . "で表示します.<br>\n";
  $r .= "必要なら保管庫を手動で編集してください";
  $r .= "(不明になってるスレタイとdatの終了日時は";
  $r .= "自分で書き換えてください).<br><br>\n";
  foreach (explode("\n", $s) as $line) {
    $e = find_entry($line, 1);
    $r .= in_array($e[2], $keys_in_table) ? $line : warn($line);
    $r .= "<br>\n";
  }
  $r .= "<br>\n";
  
  return $r;
}

function get_source($wiki, $page)
{
  $s = url_get("{$wiki}?cmd=source&page=${page}");
  $q = "<div id=\"body\"><pre id=\"source\">";
  $i = strpos($s, $q) + strlen($q);
  if ($i === false) {
    return false;
  }
  $q = "</pre></div>";
  $j = strpos($s, $q, $i);
  if ($j === false) {
    return false;
  }
  $s = substr($s, $i, $j - $i);
  $s = html_entity_decode($s);
  $s = mb_convert_encoding($s, "Shift_JIS", "EUC-JP");
  return $s;
}

function get_keys_attached($wiki, $page)
{
  $url = "{$wiki}?plugin=attach&pcmd=list&refer={$page}";
  $s = url_get($url);
  $re = "/plugin=attach&amp;pcmd=info&amp;file=(\d{10})\.dat\.gz/";
  if (!preg_match_all($re, $s, $m)) {
    return array();
  }
  $keys = $m[1]; sort($keys);
  return $keys;
}

function in_kako($host, $bbs, $key)
{
  $url = "http://{$host}/{$bbs}/subject.txt";
  $s = url_get($url);
  if (!preg_match_all("/(\d{10})\.dat<>(.*) \((\d+)\)/", $s, $m)) {
    return NULL;
  }
  $i = array_search($key , $m[1]);
  if ($i !== false) {
    return array(false, $m[2][$i], $m[3][$i]);
  }

  $url = make_dat($host, $bbs, $key);
  $s = url_get($url, $x = NULL, true);
  $re = "/(.*)<>(.*)<>(.*)<>(.*)<>(.*)/";
  if (!preg_match_all($re, $s, $lines, PREG_SET_ORDER)) {
    return NULL;
  }
  if (preg_match("/^(\d+), (\d+) /", $lines[1][1], $m)) {
    return array(true, $lines[0][5], $m[1]);
  }

  return NULL;
}

function in_page($entry, $s)
{
  $e = find_entry($entry, 1);
  $m = find_entry($s);
  foreach ($m as $x) {
    if (($e[2] == $x[2]) and ($e[3] == $x[3]) and ($e[4] == $x[4])) {
      return true;
    }
  }
  return false;
}

function make_url($host, $bbs, $key)
{
  return "http://{$host}/test/read.cgi/{$bbs}/{$key}/";
}

function make_dat($host, $bbs, $key)
{
  return "http://{$host}/{$bbs}/dat/{$key}.dat";
}

function make_bg($host, $bbs, $key)
{
  return "http://bg20.2ch.net/test/r.so/{$host}/{$bbs}/{$key}/";
}

function make_dat2chex($host, $bbs, $key, $page = NULL)
{
  $url = "http://anikan.pa.land.to/dat2chex/";
  $url .= "{$host}/{$bbs}/{$key}/";
  if ($page) {
    $url .= "?p={$page}";
  }
  return $url;
}

function make_cap($host, $bbs, $key, $page)
{
  $url = "http://anikan.pa.land.to/dat2chex/";
  $url .= "{$host}/{$bbs}/{$key}/?cap&p={$page}";
  return $url;
}

function make_entry($bbs, $key, $title, $url, $te = "", $n = NULL)
{
  $t0 = get_date(date("Y/m/d H:i", $key));
  $t1 = get_date($te);
  $note = (!is_null($n) and ($n != 1001)) ? "({$n}まで)" : "";

  if ($bbs == "livewkwest") {
    $e = "|{$t0[2]}{$t0[3]}|{$t0[4]}:{$t0[5]}〜{$t1[4]}:{$t1[5]}|";
  } else {
    $e = "|{$t0[1]}/{$t0[2]}{$t0[3]} {$t0[4]}:{$t0[5]}〜";
    $e .= "{$t1[1]}/{$t1[2]}{$t1[3]} {$t1[4]}:{$t1[5]}|";
  }  
  $e .= "&ref(./{$key}.dat.gz);|[[{$title}:{$url}]]{$note}|";

  $page = urlencode(get_page($bbs, $key, $title));
  if (preg_match("|http://(.+?)/test/read\.cgi/(\w+)/(\d+)|", $url, $m)) {
    list($url, $host, $bbs, $key) = $m;
    $url = make_dat2chex($host, $bbs, $key);
    //$url = make_tv2ch($host, $bbs, $key) . "&ls=1-10";
    $e .= "[[閲覧:{$url}]]|";
  } else {
    $e .= "閲覧|";
  }
  return $e;
}

function make_entry_old($bbs, $key, $title, $url)
{
  return "|{$key}|&ref(./{$key}.dat.gz);|[[{$title}:{$url}]]|";
}

function find_entry($s, $n = NULL)
{
  $re = "/^\|([^\|]*)\|?[^\|]*\|";
  $re .= "&ref\(.+?\/(\d{10}).+?\);\|";
  $re .= "\[\[(.+?):(.+?)\]\](.*?)\|.*?\|/m";
  if (!preg_match_all($re, $s, $m, PREG_SET_ORDER)) {
    $m = array();
  }
  if (!is_null($n)) {
    if ($n == 1) {
      return array_shift($m);
    }
    if ($n == -1) {
      return array_pop($m);
    }
  }
  return $m;
}

function insert_entry($entry, $msg, $bbs)
{
  $e = find_entry($entry, 1);
  $z = find_entry($msg, -1);
  $r = ""; $day = ""; $done = false;
  foreach (explode("\n", $msg) as $line) {
    if ($done or !(($x = find_entry($line, 1)) and (count($x) > 0))) {
      $r .= "{$line}\n"; continue;
    }
    if ($x[2] > $e[2]) {
      if (($bbs == "livewkwest") and ($e[1] == $day)) {
	$e[0] = str_replace($e[1], "~", $e[0]);
      }
      if (($bbs == "livewkwest") and ($e[1] == $x[1])) {
	$x[0] = str_replace($x[1], "~", $x[0]);
      }
      $r .= "{$e[0]}\n"; $done = true;
    }
    $r .= "{$x[0]}\n"; ($x[1] != "~") and $day = $x[1];
    if (!$done and ($x == $z)) {
      if (($bbs == "livewkwest") and ($e[1] == $day)) {
	$e[0] = str_replace($e[1], "~", $e[0]);
      }
      $r .= "{$e[0]}\n"; $done = true;
    }
  }
  if (!$done) {
    $r .= "{$e[0]}\n";
  }

  return $r;
}

function make_wikilink($wiki, $page, $name = NULL)
{
  if (!$name) {
    $name = $page;
  }
  $page = urlencode(mb_convert_encoding($page, "EUC-JP", "Shift_JIS"));
  return "<a href=\"{$wiki}?{$page}\">{$name}</a>";
}

function get_title($kakolog, $key)
{
  return $kakolog[$key] ? $kakolog[$key] : "(スレタイ不明)";
}

//function get_range($s1, $s2 = "")
//{
//  $re = "/([\d\/]+)\(..\) (\d+:\d+)/";
//  if (preg_match($re, $s1, $m)) {
//    $range = get_date($m[1], $m[2]) . "〜";
//    if (preg_match($re, $s2, $m)) {
//      $range .= get_date("", $m[2]);
//    }
//  } else if (preg_match($re, $s2, $m)) {
//    $range = "〜" . get_date($m[1], $m[2]);
//  }
//  return $range;
//}

function get_date($s, $dateline = 5)
{
  list($y, $m, $d, $w, $h, $i) = array("==", "==", "==", 8, "==", "==");
  $a = array("日", "月", "火", "水", "木", "金", "土", "日", "==");

  $day = preg_match("/[\d\/]+/", $s, $m) ? $m[0] : "";
  $time = preg_match("/\d+:\d+/", $s, $m) ? $m[0] : "";
  if (($day == "") and ($time == "")) {
    return array($y, $m, $d, "(==)", $h, $i);
  }
  $t = strtotime("{$day} {$time}");

  list($h, $i) = explode(":", date("H:i", $t));
  if ($h < $dateline) {
    $h += 24; $t -= 24*3600;
  }
  
  list($y, $m, $d, $w) = explode("/", date("Y/m/d/w", $t));
  if (($w == 0) or !is_null(is_holiday($y, $m, $d))) {
    $wday = "&color(red){{$a[$w]}};";
  } else if ($w == 6) {
    $wday = "&color(blue){{$a[$w]}};";
  } else {
    $wday = $a[$w];
  }

  return array($y, $m, $d, "({$wday})", $h, $i);
}

function get_page($bbs, $key, $title = "", $dateline = 5)
{
  $t = $key - $dateline * 3600;
  $y = date("Y", $t);
  $m = date("m", $t);

  //switch($m) {
  //case  1: case  2: case  3: $m =  "1"; break;
  //case  4: case  5: case  6: $m =  "4"; break;
  //case  7: case  8: case  9: $m =  "7"; break;
  //case 10: case 11: case 12: $m = "10"; break;
  //}
  //switch($m) {
  //case  1: case  2: case  3: $m = "01-03"; break;
  //case  4: case  5: case  6: $m = "04-06"; break;
  //case  7: case  8: case  9: $m = "07-09"; break;
  //case 10: case 11: case 12: $m = "10-12"; break;
  //}

  if (is_anikan($bbs, $title)) {
    return "2chdat/{$y}/{$m}";
  }
  if (is_aniani($bbs, $title)) {
    return "2chdat/{$bbs}/{$y}";
  }
  if (is_sinawa($bbs, $title)) {
    return "2chdat/{$bbs}/SNW";
  }
  return false;
}

function is_anikan($bbs, $title)
{
  if ($bbs != "livewkwest") {
    return false;
  }
  if (!preg_match("/関/", $title)) {
    return false;
  }
  if (!preg_match("/アニ|アニ|ニメ|ニメ/", $title)) {
    return false;
  }
  if (preg_match("/\(試\)/", $title)) {
    return false;
  }
  return true;
}

function is_aniani($bbs, $title)
{
  if ($bbs != "liveanime") {
    return false;
  }
  if (!is_anikan("livewkwest", str_replace("(試)", "", $title))) {
    return false;
  }
  if (!preg_match("/\(試\)/", $title)) {
    return false;
  }
  return true;
}

function is_sinawa($bbs, $title)
{
  if ($bbs != "liveanime") {
    return false;
  }
  if (!preg_match("/(滋賀|奈良|和歌山){2}/", $title)) {
    return false;
  }
  return true;
}

function is_valid_host($host)
{
  global $host_list;
  if (in_array($host, $host_list)) {
    return true;
  }
  if (preg_match("|^\w+\.2ch\.net$|", $host)) {
    return true;
  }
  return false;
}

function is_valid_bbs($bbs)
{
  global $bbs_list; return in_array($bbs, $bbs_list);
}

function get_akismet_form($s)
{
  $r = "<input type=\"hidden\" name=\"cmd\" value=\"akismet\">";
  if (strpos($s, $r) === false) {
    return false;
  }
  $re = "|(<form.+?>)(.+?)(<script.+?/script>.*?)<noscript>(.+?)</noscript>|s";
  if (!preg_match($re, $s, $m)) {
    return false;
  }
  $re = "|<form action=\".+?\" method=\"post\">|";
  $to = "<form action=\"./\" method=\"post\">";
  $r = preg_replace($re, $to, $m[1]);
  $r .= mb_convert_encoding($m[2], "Shift_JIS", "UTF-8");
  //$r .= $m[3];
  $r .= $m[4];
  
  $re = "|</noscript>( .+</form>)|s";
  if (!preg_match($re, $s, $m)) {
    return false;
  }
  $r .= mb_convert_encoding($m[1], "Shift_JIS", "EUC-JP");
  //$r .= $m[1];

  return $r;
}

function get_kakolog($host, $bbs)
{
  $url = "http://{$host}/{$bbs}/kako/subject.txt";
  $s = url_get($url);
  if (!preg_match_all("/(o\d{4})<>(\d{4}) \(\d+\)/", $s, $m)) {
    return false;
  }
  $ords = $m[1]; $kakolog = array();

  $re = "/(\d{10})\.dat<>(.+) \(\d+\)/";
  foreach ($ords as $ord) {
    $url = "http://{$host}/{$bbs}/kako/{$ord}/subject.txt";
    $s = url_get($url);
    if (!preg_match_all($re, $s, $m, PREG_SET_ORDER)) {
      continue;
    }
    foreach ($m as $x) {
      $kakolog[$x[1]] = $x[2];
    }
    if (count($kakolog) > 500) {
      break;
    }
  }

  $url = "http://{$host}/{$bbs}/subject.txt";
  $s = url_get($url);
  if (preg_match_all($re, $s, $m, PREG_SET_ORDER)) {
    foreach ($m as $x) {
      $kakolog[$x[1]] = $x[2];
    }
  }

  return $kakolog;
}

function url_get($url, &$r = NULL, $ignore_errors = false)
{
  global $ua;
  $q = array("method" => "GET", "header" => "User-Agent: {$ua}");
  if ($ignore_errors) {
    $q["ignore_errors"] = true;
  }
  $p = array("http" => $q);
  $s = file_get_contents($url, false, stream_context_create($p));
  if (!is_null($r)) {
    $r = $http_response_header;
  }
  return $s;
}

function url_post($url, $h, $s, &$r = NULL)
{
  global $ua;
  $h = "User-Agent: {$ua}\r\n{$h}";
  $q = array("method"  => "POST", "header"  => $h, "content" => $s);
  $p = array("http" => $q);
  $s = file_get_contents($url, false, stream_context_create($p));
  if (!is_null($r)) {
    $r = $http_response_header;
  }
  return $s;
}

function get_cookie()
{
  global $cookie_file;
  $s = file_get_contents($cookie_file);
  return rtrim($s, "\n");
}

function set_cookie($headers)
{
  $s = get_cookie();
  if ($s) {
    $headers = array_unshift($headers, "Set-Cookie: {$s}");
  }

  $a = array();
  foreach ($headers as $h) {
    if (!preg_match("/^Set-Cookie:/", $h)) {
      continue;
    }
    if (!preg_match("/(PHPSESSID)=([a-z0-9]+);/", $h, $m)) {
      continue;
    }
    $a[$m[1]] = $m[2];
  }
  if (!count($a)) {
    return;
  }

  $s = "";
  foreach ($a as $k => $v) {
    $s .= "{$k}={$v}; ";
  }

  global $cookie_file;
  file_put_contents($cookie_file, $s, LOCK_EX);
}

function make_tv2ch($host, $bbs, $key, $u = NULL)
{
  $p2 = "http://tv2ch.net/p2";
  if (!is_null($u)) {
    if (preg_match("|http://(.+?)/test/read\.cgi/(\w+)/(\d+)|", $u, $m)) {
      list($u, $host, $bbs, $key) = $m;
    }
  }
  return "{$p2}/read.php?host={$host}&bbs={$bbs}&key=${key}&maru=true";
}

function get_dat_tv2ch($host, $bbs, $key)
{
  $url = make_tv2ch($host, $bbs, $key);
  $http_response_header = "";
  $s = url_get($url, $http_response_header);
  foreach ($http_response_header as $h) {
    if (preg_match("/Set-Cookie: PS=(.+?);/", $h, $m)) {
      $ps = $m[1]; break;
    }
  }

  $s = "form_login_id=2ch&form_login_pass=2ch&submit_member=過去ログ閲覧";
  $n = bytelen($s);

  $h = "Cookie: PS={$ps}; \r\n";
  $h .= "Content-Type: application/x-www-form-urlencoded\r\n";
  $h .= "Content-Length: {$n}\r\n";

  $r = url_post($url, $h, $s);
  $r = url_post(str_replace("read.php", "dat.php", $url), $h, $s);
  $r = preg_replace("/\?PS=\w+/", "", $r);
  return $r;
}

function save_update_log($host, $bbs, $key)
{
  $now = time();
  $file = "update.log"; $s = "";
  if (file_exists($file)) {
    $s = file_get_contents($file);
    $s = implode("\n", array_slice(explode("\n", $s), -2000));
  }
  $s .= "{$now}\t{$bbs}\t{$key}\n";
  file_put_contents($file, $s, LOCK_EX);
}

function dump($s)
{
  $file = time() . ".txt";
  file_put_contents($file, $s, LOCK_EX);
  return $file;
}

function warn($s)
{
  return "<font color=red>{$s}</font>";
}

function sanitize($s, $safe_tags = NULL)
{
  if (!is_null($safe_tags)) {
    $tags = array();
    foreach ($safe_tags as $i => $tag) {
      $tags[$i] = sanitize($tag);
    }
    $s = htmlspecialchars($s, ENT_QUOTES);
    $s = str_replace($tags, $safe_tags, $s);
  } else {
    $s = htmlspecialchars($s, ENT_QUOTES);
  }
  return $s;
}

function make_bbs_radio($bbs_list, $bbs)
{
  $s = "";
  foreach ($bbs_list as $k) {
    $c = ($k == $bbs) ? " checked" : "";
    $s .= "<input type=\"radio\" name=\"bbs\" value=\"{$k}\"{$c}>{$k} ";
  }
  return $s;
}

function is_holiday($y, $m, $d)
{
  $t = strtotime("{$y}/{$m}/{$d}");
  $day = date("Y/m/d", $t);
  $min = date("Y-m-d", $t);
  $max = date("Y-m-d", $t + 24*3600);
  $url = "http://www.google.com/calendar/feeds/";
  $url .= "japanese__ja@holiday.calendar.google.com/public/basic";
  $url .= "?start-min={$min}&start-max={$max}";
  $s = url_get($url);
  $s = mb_convert_encoding($s, "Shift_JIS", "UTF-8");
  if (preg_match_all("|<entry>.+?</entry>|s", $s, $m, PREG_SET_ORDER)) {
    if (count($m) == 1) {
      if (preg_match("|<title.*?>(.+?)</title>.+?: {$day}|s", $m[0][0], $r)) {
	return $r[1];
      }
    }
  }
  return NULL;
}

function bytelen($data)
{
  return strlen(bin2hex($data)) / 2;
}

function gzdecode($data){
  $g=tempnam('/tmp','ff');
  @file_put_contents($g,$data);
  ob_start();
  readgzfile($g);
  $d=ob_get_clean();
  return $d;
}

// ------------------------------------------------------------------------
// main



if (isset($_SERVER["SCRIPT_NAME"])) {
  $a = explode("/", $_SERVER["SCRIPT_NAME"]); $me = end($a);
  $a = explode(".", $me); $e = array_pop($a);
  $old = implode(".", $a) . "-old.{$e}";
}

if (isset($_REQUEST["source"])) {
  show($me); exit;
}

if (isset($_SERVER["HTTP_REFERER"])) {
  $refer = $_SERVER["HTTP_REFERER"];
} else {
  $refer = $wiki;
}

if (isset($_REQUEST["read"])) {
  read_dat($wiki, $_REQUEST["host"], $_REQUEST["bbs"], $_REQUEST["key"],
	   $_REQUEST["page"], $refer); exit;
}
if (isset($_REQUEST["cap"])) {
  show_cap($wiki, $_REQUEST["host"], $_REQUEST["bbs"], $_REQUEST["key"],
	   $_REQUEST["page"], $refer); exit;
}


if (isset($_POST["cmd"]) and ($_POST["cmd"] == "akismet")) {
  akismet($wiki,
	  $_POST["recaptcha_challenge_field"],
	  $_POST["recaptcha_response_field"],
	  $_POST["comment"], $_POST["vars"]);
  header("Location: {$wiki}?{$_POST["vars"]["page"]}"); exit;
}

$now = time();
foreach ($bbsnames as $k => $v) {
  $pages[$k] = get_page($v[0], $now, $v[2]);
  $links[$k] = make_wikilink($wiki, $pages[$k], $v[1]);
}

if (isset($_POST["url"])) {
  $url = $_POST["url"];
} else {
  $url = "";
}

if (isset($_POST["host"])) {
  $host = $_POST["host"];
} else {
  $host = $host_list[0];
}

if (isset($_POST["bbs"])) {
  $bbs = $_POST["bbs"];
} else {
  $bbs = $bbs_list[0];
}
$bbs_radio = make_bbs_radio($bbs_list, $bbs);

if (isset($_POST["page"])) {
  $page = $_POST["page"];
} else {
  $page = $pages["anikan"];
}

$body = "";

if (isset($_POST["fetch"]) and ($_POST["fetch"] == "OK")) {
  $body = fetch($wiki, $url);
}

if (isset($_POST["upload"]) and ($_POST["upload"] == "OK")) {
  $body = upload($wiki, $host, $bbs,
		 $_FILES["dat"]["name"], $_FILES["dat"]["tmp_name"],
		 $_FILES["dat"]["size"], $_FILES["dat"]["error"]);
}

if (isset($_POST["check"]) and ($_POST["check"] == "OK")) {
  $body = check($wiki, $page, $host);
}

$url = sanitize($url);
$host = sanitize($host);
$page = sanitize($page);

?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift-JIS">
<title><?php echo $sitename?></title>
</head>
<body>
<hr>
<h3><a href="<?php echo $me?>"><?php echo $sitename?></a>
</h3>

<?php echo $body?>

<form action="<?php echo $me?>" method="post" enctype="multipart/form-data">
<fieldset>
<legend>datを自動アップ</legend>
url1: <input type="text" name="url[]" value="<?php echo $url[0]?>" size="78">
<input type="submit" name="fetch" value="OK"><br>
url2: <input type="text" name="url[]" value="" size="78"><br>
url3: <input type="text" name="url[]" value="" size="78"><br>
url4: <input type="text" name="url[]" value="" size="78"><br>
url5: <input type="text" name="url[]" value="" size="78"><br>
</fieldset>
</form>

<form action="<?php echo $me?>" method="post" enctype="multipart/form-data">
<fieldset>
<legend>datを直接アップ</legend>
dat1: <input type="file" name="dat[]" value="" size="78">
<input type="submit" name="upload" value="OK"><br>
dat2: <input type="file" name="dat[]" value="" size="78"><br>
dat3: <input type="file" name="dat[]" value="" size="78"><br>
dat4: <input type="file" name="dat[]" value="" size="78"><br>
dat5: <input type="file" name="dat[]" value="" size="78"><br>
サーバ名: <input type="text" name="host" value="<?php echo $host?>" size="32">
<small>(省略時=<?php echo $host_list[0]?>)</small><br>
板フォルダ名: <?php echo $bbs_radio?>
</fieldset>
</form>

<form action="<?php echo $me?>" method="post" enctype="multipart/form-data">
<fieldset>
<legend>編集漏れチェック</legend>
ページ名: <input type="text" name="page" value="<?php echo $page?>" size="32">
<input type="submit" name="check" value="OK"><br>
サーバ名: <input type="text" name="host" value="<?php echo $host?>" size="32">
<small>(省略時=<?php echo $host_list[0]?>)</small>
</fieldset>
</form>

<small>
<ul>
<li>アップしたいスレの url を入力して OK を押せば自動的にアップします.
<li>datを直接アップする場合は,圧縮せずにアップしてください.
(<font color="red">板フォルダ名に注意</font>)
<li>キャプチャにひっかかったら,手動で突破してください.
<ul>
<li>でないと,テーブルが更新されません(datはアップされます).
</ul>
<li>編集漏れチェックは,
指定されたページに添付されてるのにテーブルにはないスレを表示します.
<ul>
<li>ページの編集はしないでの試したらわかるかも.
<li>(例) ページ名: 2chdat_8205-9196 サーバ名: live24.2ch.net
</ul>
<li>不具合・要望等連絡先→<?php echo $contact?>
</ul>
</small>

<hr>
<a href="<?php echo $wiki?>">アニ関Wiki</a>
 保管庫: 
<?php echo $links["anikan"]?> 
<?php echo $links["aniani"]?> 
<?php echo $links["sinawa"]?> 
 <a href="<?php echo $old?>">旧版</a>
<hr>
</body>
</html>