2 //ini_set('display_errors', 'On');
4 ini_set('log_errors', 'On');
5 ini_set('error_log', 'errors/'.pathinfo(__FILE__, PATHINFO_FILENAME).'.log');
7 require_once "db_common.inc";
8 require_once "dump_file.inc";
10 // 登録が成功しない場合、HTTPレスポンスコード 400 Bad Request を返す
11 http_response_code(400);
14 * 送信されてきたスコアのマルチバイト文字エンコーディングを取得する
16 * Content-Typeヘッダからエンコーディングを取得する。
17 * 同時に変愚蛮怒が送ってきているはずのContent-Typeヘッダと一致しているかチェックする。
19 * @return string|false 送られてきたスコアの、PHPのマルチバイト文字処理における文字エンコーディングを表す文字列
22 function get_mb_encoding(){
23 $content_type = filter_input(INPUT_SERVER, 'CONTENT_TYPE');
24 if ($content_type == NULL) return FALSE;
26 $s = explode(';', $content_type);
29 $s[0] !== "text/plain" ||
30 strpos(trim($s[1]), "charset=") !== 0) return FALSE;
32 $c = explode('=', $s[1]);
34 switch (strtolower(trim($c[1]))) {
50 * 受信したスコアデータを、キャラクタ情報部分・キャラクタダンプ部分・スクリーンショット部分の3つに分割する
51 * それぞれの部分は1行毎の文字列の配列とする
53 * @param string $recv_contents 受信したスコアデータ
54 * @return array|false キャラクタ情報・キャラクタダンプ・スクリーンショットのそれぞれの部分のデータの配列
57 function split_recv_contents($recv_contents)
59 $recv_lines = explode("\n", $recv_contents);
61 $dump_info_end_line = array_search('-----charcter dump-----', $recv_lines);
62 $dump_txt_end_line = array_search('-----screen shot-----', $recv_lines);
64 if ($dump_info_end_line === FALSE) return FALSE;
66 $info_lines = array_slice($recv_lines, 0, $dump_info_end_line);
67 $dump_lines = array_slice(
69 $dump_info_end_line + 1,
70 $dump_txt_end_line ? $dump_txt_end_line - $dump_info_end_line - 1: NULL
72 $screen_lines = $dump_txt_end_line ?
75 $dump_txt_end_line + 1,
79 return [$info_lines, $dump_lines, $screen_lines];
86 * スコアデータのキャラクタ情報をパースし、情報名=>値の連想配列を得る
87 * ex) name: Hoge を ['name' => 'Hoge'] のようにする
89 * @param string $info_liens 受信したスコアデータのキャラクタ情報(1要素1行の配列)
90 * @return array|false キャラクタ情報・キャラクタダンプ・スクリーンショットのそれぞれの部分のデータの配列
93 function parse_character_info($info_lines)
96 foreach ($info_lines as $l) {
97 $splitpos = strpos($l, ':');
98 if ($splitpos !== FALSE) {
99 $key = substr($l, 0, $splitpos);
100 $val = substr($l, $splitpos + 1);
101 $info[$key] = trim($val);
110 * キャラクタ情報からDBへのスコア登録用パラメータを生成する
112 * @param array $info キャラクタ情報の連想配列
113 * @return array DBへのスコア登録用パラメータ('character_info'と'realm_info'の連想配列)
115 function create_db_insert_score_data($info)
117 $character_info_array = [
118 'version' => $info['version'],
119 'score' => $info['score'],
120 'name' => $info['name'],
121 'race' => $info['race'],
122 'class' => $info['class'],
123 'personality' => $info['seikaku'],
124 'sex' => $info['sex'],
125 'level' => $info['level'],
126 'depth' => $info['depth'],
127 'maxlv' => $info['maxlv'],
128 'maxdp' => $info['maxdp'],
130 'turns' => $info['turns'],
131 'winner' => $info['killer'] == 'ripe' || $info['killer'] == 'Seppuku',
132 'killer' => $info['killer'],
135 $realm_info_array = array_values(
137 [$info['realm1'], $info['realm2']],
138 function($v) {return $v !== '魔法なし';})
142 'character_info' => $character_info_array,
143 'realm_info' => $realm_info_array,
148 $recv_encoding = get_mb_encoding();
149 if ($recv_encoding === FALSE) {
153 $recv_contents = file_get_contents('php://input');
154 if (strlen($recv_contents) !== filter_input(INPUT_SERVER, 'CONTENT_LENGTH', FILTER_VALIDATE_INT)) {
158 $recv_contents = mb_convert_encoding($recv_contents, "UTF-8", $recv_encoding);
160 $split_contents = split_recv_contents($recv_contents);
161 if ($split_contents === FALSE) {
165 $char_info = parse_character_info($split_contents[0]);
168 $score_id = $db->register_new_score(create_db_insert_score_data($char_info));
170 if ($score_id === FALSE) {
174 $dumpfile = new DumpFile($score_id);
175 $dumpfile->save('dumps', 'txt', $split_contents[1]);
176 $dumpfile->save('screens', 'html', $split_contents[2]);
178 // 登録成功、HTTPレスポンスコード 200 OK を返す
179 http_response_code(200);