· 8 years ago · Jul 03, 2018, 12:32 AM
1<?php
2 /* Config */
3
4 $kusabaxc = Array('db' => Array('timeout' => 5, 'persistent' => false));
5 $kusabaxc['db']['type'] = 'mysql';
6 $kusabaxc['db']['server'] = 'localhost';
7 $kusabaxc['db']['user'] = 'unchanor_*****';
8 $kusabaxc['db']['password'] = 'false pass';
9 $kusabaxc['db']['database'] = 'unchanor_*****';
10 // KusabaX table prefix
11 $kusabaxc['db']['prefix'] = '';
12 // Anything more to add to the DSN string (eg. port=xxx;foo=bar)
13 $kusabaxc['db']['dsn'] = '';
14 // From your KusabaX config; needed to decode IP addresses
15 $kusabaxc['randomseed'] = '*****false seed******'; //KU_RANDOMSEED
16 // KusabaX directory (without trailing slash)
17 $kusabaxc['root'] = '/var/www';
18
19 /* End Config */
20
21 if(empty($kusabaxc['db']['user']))
22 die('Did you forget to configure the script?');
23
24 // Infinite timeout
25 set_time_limit(0);
26
27 // KusabaX functions
28 function md5_decrypt($enc_text, $password, $iv_len = 16) {
29 $enc_text = base64_decode($enc_text);
30 $n = strlen($enc_text);
31 $i = $iv_len;
32 $plain_text = '';
33 $iv = substr($password ^ substr($enc_text, 0, $iv_len), 0, 512);
34 while ($i < $n) {
35 $block = substr($enc_text, $i, 16);
36 $plain_text .= $block ^ pack('H*', md5($iv));
37 $iv = substr($block . $iv, 0, 512) ^ $password;
38 $i += 16;
39 }
40 return preg_replace('/\\x13\\x00*$/', '', $plain_text);
41 }
42
43 // KusabaX -> Tinyboard HTML
44 function convert_markup($body) {
45 global $config;
46 $body = stripslashes($body);
47
48 // >quotes
49 $body = str_replace('"unkfunc"', '"quote"', $body);
50
51 // >>cites
52 $body = preg_replace('/<a href="[^"]+?\/(\w+)\/res\/(\d+).html#(\d+)" onclick="return highlight\(\'\d+\', true\);" class="[^"]+">/', '<a onclick="highlightReply(\'$3\');" href="' . $config['root'] . '$1/res/$2.html#$3">', $body);
53
54 // Public bans
55 $body = preg_replace('/<br \/><font color="#FF0000"><b>\((.+?)\)<\/b><\/font>/', '<span class="public_ban">($1)</span>', $body);
56
57 return $body;
58 }
59
60 require 'inc/functions.php';
61 require 'inc/display.php';
62 require 'inc/template.php';
63 require 'inc/database.php';
64 require 'inc/user.php';
65 $step = isset($_GET['step']) ? round($_GET['step']) : 0;
66 $page = Array(
67 'config' => $config,
68 'title' => 'KusabaX Database Migration',
69 'body' => ''
70 );
71
72 $log = Array();
73
74 // Trick Tinyboard into opening the KusabaX databse instead
75 $__temp = $config['db'];
76 $config['db'] = $kusabaxc['db'];
77
78 // Get databse link
79 $kusabax = $pdo;
80 // Clear
81 unset($pdo);
82
83 // Open Tinyboard database
84 $config['db'] = $__temp;
85 unset($__temp);
86
87 $k_query = $kusabax->query('SELECT * FROM `' . $kusabaxc['db']['prefix'] . 'boards`');
88 $boards = listBoards();
89
90 // Copy boards table, briefly
91 $kusabax_boards = Array();
92 while($board = $k_query->fetch()) {
93 // For later use...
94 $kusabax_boards[(int)$board['id']] = $board['name'];
95
96 $already_exists = false;
97 foreach($boards as &$_board) {
98 if($_board['uri'] == $board['name']) {
99 // Board already exists in Tinyboard...
100 $log[] = 'Board /' . $board['name'] . '/ already exists.';
101 $already_exists = true;
102 break;
103 }
104 }
105 if($already_exists)
106 continue;
107
108 $log[] = 'Creating board: <strong>/' . $board['name'] . '/</strong>';
109
110 // Go ahead and create this new board...
111 $query = prepare('INSERT INTO `boards` VALUES (NULL, :uri, :title, :subtitle)');
112 $query->bindValue(':uri', $board['name']);
113 $query->bindValue(':title', $board['desc']);
114 $query->bindValue(':subtitle', null, PDO::PARAM_NULL);
115 $query->execute() or error(db_error($query));
116
117 // Posting table
118 query(Element('posts.sql', Array('board' => $board['name']))) or error(db_error());
119
120 // Set up board (create directories, etc.) by opening it
121 openBoard($board['name']);
122 }
123
124
125 $k_query = $kusabax->query('SELECT * FROM `' . $kusabaxc['db']['prefix'] . 'posts` WHERE `IS_DELETED` = 0');
126 while($post = $k_query->fetch()) {
127 if(!isset($kusabax_boards[(int)$post['boardid']])) {
128 // Board doesn't exist...
129 continue;
130 }
131 $board = $kusabax_boards[(int)$post['boardid']];
132
133 $log[] = 'Replicating post <strong>' . $post['id'] . '</strong> on /' . $board . '/';
134
135 $query = prepare(sprintf("INSERT INTO `posts_%s` VALUES (:id, :thread, :subject, :email, :name, :trip, :capcode, :body, :time, :bump, :thumb, :thumbwidth, :thumbheight, :file, :width, :height, :filesize, :filename, :filehash, :password, :ip, :sticky, :locked, 0, :embed)", $board));
136
137 // Post ID
138 $query->bindValue(':id', $post['id'], PDO::PARAM_INT);
139
140 // Thread (`parentid`)
141 if($post['parentid'] == 0)
142 $query->bindValue(':thread', null, PDO::PARAM_NULL);
143 else
144 $query->bindValue(':thread', (int)$post['parentid'], PDO::PARAM_INT);
145
146 // Name
147 if(empty($post['name']))
148 $post['name'] = $config['anonymous'];
149 $query->bindValue(':name', $post['name'], PDO::PARAM_INT);
150
151 // Trip
152 if(empty($post['tripcode']))
153 $query->bindValue(':trip', null, PDO::PARAM_NULL);
154 else
155 $query->bindValue(':trip', $post['tripcode'], PDO::PARAM_STR);
156
157 // Email
158 $query->bindValue(':email', $post['email'], PDO::PARAM_STR);
159
160 // Subject
161 $query->bindValue(':subject', $post['subject'], PDO::PARAM_STR);
162
163 // Body (`message`)
164 $query->bindValue(':body', convert_markup($post['message']), PDO::PARAM_STR);
165
166 // File
167 if(empty($post['file']) || $post['file'] == 'removed') {
168 if($post['file'] == 'removed')
169 $query->bindValue(':file', 'deleted', PDO::PARAM_STR);
170 else
171 $query->bindValue(':file', null, PDO::PARAM_NULL);
172 $query->bindValue(':width', null, PDO::PARAM_NULL);
173 $query->bindValue(':height', null, PDO::PARAM_NULL);
174 $query->bindValue(':filesize', null, PDO::PARAM_NULL);
175 $query->bindValue(':filename', null, PDO::PARAM_NULL);
176 $query->bindValue(':filehash', null, PDO::PARAM_NULL);
177 $query->bindValue(':thumb', null, PDO::PARAM_NULL);
178 $query->bindValue(':thumbwidth', null, PDO::PARAM_NULL);
179 $query->bindValue(':thumbheight', null, PDO::PARAM_NULL);
180 } else {
181 $query->bindValue(':file', $post['file'] . '.' . $post['file_type'], PDO::PARAM_STR);
182 $query->bindValue(':width', $post['image_w'], PDO::PARAM_INT);
183 $query->bindValue(':height', $post['image_h'], PDO::PARAM_INT);
184 $query->bindValue(':filesize', $post['file_size'], PDO::PARAM_INT);
185 $query->bindValue(':filename', $post['file_original'] . '.' . $post['file_type'], PDO::PARAM_STR);
186 // They use MD5; we use SHA1 by default.
187 $query->bindValue(':filehash', null, PDO::PARAM_NULL);
188
189 $query->bindValue(':thumb', $post['file'] . '.' . $post['file_type'], PDO::PARAM_STR);
190 $query->bindValue(':thumbwidth', $post['thumb_w'], PDO::PARAM_INT);
191 $query->bindValue(':thumbheight', $post['thumb_h'], PDO::PARAM_INT);
192
193 // Copy file
194 $file_path = $kusabaxc['root'] . '/' . $board . '/src/' . $post['file'] . '.' . $post['file_type'];
195 $thumb_path = $kusabaxc['root'] . '/' . $board . '/thumb/' . $post['file'] . 's.' . $post['file_type'];
196
197 $to_file_path = sprintf($config['board_path'], $board) . $config['dir']['img'] . $post['file'] . '.' . $post['file_type'];
198 $to_thumb_path = sprintf($config['board_path'], $board) . $config['dir']['thumb'] . $post['file'] . '.' . $post['file_type'];
199
200 if(!file_exists($to_file_path)) {
201 $log[] = 'Copying file: <strong>' . $file_path . '</strong>';
202 if(!@copy($file_path, $to_file_path)) {
203 $err = error_get_last();
204 $log[] = 'Could not copy <strong>' . $file_path . '</strong>: ' . $err['message'];
205 }
206 }
207
208 if(!file_exists($to_thumb_path)) {
209 $log[] = 'Copying file: <strong>' . $thumb_path . '</strong>';
210 if(!@copy($thumb_path, $to_thumb_path)) {
211 $err = error_get_last();
212 $log[] = 'Could not copy <strong>' . $thumb_path. '</strong>: ' . $err['message'];
213 }
214 }
215 }
216
217 // IP
218 $ip = md5_decrypt($post['ip'], $kusabaxc['randomseed']);
219 if(!preg_match('/^\d+\.\d+\.\d+\.\d+$/', $ip)) {
220 // Invalid IP address. Wrong KU_RANDOMSEED?
221
222 $log[] = 'Invalid IP address returned after decryption. Wrong KU_RANDOMSEED?';
223 $ip = '0.0.0.0'; // just set it to something valid and continue
224 }
225 $query->bindValue(':ip', $ip, PDO::PARAM_STR);
226
227 // Time (`timestamp`)
228 $query->bindValue(':time', $post['timestamp'], PDO::PARAM_INT);
229
230 // Bump (`bumped`)
231 $query->bindValue(':bump', $post['bumped'], PDO::PARAM_INT);
232
233 // Locked
234 $query->bindValue(':locked', $post['locked'], PDO::PARAM_INT);
235
236 // Sticky
237 $query->bindValue(':sticky', $post['stickied'], PDO::PARAM_INT);
238
239 // Stuff we can't do (yet)
240 $query->bindValue(':embed', null, PDO::PARAM_NULL);
241 $query->bindValue(':password', null, PDO::PARAM_NULL);
242 $query->bindValue(':capcode', null, PDO::PARAM_NULL);
243
244 // Insert post
245 $query->execute() or $log[] = 'Error: ' . db_error($query);
246 }
247
248 // News
249 $k_query = $kusabax->query('SELECT * FROM `' . $kusabaxc['db']['prefix'] . 'front` WHERE `page` = 0');
250 while($news = $k_query->fetch()) {
251 // Check if already exists
252 $query = prepare("SELECT 1 FROM `news` WHERE `body` = :body AND `time` = :time");
253 $query->bindValue(':time', $news['timestamp'], PDO::PARAM_INT);
254 $query->bindValue(':body', $news['message'], PDO::PARAM_STR);
255 $query->execute() or error(db_error($query));
256 if($query->fetch())
257 continue;
258
259 $query = prepare("INSERT INTO `news` VALUES (NULL, :name, :time, :subject, :body)");
260 $query->bindValue(':name', $news['poster'], PDO::PARAM_STR);
261 $query->bindValue(':time', $news['timestamp'], PDO::PARAM_INT);
262 $query->bindValue(':subject', $news['subject'], PDO::PARAM_STR);
263 $query->bindValue(':body', $news['message'], PDO::PARAM_STR);
264 $query->execute() or $log[] = 'Error: ' . db_error($query);
265 }
266
267 $page['body'] = '<div class="ban"><h2>Migrating…</h2><p>';
268 foreach($log as &$l) {
269 $page['body'] .= $l . '<br/>';
270 }
271 $page['body'] .= '</p></div>';
272
273 echo Element('page.html', $page);