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.

294 lines
8.8 KiB

  1. <?php
  2. /**
  3. * import account file exported from mod/uexport
  4. * args:
  5. * $a App Friendica App Class
  6. * $file Array array from $_FILES
  7. */
  8. require_once("include/Photo.php");
  9. define("IMPORT_DEBUG", False);
  10. function last_insert_id() {
  11. global $db;
  12. if (IMPORT_DEBUG)
  13. return 1;
  14. if ($db->mysqli) {
  15. $thedb = $db->getdb();
  16. return $thedb->insert_id;
  17. } else {
  18. return mysql_insert_id();
  19. }
  20. }
  21. function last_error() {
  22. global $db;
  23. return $db->error;
  24. }
  25. /**
  26. * Remove columns from array $arr that aren't in table $table
  27. *
  28. * @param string $table Table name
  29. * @param array &$arr Column=>Value array from json (by ref)
  30. */
  31. function check_cols($table, &$arr) {
  32. $query = sprintf("SHOW COLUMNS IN `%s`", dbesc($table));
  33. logger("uimport: $query", LOGGER_DEBUG);
  34. $r = q($query);
  35. $tcols = array();
  36. // get a plain array of column names
  37. foreach ($r as $tcol) {
  38. $tcols[] = $tcol['Field'];
  39. }
  40. // remove inexistent columns
  41. foreach ($arr as $icol => $ival) {
  42. if (!in_array($icol, $tcols)) {
  43. unset($arr[$icol]);
  44. }
  45. }
  46. }
  47. /**
  48. * Import data into table $table
  49. *
  50. * @param string $table Table name
  51. * @param array $arr Column=>Value array from json
  52. */
  53. function db_import_assoc($table, $arr) {
  54. if (isset($arr['id']))
  55. unset($arr['id']);
  56. check_cols($table, $arr);
  57. $cols = implode("`,`", array_map('dbesc', array_keys($arr)));
  58. $vals = implode("','", array_map('dbesc', array_values($arr)));
  59. $query = "INSERT INTO `$table` (`$cols`) VALUES ('$vals')";
  60. logger("uimport: $query", LOGGER_TRACE);
  61. if (IMPORT_DEBUG)
  62. return true;
  63. return q($query);
  64. }
  65. function import_cleanup($newuid) {
  66. q("DELETE FROM `user` WHERE uid = %d", $newuid);
  67. q("DELETE FROM `contact` WHERE uid = %d", $newuid);
  68. q("DELETE FROM `profile` WHERE uid = %d", $newuid);
  69. q("DELETE FROM `photo` WHERE uid = %d", $newuid);
  70. q("DELETE FROM `group` WHERE uid = %d", $newuid);
  71. q("DELETE FROM `group_member` WHERE uid = %d", $newuid);
  72. q("DELETE FROM `pconfig` WHERE uid = %d", $newuid);
  73. }
  74. function import_account(&$a, $file) {
  75. logger("Start user import from " . $file['tmp_name']);
  76. /*
  77. STEPS
  78. 1. checks
  79. 2. replace old baseurl with new baseurl
  80. 3. import data (look at user id and contacts id)
  81. 4. archive non-dfrn contacts
  82. 5. send message to dfrn contacts
  83. */
  84. $account = json_decode(file_get_contents($file['tmp_name']), true);
  85. if ($account === null) {
  86. notice(t("Error decoding account file"));
  87. return;
  88. }
  89. if (!x($account, 'version')) {
  90. notice(t("Error! No version data in file! This is not a Friendica account file?"));
  91. return;
  92. }
  93. /*
  94. // this is not required as we remove columns in json not in current db schema
  95. if ($account['schema'] != DB_UPDATE_VERSION) {
  96. notice(t("Error! I can't import this file: DB schema version is not compatible."));
  97. return;
  98. }
  99. */
  100. // check for username
  101. $r = q("SELECT uid FROM user WHERE nickname='%s'", $account['user']['nickname']);
  102. if ($r === false) {
  103. logger("uimport:check nickname : ERROR : " . last_error(), LOGGER_NORMAL);
  104. notice(t('Error! Cannot check nickname'));
  105. return;
  106. }
  107. if (count($r) > 0) {
  108. notice(sprintf(t("User '%s' already exists on this server!"), $account['user']['nickname']));
  109. return;
  110. }
  111. // check if username matches deleted account
  112. $r = q("SELECT id FROM userd WHERE username='%s'", $account['user']['nickname']);
  113. if ($r === false) {
  114. logger("uimport:check nickname : ERROR : " . last_error(), LOGGER_NORMAL);
  115. notice(t('Error! Cannot check nickname'));
  116. return;
  117. }
  118. if (count($r) > 0) {
  119. notice(sprintf(t("User '%s' already exists on this server!"), $account['user']['nickname']));
  120. return;
  121. }
  122. $oldbaseurl = $account['baseurl'];
  123. $newbaseurl = $a->get_baseurl();
  124. $olduid = $account['user']['uid'];
  125. unset($account['user']['uid']);
  126. unset($account['user']['account_expired']);
  127. unset($account['user']['account_expires_on']);
  128. unset($account['user']['expire_notification_sent']);
  129. foreach ($account['user'] as $k => &$v) {
  130. $v = str_replace($oldbaseurl, $newbaseurl, $v);
  131. }
  132. // import user
  133. $r = db_import_assoc('user', $account['user']);
  134. if ($r === false) {
  135. //echo "<pre>"; var_dump($r, $query, mysql_error()); killme();
  136. logger("uimport:insert user : ERROR : " . last_error(), LOGGER_NORMAL);
  137. notice(t("User creation error"));
  138. return;
  139. }
  140. $newuid = last_insert_id();
  141. //~ $newuid = 1;
  142. // Generate a new guid for the account. Otherwise there will be problems with diaspora
  143. q("UPDATE `user` SET `guid` = '%s' WHERE `uid` = %d",
  144. dbesc(generate_user_guid()), intval($newuid));
  145. foreach ($account['profile'] as &$profile) {
  146. foreach ($profile as $k => &$v) {
  147. $v = str_replace($oldbaseurl, $newbaseurl, $v);
  148. foreach (array("profile", "avatar") as $k)
  149. $v = str_replace($oldbaseurl . "/photo/" . $k . "/" . $olduid . ".jpg", $newbaseurl . "/photo/" . $k . "/" . $newuid . ".jpg", $v);
  150. }
  151. $profile['uid'] = $newuid;
  152. $r = db_import_assoc('profile', $profile);
  153. if ($r === false) {
  154. logger("uimport:insert profile " . $profile['profile-name'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
  155. info(t("User profile creation error"));
  156. import_cleanup($newuid);
  157. return;
  158. }
  159. }
  160. $errorcount = 0;
  161. foreach ($account['contact'] as &$contact) {
  162. if ($contact['uid'] == $olduid && $contact['self'] == '1') {
  163. foreach ($contact as $k => &$v) {
  164. $v = str_replace($oldbaseurl, $newbaseurl, $v);
  165. foreach (array("profile", "avatar", "micro") as $k)
  166. $v = str_replace($oldbaseurl . "/photo/" . $k . "/" . $olduid . ".jpg", $newbaseurl . "/photo/" . $k . "/" . $newuid . ".jpg", $v);
  167. }
  168. }
  169. if ($contact['uid'] == $olduid && $contact['self'] == '0') {
  170. // set contacts 'avatar-date' to "0000-00-00 00:00:00" to let poller to update urls
  171. $contact["avatar-date"] = "0000-00-00 00:00:00" ;
  172. switch ($contact['network']) {
  173. case NETWORK_DFRN:
  174. // send relocate message (below)
  175. break;
  176. case NETWORK_ZOT:
  177. /// @TODO handle zot network
  178. break;
  179. case NETWORK_MAIL2:
  180. /// @TODO ?
  181. break;
  182. case NETWORK_FEED:
  183. case NETWORK_MAIL:
  184. // Nothing to do
  185. break;
  186. default:
  187. // archive other contacts
  188. $contact['archive'] = "1";
  189. }
  190. }
  191. $contact['uid'] = $newuid;
  192. $r = db_import_assoc('contact', $contact);
  193. if ($r === false) {
  194. logger("uimport:insert contact " . $contact['nick'] . "," . $contact['network'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
  195. $errorcount++;
  196. } else {
  197. $contact['newid'] = last_insert_id();
  198. }
  199. }
  200. if ($errorcount > 0) {
  201. notice(sprintf(tt("%d contact not imported", "%d contacts not imported", $errorcount), $errorcount));
  202. }
  203. foreach ($account['group'] as &$group) {
  204. $group['uid'] = $newuid;
  205. $r = db_import_assoc('group', $group);
  206. if ($r === false) {
  207. logger("uimport:insert group " . $group['name'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
  208. } else {
  209. $group['newid'] = last_insert_id();
  210. }
  211. }
  212. foreach ($account['group_member'] as &$group_member) {
  213. $group_member['uid'] = $newuid;
  214. $import = 0;
  215. foreach ($account['group'] as $group) {
  216. if ($group['id'] == $group_member['gid'] && isset($group['newid'])) {
  217. $group_member['gid'] = $group['newid'];
  218. $import++;
  219. break;
  220. }
  221. }
  222. foreach ($account['contact'] as $contact) {
  223. if ($contact['id'] == $group_member['contact-id'] && isset($contact['newid'])) {
  224. $group_member['contact-id'] = $contact['newid'];
  225. $import++;
  226. break;
  227. }
  228. }
  229. if ($import == 2) {
  230. $r = db_import_assoc('group_member', $group_member);
  231. if ($r === false) {
  232. logger("uimport:insert group member " . $group_member['id'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
  233. }
  234. }
  235. }
  236. foreach ($account['photo'] as &$photo) {
  237. $photo['uid'] = $newuid;
  238. $photo['data'] = hex2bin($photo['data']);
  239. $p = new Photo($photo['data'], $photo['type']);
  240. $r = $p->store(
  241. $photo['uid'], $photo['contact-id'], //0
  242. $photo['resource-id'], $photo['filename'], $photo['album'], $photo['scale'], $photo['profile'], //1
  243. $photo['allow_cid'], $photo['allow_gid'], $photo['deny_cid'], $photo['deny_gid']
  244. );
  245. if ($r === false) {
  246. logger("uimport:insert photo " . $photo['resource-id'] . "," . $photo['scale'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
  247. }
  248. }
  249. foreach ($account['pconfig'] as &$pconfig) {
  250. $pconfig['uid'] = $newuid;
  251. $r = db_import_assoc('pconfig', $pconfig);
  252. if ($r === false) {
  253. logger("uimport:insert pconfig " . $pconfig['id'] . " : ERROR : " . last_error(), LOGGER_NORMAL);
  254. }
  255. }
  256. // send relocate messages
  257. proc_run(PRIORITY_HIGH, 'include/notifier.php', 'relocate', $newuid);
  258. info(t("Done. You can now login with your username and password"));
  259. goaway($a->get_baseurl() . "/login");
  260. }