Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1824 lines
84 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. <?php
  2. use Friendica\App;
  3. use Friendica\Core\System;
  4. use Friendica\Core\Config;
  5. require_once "boot.php";
  6. require_once "include/text.php";
  7. define('NEW_UPDATE_ROUTINE_VERSION', 1170);
  8. const DB_UPDATE_NOT_CHECKED = 0; // Database check wasn't executed before
  9. const DB_UPDATE_SUCCESSFUL = 1; // Database check was successful
  10. const DB_UPDATE_FAILED = 2; // Database check failed
  11. /*
  12. * Converts all tables from MyISAM to InnoDB
  13. */
  14. function convert_to_innodb() {
  15. $r = q("SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `engine` = 'MyISAM' AND `table_schema` = '%s'",
  16. dbesc(dba::database_name()));
  17. if (!dbm::is_result($r)) {
  18. echo t('There are no tables on MyISAM.')."\n";
  19. return;
  20. }
  21. foreach ($r AS $table) {
  22. $sql = sprintf("ALTER TABLE `%s` engine=InnoDB;", dbesc($table['TABLE_NAME']));
  23. echo $sql."\n";
  24. $result = dba::e($sql);
  25. if (!dbm::is_result($result)) {
  26. print_update_error($sql);
  27. }
  28. }
  29. }
  30. /*
  31. * send the email and do what is needed to do on update fails
  32. *
  33. * @param update_id (int) number of failed update
  34. * @param error_message (str) error message
  35. */
  36. function update_fail($update_id, $error_message) {
  37. //send the administrators an e-mail
  38. $admin_mail_list = "'".implode("','", array_map(dbesc, explode(",", str_replace(" ", "", $a->config['admin_email']))))."'";
  39. $adminlist = q("SELECT uid, language, email FROM user WHERE email IN (%s)",
  40. $admin_mail_list
  41. );
  42. // No valid result?
  43. if (!dbm::is_result($adminlist)) {
  44. logger(sprintf('Cannot notify administrators about update_id=%d, error_message=%s', $update_id, $error_message), LOGGER_NORMAL);
  45. // Don't continue
  46. return;
  47. }
  48. // every admin could had different language
  49. foreach ($adminlist as $admin) {
  50. $lang = (($admin['language'])?$admin['language']:'en');
  51. push_lang($lang);
  52. $preamble = deindent(t("
  53. The friendica developers released update %s recently,
  54. but when I tried to install it, something went terribly wrong.
  55. This needs to be fixed soon and I can't do it alone. Please contact a
  56. friendica developer if you can not help me on your own. My database might be invalid."));
  57. $body = t("The error message is\n[pre]%s[/pre]");
  58. $preamble = sprintf($preamble, $update_id);
  59. $body = sprintf($body, $error_message);
  60. notification(array(
  61. 'type' => SYSTEM_EMAIL,
  62. 'to_email' => $admin['email'],
  63. 'preamble' => $preamble,
  64. 'body' => $body,
  65. 'language' => $lang,
  66. ));
  67. }
  68. /*
  69. @TODO deprecated code?
  70. $email_tpl = get_intltext_template("update_fail_eml.tpl");
  71. $email_msg = replace_macros($email_tpl, array(
  72. '$sitename' => $a->config['sitename'],
  73. '$siteurl' => System::baseUrl(),
  74. '$update' => DB_UPDATE_VERSION,
  75. '$error' => sprintf(t('Update %s failed. See error logs.'), DB_UPDATE_VERSION)
  76. ));
  77. $subject=sprintf(t('Update Error at %s'), System::baseUrl());
  78. require_once('include/email.php');
  79. $subject = email_header_encode($subject,'UTF-8');
  80. mail($a->config['admin_email'], $subject, $email_msg,
  81. 'From: ' . 'Administrator' . '@' . $_SERVER['SERVER_NAME']."\n"
  82. .'Content-type: text/plain; charset=UTF-8'."\n"
  83. .'Content-transfer-encoding: 8bit');
  84. */
  85. //try the logger
  86. logger("CRITICAL: Database structure update failed: ".$retval);
  87. }
  88. function table_structure($table) {
  89. $structures = q("DESCRIBE `%s`", $table);
  90. $full_columns = q("SHOW FULL COLUMNS FROM `%s`", $table);
  91. $indexes = q("SHOW INDEX FROM `%s`", $table);
  92. $table_status = q("SHOW TABLE STATUS WHERE `name` = '%s'", $table);
  93. if (dbm::is_result($table_status)) {
  94. $table_status = $table_status[0];
  95. } else {
  96. $table_status = array();
  97. }
  98. $fielddata = array();
  99. $indexdata = array();
  100. if (dbm::is_result($indexes))
  101. foreach ($indexes AS $index) {
  102. if ($index['Key_name'] != 'PRIMARY' && $index['Non_unique'] == '0' && !isset($indexdata[$index["Key_name"]])) {
  103. $indexdata[$index["Key_name"]] = array('UNIQUE');
  104. }
  105. $column = $index["Column_name"];
  106. // On utf8mb4 a varchar index can only have a length of 191
  107. // The "show index" command sometimes returns this value although this value wasn't added manually.
  108. // Because we don't want to add this number to every index, we ignore bigger numbers
  109. if (($index["Sub_part"] != "") && (($index["Sub_part"] < 191) || ($index["Key_name"] == "PRIMARY"))) {
  110. $column .= "(".$index["Sub_part"].")";
  111. }
  112. $indexdata[$index["Key_name"]][] = $column;
  113. }
  114. if (dbm::is_result($structures)) {
  115. foreach ($structures AS $field) {
  116. $fielddata[$field["Field"]]["type"] = $field["Type"];
  117. if ($field["Null"] == "NO") {
  118. $fielddata[$field["Field"]]["not null"] = true;
  119. }
  120. if (isset($field["Default"])) {
  121. $fielddata[$field["Field"]]["default"] = $field["Default"];
  122. }
  123. if ($field["Extra"] != "") {
  124. $fielddata[$field["Field"]]["extra"] = $field["Extra"];
  125. }
  126. if ($field["Key"] == "PRI") {
  127. $fielddata[$field["Field"]]["primary"] = true;
  128. }
  129. }
  130. }
  131. if (dbm::is_result($full_columns)) {
  132. foreach ($full_columns AS $column) {
  133. $fielddata[$column["Field"]]["Collation"] = $column["Collation"];
  134. }
  135. }
  136. return array("fields" => $fielddata, "indexes" => $indexdata, "table_status" => $table_status);
  137. }
  138. function print_structure($database) {
  139. echo "-- ------------------------------------------\n";
  140. echo "-- ".FRIENDICA_PLATFORM." ".FRIENDICA_VERSION." (".FRIENDICA_CODENAME,")\n";
  141. echo "-- DB_UPDATE_VERSION ".DB_UPDATE_VERSION."\n";
  142. echo "-- ------------------------------------------\n\n\n";
  143. foreach ($database AS $name => $structure) {
  144. echo "--\n";
  145. echo "-- TABLE $name\n";
  146. echo "--\n";
  147. db_create_table($name, $structure['fields'], true, false, $structure["indexes"]);
  148. echo "\n";
  149. }
  150. }
  151. /**
  152. * @brief Print out database error messages
  153. *
  154. * @param string $message Message to be added to the error message
  155. *
  156. * @return string Error message
  157. */
  158. function print_update_error($message) {
  159. echo sprintf(t("\nError %d occurred during database update:\n%s\n"),
  160. dba::errorNo(), dba::errorMessage());
  161. return t('Errors encountered performing database changes: ').$message.EOL;
  162. }
  163. function update_structure($verbose, $action, $tables=null, $definition=null) {
  164. global $a;
  165. if ($action) {
  166. Config::set('system', 'maintenance', 1);
  167. Config::set('system', 'maintenance_reason', sprintf(t(': Database update'), dbm::date().' '.date('e')));
  168. }
  169. $errors = false;
  170. logger('updating structure', LOGGER_DEBUG);
  171. // Get the current structure
  172. $database = array();
  173. if (is_null($tables)) {
  174. $tables = q("SHOW TABLES");
  175. }
  176. if (dbm::is_result($tables)) {
  177. foreach ($tables AS $table) {
  178. $table = current($table);
  179. logger(sprintf('updating structure for table %s ...', $table), LOGGER_DEBUG);
  180. $database[$table] = table_structure($table);
  181. }
  182. }
  183. // Get the definition
  184. if (is_null($definition)) {
  185. $definition = db_definition();
  186. }
  187. // MySQL >= 5.7.4 doesn't support the IGNORE keyword in ALTER TABLE statements
  188. if ((version_compare(dba::server_info(), '5.7.4') >= 0) &&
  189. !(strpos(dba::server_info(), 'MariaDB') !== false)) {
  190. $ignore = '';
  191. } else {
  192. $ignore = ' IGNORE';
  193. }
  194. // Compare it
  195. foreach ($definition AS $name => $structure) {
  196. $is_new_table = False;
  197. $group_by = "";
  198. $sql3 = "";
  199. if (!isset($database[$name])) {
  200. $r = db_create_table($name, $structure["fields"], $verbose, $action, $structure['indexes']);
  201. if (!dbm::is_result($r)) {
  202. $errors .= print_update_error($name);
  203. }
  204. $is_new_table = True;
  205. } else {
  206. $is_unique = false;
  207. $temp_name = $name;
  208. foreach ($structure["indexes"] AS $indexname => $fieldnames) {
  209. if (isset($database[$name]["indexes"][$indexname])) {
  210. $current_index_definition = implode(",",$database[$name]["indexes"][$indexname]);
  211. } else {
  212. $current_index_definition = "__NOT_SET__";
  213. }
  214. $new_index_definition = implode(",",$fieldnames);
  215. if ($current_index_definition != $new_index_definition) {
  216. if ($fieldnames[0] == "UNIQUE") {
  217. $is_unique = true;
  218. if ($ignore == "") {
  219. $temp_name = "temp-".$name;
  220. }
  221. }
  222. }
  223. }
  224. /*
  225. * Drop the index if it isn't present in the definition
  226. * or the definition differ from current status
  227. * and index name doesn't start with "local_"
  228. */
  229. foreach ($database[$name]["indexes"] as $indexname => $fieldnames) {
  230. $current_index_definition = implode(",",$fieldnames);
  231. if (isset($structure["indexes"][$indexname])) {
  232. $new_index_definition = implode(",",$structure["indexes"][$indexname]);
  233. } else {
  234. $new_index_definition = "__NOT_SET__";
  235. }
  236. if ($current_index_definition != $new_index_definition && substr($indexname, 0, 6) != 'local_') {
  237. $sql2=db_drop_index($indexname);
  238. if ($sql3 == "") {
  239. $sql3 = "ALTER".$ignore." TABLE `".$temp_name."` ".$sql2;
  240. } else {
  241. $sql3 .= ", ".$sql2;
  242. }
  243. }
  244. }
  245. // Compare the field structure field by field
  246. foreach ($structure["fields"] AS $fieldname => $parameters) {
  247. if (!isset($database[$name]["fields"][$fieldname])) {
  248. $sql2=db_add_table_field($fieldname, $parameters);
  249. if ($sql3 == "") {
  250. $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  251. } else {
  252. $sql3 .= ", ".$sql2;
  253. }
  254. } else {
  255. // Compare the field definition
  256. $field_definition = $database[$name]["fields"][$fieldname];
  257. // Remove the relation data that is used for the referential integrity
  258. unset($parameters['relation']);
  259. // We change the collation after the indexes had been changed.
  260. // This is done to avoid index length problems.
  261. // So here we always ensure that there is no need to change it.
  262. unset($parameters['Collation']);
  263. unset($field_definition['Collation']);
  264. $current_field_definition = implode(",", $field_definition);
  265. $new_field_definition = implode(",", $parameters);
  266. if ($current_field_definition != $new_field_definition) {
  267. $sql2 = db_modify_table_field($fieldname, $parameters);
  268. if ($sql3 == "") {
  269. $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  270. } else {
  271. $sql3 .= ", ".$sql2;
  272. }
  273. }
  274. }
  275. }
  276. }
  277. /*
  278. * Create the index if the index don't exists in database
  279. * or the definition differ from the current status.
  280. * Don't create keys if table is new
  281. */
  282. if (!$is_new_table) {
  283. foreach ($structure["indexes"] AS $indexname => $fieldnames) {
  284. if (isset($database[$name]["indexes"][$indexname])) {
  285. $current_index_definition = implode(",",$database[$name]["indexes"][$indexname]);
  286. } else {
  287. $current_index_definition = "__NOT_SET__";
  288. }
  289. $new_index_definition = implode(",",$fieldnames);
  290. if ($current_index_definition != $new_index_definition) {
  291. $sql2 = db_create_index($indexname, $fieldnames);
  292. // Fetch the "group by" fields for unique indexes
  293. if ($fieldnames[0] == "UNIQUE") {
  294. $group_by = db_group_by($indexname, $fieldnames);
  295. }
  296. if ($sql2 != "") {
  297. if ($sql3 == "") {
  298. $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  299. } else {
  300. $sql3 .= ", ".$sql2;
  301. }
  302. }
  303. }
  304. }
  305. if (isset($database[$name]["table_status"]["Collation"])) {
  306. if ($database[$name]["table_status"]["Collation"] != 'utf8mb4_general_ci') {
  307. $sql2 = "DEFAULT COLLATE utf8mb4_general_ci";
  308. if ($sql3 == "") {
  309. $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  310. } else {
  311. $sql3 .= ", ".$sql2;
  312. }
  313. }
  314. }
  315. if ($sql3 != "") {
  316. $sql3 .= "; ";
  317. }
  318. // Now have a look at the field collations
  319. // Compare the field structure field by field
  320. foreach ($structure["fields"] AS $fieldname => $parameters) {
  321. // Compare the field definition
  322. $field_definition = $database[$name]["fields"][$fieldname];
  323. // Define the default collation if not given
  324. if (!isset($parameters['Collation']) && !is_null($field_definition['Collation'])) {
  325. $parameters['Collation'] = 'utf8mb4_general_ci';
  326. } else {
  327. $parameters['Collation'] = null;
  328. }
  329. if ($field_definition['Collation'] != $parameters['Collation']) {
  330. $sql2 = db_modify_table_field($fieldname, $parameters);
  331. if (($sql3 == "") || (substr($sql3, -2, 2) == "; ")) {
  332. $sql3 .= "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  333. } else {
  334. $sql3 .= ", ".$sql2;
  335. }
  336. }
  337. }
  338. }
  339. if ($sql3 != "") {
  340. if (substr($sql3, -2, 2) != "; ") {
  341. $sql3 .= ";";
  342. }
  343. $field_list = '';
  344. if ($is_unique && $ignore == '') {
  345. foreach ($structure['fields'] AS $fieldname => $parameters) {
  346. $field_list .= 'ANY_VALUE(`' . $fieldname . '`),';
  347. }
  348. $field_list = rtrim($field_list, ',');
  349. }
  350. if ($verbose) {
  351. // Ensure index conversion to unique removes duplicates
  352. if ($is_unique) {
  353. if ($ignore != "") {
  354. echo "SET session old_alter_table=1;\n";
  355. } else {
  356. echo "CREATE TABLE `".$temp_name."` LIKE `".$name."`;\n";
  357. }
  358. }
  359. echo $sql3."\n";
  360. if ($is_unique) {
  361. if ($ignore != "") {
  362. echo "SET session old_alter_table=0;\n";
  363. } else {
  364. echo "INSERT INTO `".$temp_name."` SELECT ".$field_list." FROM `".$name."`".$group_by.";\n";
  365. echo "DROP TABLE `".$name."`;\n";
  366. echo "RENAME TABLE `".$temp_name."` TO `".$name."`;\n";
  367. }
  368. }
  369. }
  370. if ($action) {
  371. Config::set('system', 'maintenance_reason', sprintf(t('%s: updating %s table.'), dbm::date().' '.date('e'), $name));
  372. // Ensure index conversion to unique removes duplicates
  373. if ($is_unique) {
  374. if ($ignore != "") {
  375. dba::e("SET session old_alter_table=1;");
  376. } else {
  377. $r = dba::e("CREATE TABLE `".$temp_name."` LIKE `".$name."`;");
  378. if (!dbm::is_result($r)) {
  379. $errors .= print_update_error($sql3);
  380. return $errors;
  381. }
  382. }
  383. }
  384. $r = @dba::e($sql3);
  385. if (!dbm::is_result($r)) {
  386. $errors .= print_update_error($sql3);
  387. }
  388. if ($is_unique) {
  389. if ($ignore != "") {
  390. dba::e("SET session old_alter_table=0;");
  391. } else {
  392. $r = dba::e("INSERT INTO `".$temp_name."` SELECT ".$field_list." FROM `".$name."`".$group_by.";");
  393. if (!dbm::is_result($r)) {
  394. $errors .= print_update_error($sql3);
  395. return $errors;
  396. }
  397. $r = dba::e("DROP TABLE `".$name."`;");
  398. if (!dbm::is_result($r)) {
  399. $errors .= print_update_error($sql3);
  400. return $errors;
  401. }
  402. $r = dba::e("RENAME TABLE `".$temp_name."` TO `".$name."`;");
  403. if (!dbm::is_result($r)) {
  404. $errors .= print_update_error($sql3);
  405. return $errors;
  406. }
  407. }
  408. }
  409. }
  410. }
  411. }
  412. if ($action) {
  413. Config::set('system', 'maintenance', 0);
  414. Config::set('system', 'maintenance_reason', '');
  415. }
  416. if ($errors) {
  417. Config::set('system', 'dbupdate', DB_UPDATE_FAILED);
  418. } else {
  419. Config::set('system', 'dbupdate', DB_UPDATE_SUCCESSFUL);
  420. }
  421. return $errors;
  422. }
  423. function db_field_command($parameters, $create = true) {
  424. $fieldstruct = $parameters["type"];
  425. if (!is_null($parameters["Collation"])) {
  426. $fieldstruct .= " COLLATE ".$parameters["Collation"];
  427. }
  428. if ($parameters["not null"])
  429. $fieldstruct .= " NOT NULL";
  430. if (isset($parameters["default"])) {
  431. if (strpos(strtolower($parameters["type"]),"int")!==false) {
  432. $fieldstruct .= " DEFAULT ".$parameters["default"];
  433. } else {
  434. $fieldstruct .= " DEFAULT '".$parameters["default"]."'";
  435. }
  436. }
  437. if ($parameters["extra"] != "")
  438. $fieldstruct .= " ".$parameters["extra"];
  439. /*if (($parameters["primary"] != "") && $create)
  440. $fieldstruct .= " PRIMARY KEY";*/
  441. return($fieldstruct);
  442. }
  443. function db_create_table($name, $fields, $verbose, $action, $indexes=null) {
  444. global $a;
  445. $r = true;
  446. $sql = "";
  447. $sql_rows = array();
  448. $primary_keys = array();
  449. foreach ($fields AS $fieldname => $field) {
  450. $sql_rows[] = "`".dbesc($fieldname)."` ".db_field_command($field);
  451. if (x($field,'primary') && $field['primary']!='') {
  452. $primary_keys[] = $fieldname;
  453. }
  454. }
  455. if (!is_null($indexes)) {
  456. foreach ($indexes AS $indexname => $fieldnames) {
  457. $sql_index = db_create_index($indexname, $fieldnames, "");
  458. if (!is_null($sql_index)) $sql_rows[] = $sql_index;
  459. }
  460. }
  461. $sql = implode(",\n\t", $sql_rows);
  462. $sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", dbesc($name)).$sql."\n) DEFAULT COLLATE utf8mb4_general_ci";
  463. if ($verbose)
  464. echo $sql.";\n";
  465. if ($action)
  466. $r = @dba::e($sql);
  467. return $r;
  468. }
  469. function db_add_table_field($fieldname, $parameters) {
  470. $sql = sprintf("ADD `%s` %s", dbesc($fieldname), db_field_command($parameters));
  471. return($sql);
  472. }
  473. function db_modify_table_field($fieldname, $parameters) {
  474. $sql = sprintf("MODIFY `%s` %s", dbesc($fieldname), db_field_command($parameters, false));
  475. return($sql);
  476. }
  477. function db_drop_index($indexname) {
  478. $sql = sprintf("DROP INDEX `%s`", dbesc($indexname));
  479. return($sql);
  480. }
  481. function db_create_index($indexname, $fieldnames, $method="ADD") {
  482. $method = strtoupper(trim($method));
  483. if ($method!="" && $method!="ADD") {
  484. throw new Exception("Invalid parameter 'method' in db_create_index(): '$method'");
  485. killme();
  486. }
  487. if ($fieldnames[0] == "UNIQUE") {
  488. array_shift($fieldnames);
  489. $method .= ' UNIQUE';
  490. }
  491. $names = "";
  492. foreach ($fieldnames AS $fieldname) {
  493. if ($names != "")
  494. $names .= ",";
  495. if (preg_match('|(.+)\((\d+)\)|', $fieldname, $matches)) {
  496. $names .= "`".dbesc($matches[1])."`(".intval($matches[2]).")";
  497. } else {
  498. $names .= "`".dbesc($fieldname)."`";
  499. }
  500. }
  501. if ($indexname == "PRIMARY") {
  502. return sprintf("%s PRIMARY KEY(%s)", $method, $names);
  503. }
  504. $sql = sprintf("%s INDEX `%s` (%s)", $method, dbesc($indexname), $names);
  505. return($sql);
  506. }
  507. function db_group_by($indexname, $fieldnames) {
  508. if ($fieldnames[0] != "UNIQUE") {
  509. return "";
  510. }
  511. array_shift($fieldnames);
  512. $names = "";
  513. foreach ($fieldnames AS $fieldname) {
  514. if ($names != "")
  515. $names .= ",";
  516. if (preg_match('|(.+)\((\d+)\)|', $fieldname, $matches)) {
  517. $names .= "`".dbesc($matches[1])."`";
  518. } else {
  519. $names .= "`".dbesc($fieldname)."`";
  520. }
  521. }
  522. $sql = sprintf(" GROUP BY %s", $names);
  523. return $sql;
  524. }
  525. function db_definition() {
  526. $database = array();
  527. $database["addon"] = array(
  528. "fields" => array(
  529. "id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  530. "name" => array("type" => "varchar(190)", "not null" => "1", "default" => ""),
  531. "version" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  532. "installed" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  533. "hidden" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  534. "timestamp" => array("type" => "bigint(20)", "not null" => "1", "default" => "0"),
  535. "plugin_admin" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  536. ),
  537. "indexes" => array(
  538. "PRIMARY" => array("id"),
  539. "name" => array("UNIQUE", "name"),
  540. )
  541. );
  542. $database["attach"] = array(
  543. "fields" => array(
  544. "id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  545. "uid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
  546. "hash" => array("type" => "varchar(64)", "not null" => "1", "default" => ""),
  547. "filename" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  548. "filetype" => array("type" => "varchar(64)", "not null" => "1", "default" => ""),
  549. "filesize" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
  550. "data" => array("type" => "longblob", "not null" => "1"),
  551. "created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  552. "edited" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  553. "allow_cid" => array("type" => "mediumtext"),
  554. "allow_gid" => array("type" => "mediumtext"),
  555. "deny_cid" => array("type" => "mediumtext"),
  556. "deny_gid" => array("type" => "mediumtext"),
  557. ),
  558. "indexes" => array(
  559. "PRIMARY" => array("id"),
  560. )
  561. );
  562. $database["auth_codes"] = array(
  563. "fields" => array(
  564. "id" => array("type" => "varchar(40)", "not null" => "1", "primary" => "1"),
  565. "client_id" => array("type" => "varchar(20)", "not null" => "1", "default" => "", "relation" => array("clients" => "client_id")),
  566. "redirect_uri" => array("type" => "varchar(200)", "not null" => "1", "default" => ""),
  567. "expires" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
  568. "scope" => array("type" => "varchar(250)", "not null" => "1", "default" => ""),
  569. ),
  570. "indexes" => array(
  571. "PRIMARY" => array("id"),
  572. )
  573. );
  574. $database["cache"] = array(
  575. "fields" => array(
  576. "k" => array("type" => "varbinary(255)", "not null" => "1", "primary" => "1"),
  577. "v" => array("type" => "mediumtext"),
  578. "expire_mode" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
  579. "updated" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  580. ),
  581. "indexes" => array(
  582. "PRIMARY" => array("k"),
  583. "expire_mode_updated" => array("expire_mode", "updated"),
  584. )
  585. );
  586. $database["challenge"] = array(
  587. "fields" => array(
  588. "id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  589. "challenge" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  590. "dfrn-id" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  591. "expire" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
  592. "type" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  593. "last_update" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  594. ),
  595. "indexes" => array(
  596. "PRIMARY" => array("id"),
  597. )
  598. );
  599. $database["clients"] = array(
  600. "fields" => array(
  601. "client_id" => array("type" => "varchar(20)", "not null" => "1", "primary" => "1"),
  602. "pw" => array("type" => "varchar(20)", "not null" => "1", "default" => ""),
  603. "redirect_uri" => array("type" => "varchar(200)", "not null" => "1", "default" => ""),
  604. "name" => array("type" => "text"),
  605. "icon" => array("type" => "text"),
  606. "uid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
  607. ),
  608. "indexes" => array(
  609. "PRIMARY" => array("client_id"),
  610. )
  611. );
  612. $database["config"] = array(
  613. "fields" => array(
  614. "id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  615. "cat" => array("type" => "varbinary(255)", "not null" => "1", "default" => ""),
  616. "k" => array("type" => "varbinary(255)", "not null" => "1", "default" => ""),
  617. "v" => array("type" => "mediumtext"),
  618. ),
  619. "indexes" => array(
  620. "PRIMARY" => array("id"),
  621. "cat_k" => array("UNIQUE", "cat", "k"),
  622. )
  623. );
  624. $database["contact"] = array(
  625. "fields" => array(
  626. "id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  627. "uid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
  628. "created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  629. "self" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  630. "remote_self" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  631. "rel" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  632. "duplex" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  633. "network" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  634. "name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  635. "nick" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  636. "location" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  637. "about" => array("type" => "text"),
  638. "keywords" => array("type" => "text"),
  639. "gender" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
  640. "xmpp" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  641. "attag" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  642. "avatar" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  643. "photo" => array("type" => "text"),
  644. "thumb" => array("type" => "text"),
  645. "micro" => array("type" => "text"),
  646. "site-pubkey" => array("type" => "text"),
  647. "issued-id" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  648. "dfrn-id" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  649. "url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  650. "nurl" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  651. "addr" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  652. "alias" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  653. "pubkey" => array("type" => "text"),
  654. "prvkey" => array("type" => "text"),
  655. "batch" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  656. "request" => array("type" => "text"),
  657. "notify" => array("type" => "text"),
  658. "poll" => array("type" => "text"),
  659. "confirm" => array("type" => "text"),
  660. "poco" => array("type" => "text"),
  661. "aes_allow" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  662. "ret-aes" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  663. "usehub" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  664. "subhub" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  665. "hub-verify" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  666. "last-update" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  667. "success_update" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  668. "failure_update" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  669. "name-date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  670. "uri-date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  671. "avatar-date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  672. "term-date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  673. "last-item" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  674. "priority" => array("type" => "tinyint(3)", "not null" => "1", "default" => "0"),
  675. "blocked" => array("type" => "tinyint(1)", "not null" => "1", "default" => "1"),
  676. "readonly" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  677. "writable" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  678. "forum" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  679. "prv" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  680. "contact-type" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
  681. "hidden" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  682. "archive" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  683. "pending" => array("type" => "tinyint(1)", "not null" => "1", "default" => "1"),
  684. "rating" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  685. "reason" => array("type" => "text"),
  686. "closeness" => array("type" => "tinyint(2)", "not null" => "1", "default" => "99"),
  687. "info" => array("type" => "mediumtext"),
  688. "profile-id" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
  689. "bdyear" => array("type" => "varchar(4)", "not null" => "1", "default" => ""),
  690. "bd" => array("type" => "date", "not null" => "1", "default" => "0001-01-01"),
  691. "notify_new_posts" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  692. "fetch_further_information" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  693. "ffi_keyword_blacklist" => array("type" => "text"),
  694. ),
  695. "indexes" => array(
  696. "PRIMARY" => array("id"),
  697. "uid_name" => array("uid", "name(190)"),
  698. "self_uid" => array("self", "uid"),
  699. "alias_uid" => array("alias(32)", "uid"),
  700. "pending_uid" => array("pending", "uid"),
  701. "blocked_uid" => array("blocked", "uid"),
  702. "uid_rel_network_poll" => array("uid", "rel", "network(4)", "poll(64)", "archive"),
  703. "uid_network_batch" => array("uid", "network(4)", "batch(64)"),
  704. "addr_uid" => array("addr(32)", "uid"),
  705. "nurl_uid" => array("nurl(32)", "uid"),
  706. "nick_uid" => array("nick(32)", "uid"),
  707. "dfrn-id" => array("dfrn-id"),
  708. "issued-id" => array("issued-id"),
  709. )
  710. );
  711. $database["conv"] = array(
  712. "fields" => array(
  713. "id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  714. "guid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  715. "recips" => array("type" => "text"),
  716. "uid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
  717. "creator" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  718. "created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  719. "updated" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  720. "subject" => array("type" => "text"),
  721. ),
  722. "indexes" => array(
  723. "PRIMARY" => array("id"),
  724. "uid" => array("uid"),
  725. )
  726. );
  727. $database["conversation"] = array(
  728. "fields" => array(
  729. "item-uri" => array("type" => "varbinary(255)", "not null" => "1", "primary" => "1"),
  730. "reply-to-uri" => array("type" => "varbinary(255)", "not null" => "1", "default" => ""),
  731. "conversation-uri" => array("type" => "varbinary(255)", "not null" => "1", "default" => ""),
  732. "conversation-href" => array("type" => "varbinary(255)", "not null" => "1", "default" => ""),
  733. "protocol" => array("type" => "tinyint(1) unsigned", "not null" => "1", "default" => "0"),
  734. "source" => array("type" => "mediumtext"),
  735. "received" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  736. ),
  737. "indexes" => array(
  738. "PRIMARY" => array("item-uri"),
  739. "conversation-uri" => array("conversation-uri"),
  740. )
  741. );
  742. $database["event"] = array(
  743. "fields" => array(
  744. "id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  745. "guid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  746. "uid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
  747. "cid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("contact" => "id")),
  748. "uri" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  749. "created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  750. "edited" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  751. "start" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  752. "finish" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  753. "summary" => array("type" => "text"),
  754. "desc" => array("type" => "text"),
  755. "location" => array("type" => "text"),
  756. "type" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  757. "nofinish" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  758. "adjust" => array("type" => "tinyint(1)", "not null" => "1", "default" => "1"),
  759. "ignore" => array("type" => "tinyint(1) unsigned", "not null" => "1", "default" => "0"),
  760. "allow_cid" => array("type" => "mediumtext"),
  761. "allow_gid" => array("type" => "mediumtext"),
  762. "deny_cid" => array("type" => "mediumtext"),
  763. "deny_gid" => array("type" => "mediumtext"),
  764. ),
  765. "indexes" => array(
  766. "PRIMARY" => array("id"),
  767. "uid_start" => array("uid", "start"),
  768. )
  769. );
  770. $database["fcontact"] = array(
  771. "fields" => array(
  772. "id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  773. "guid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  774. "url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  775. "name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  776. "photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  777. "request" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  778. "nick" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  779. "addr" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  780. "batch" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  781. "notify" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  782. "poll" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  783. "confirm" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  784. "priority" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  785. "network" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
  786. "alias" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  787. "pubkey" => array("type" => "text"),
  788. "updated" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  789. ),
  790. "indexes" => array(
  791. "PRIMARY" => array("id"),
  792. "addr" => array("addr(32)"),
  793. "url" => array("UNIQUE", "url(190)"),
  794. )
  795. );
  796. $database["ffinder"] = array(
  797. "fields" => array(
  798. "id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  799. "uid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
  800. "cid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0", "relation" => array("contact" => "id")),
  801. "fid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0", "relation" => array("fcontact" => "id")),
  802. ),
  803. "indexes" => array(
  804. "PRIMARY" => array("id"),
  805. )
  806. );
  807. $database["fserver"] = array(
  808. "fields" => array(
  809. "id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  810. "server" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  811. "posturl" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  812. "key" => array("type" => "text"),
  813. ),
  814. "indexes" => array(
  815. "PRIMARY" => array("id"),
  816. "server" => array("server(32)"),
  817. )
  818. );
  819. $database["fsuggest"] = array(
  820. "fields" => array(
  821. "id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  822. "uid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
  823. "cid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("contact" => "id")),
  824. "name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  825. "url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  826. "request" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  827. "photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  828. "note" => array("type" => "text"),
  829. "created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  830. ),
  831. "indexes" => array(
  832. "PRIMARY" => array("id"),
  833. )
  834. );
  835. $database["gcign"] = array(
  836. "fields" => array(
  837. "id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  838. "uid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
  839. "gcid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("gcontact" => "id")),
  840. ),
  841. "indexes" => array(
  842. "PRIMARY" => array("id"),
  843. "uid" => array("uid"),
  844. "gcid" => array("gcid"),
  845. )
  846. );
  847. $database["gcontact"] = array(
  848. "fields" => array(
  849. "id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  850. "name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  851. "nick" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  852. "url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  853. "nurl" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  854. "photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  855. "connect" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  856. "created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
  857. "updated" => array("type" => "datetime", "default" => NULL_DATE),
  858. "last_contact" => array("type" => "datetime", "default" => NULL_DATE),
  859. "last_failure" => array("type" => "datetime", "default" => NULL_DATE),
  860. "location" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  861. "about" => array("type" => "text"),
  862. "keywords" => array("type" => "text"),
  863. "gender" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
  864. "birthday" => array("type" => "varchar(32)", "not null" => "1", "default" => "0001-01-01"),
  865. "community" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  866. "contact-type" => array("type" => "tinyint(1)", "not null" => "1", "default" => "-1"),
  867. "hide" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  868. "nsfw" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
  869. "network" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  870. "addr" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  871. "notify" => array("type" => "text"),
  872. "alias" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  873. "generation" => array("type" => "tinyint(3)", "not null" => "1", "default" => "0"),
  874. "server_url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
  875. ),
  876. "indexes" => array(
  877. "PRIMARY" => array("id"),
  878. "nurl" => array("UNIQUE", "nurl(190)"),
  879. "name" => array("name(64)"),
  880. "nick" => array("nick(32)"),
  881. "addr" => array("addr(64)"),
  882. "hide_network_updated" => array("hide", "network(4)", "updated"),
  883. "updated" => array("updated"),
  884. )
  885. );
  886. $database["glink"] = array(
  887. "fields" => array(
  888. "id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
  889. "cid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("contact" => "id")),
  890. "uid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
  891. "gcid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("gcontact" => "id")),
  892. "zcid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("gcontact" => "id")),
  893. "updated<