migrate 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #!/usr/bin/env php
  2. <?php declare(strict_types=1);
  3. /**
  4. * PrivateBin
  5. *
  6. * a zero-knowledge paste bin
  7. *
  8. * @link https://github.com/PrivateBin/PrivateBin
  9. * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
  10. * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
  11. */
  12. // change this, if your php files and data are outside of your webservers document root
  13. define('PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
  14. define('PUBLIC_PATH', __DIR__ . DIRECTORY_SEPARATOR);
  15. require PATH . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
  16. use PrivateBin\Configuration;
  17. use PrivateBin\Model;
  18. // third argument in getopt requires PHP >= 7.1
  19. if (version_compare(PHP_VERSION, '7.1.0') < 0) {
  20. dieerr('migrate requires php 7.1 or above to work. Sorry.');
  21. }
  22. $longopts = array(
  23. "delete-after",
  24. "delete-during",
  25. "help"
  26. );
  27. $opts_arr = getopt("fhnv", $longopts, $rest);
  28. if ($opts_arr === false) {
  29. dieerr("Erroneous command line options. Please use --help");
  30. }
  31. if (array_key_exists("h", $opts_arr) || array_key_exists("help", $opts_arr)) {
  32. helpexit();
  33. }
  34. $delete_after = array_key_exists("delete-after", $opts_arr);
  35. $delete_during = array_key_exists("delete-during", $opts_arr);
  36. $force_overwrite = array_key_exists("f", $opts_arr);
  37. $dryrun = array_key_exists("n", $opts_arr);
  38. $verbose = array_key_exists("v", $opts_arr);
  39. if ($rest >= $argc) {
  40. dieerr("Missing source configuration directory");
  41. }
  42. if ($delete_after && $delete_during) {
  43. dieerr("--delete-after and --delete-during are mutually exclusive");
  44. }
  45. $srcconf = getConfig("source", $argv[$rest]);
  46. $rest++;
  47. $dstconf = getConfig("destination", ($rest < $argc ? $argv[$rest] : ""));
  48. if (($srcconf->getSection("model") == $dstconf->getSection("model")) &&
  49. ($srcconf->getSection("model_options") == $dstconf->getSection("model_options"))) {
  50. dieerr("Source and destination storage configurations are identical");
  51. }
  52. $srcmodel = new Model($srcconf);
  53. $srcstore = $srcmodel->getStore();
  54. $dstmodel = new Model($dstconf);
  55. $dststore = $dstmodel->getStore();
  56. $ids = $srcstore->getAllPastes();
  57. foreach ($ids as $id) {
  58. debug("Reading document ID " . $id);
  59. $paste = $srcstore->read($id);
  60. if (!is_array($paste)) {
  61. dieerr("Unable to read document ID " . $id);
  62. }
  63. $comments = $srcstore->readComments($id);
  64. savePaste($force_overwrite, $dryrun, $id, $paste, $dststore);
  65. foreach ($comments as $comment) {
  66. saveComment($force_overwrite, $dryrun, $id, $comment, $dststore);
  67. }
  68. if ($delete_during) {
  69. deletePaste($dryrun, $id, $srcstore);
  70. }
  71. }
  72. if ($delete_after) {
  73. foreach ($ids as $id) {
  74. deletePaste($dryrun, $id, $srcstore);
  75. }
  76. }
  77. debug("Done.");
  78. function deletePaste($dryrun, $pasteid, $srcstore)
  79. {
  80. if (!$dryrun) {
  81. debug("Deleting document ID " . $pasteid);
  82. $srcstore->delete($pasteid);
  83. } else {
  84. debug("Would delete document ID " . $pasteid);
  85. }
  86. }
  87. function saveComment ($force_overwrite, $dryrun, $pasteid, $comment, $dststore)
  88. {
  89. $parentid = $comment["parentid"];
  90. $commentid = $comment["id"];
  91. if (!$dststore->existsComment($pasteid, $parentid, $commentid)) {
  92. if (!$dryrun) {
  93. debug("Saving document ID " . $pasteid . ", parent id " .
  94. $parentid . ", comment id " . $commentid);
  95. if (!$dststore->createComment($pasteid, $parentid, $commentid, $comment)) {
  96. dieerr("Unable to save document ID " . $pasteid . ", parent id " .
  97. $parentid . ", comment id " . $commentid);
  98. }
  99. } else {
  100. debug("Would save document ID " . $pasteid . ", parent id " .
  101. $parentid . ", comment id " . $commentid);
  102. }
  103. } else if ($force_overwrite) {
  104. if (!$dryrun) {
  105. debug("Overwriting document ID " . $pasteid . ", parent id " .
  106. $parentid . ", comment id " . $commentid);
  107. if (!$dststore->createComment($pasteid, $parentid, $commentid, $comment)) {
  108. dieerr("Unable to overwrite document ID " . $pasteid . ", parent id " .
  109. $parentid . ", comment id " . $commentid);
  110. }
  111. } else {
  112. debug("Would overwrite document ID " . $pasteid . ", parent id " .
  113. $parentid . ", comment id " . $commentid);
  114. }
  115. } else {
  116. if (!$dryrun) {
  117. dieerr("Not overwriting document ID " . $pasteid . ", parent id " .
  118. $parentid . ", comment id " . $commentid);
  119. } else {
  120. dieerr("Would not overwrite document ID " . $pasteid . ", parent id " .
  121. $parentid . ", comment id " . $commentid);
  122. }
  123. }
  124. }
  125. function savePaste ($force_overwrite, $dryrun, $pasteid, $paste, $dststore)
  126. {
  127. if (!$dststore->exists($pasteid)) {
  128. if (!$dryrun) {
  129. debug("Saving document ID " . $pasteid);
  130. if (!$dststore->create($pasteid, $paste)) {
  131. dieerr("Unable to save document ID " . $pasteid);
  132. }
  133. } else {
  134. debug("Would save document ID " . $pasteid);
  135. }
  136. } else if ($force_overwrite) {
  137. if (!$dryrun) {
  138. debug("Overwriting document ID " . $pasteid);
  139. $dststore->delete($pasteid);
  140. if (!$dststore->create($pasteid, $paste)) {
  141. dieerr("Unable to overwrite document ID " . $pasteid);
  142. }
  143. } else {
  144. debug("Would overwrite document ID " . $pasteid);
  145. }
  146. } else {
  147. if (!$dryrun) {
  148. dieerr("Not overwriting document ID " . $pasteid);
  149. } else {
  150. dieerr("Would not overwrite document ID " . $pasteid);
  151. }
  152. }
  153. }
  154. function getConfig ($target, $confdir)
  155. {
  156. debug("Trying to load " . $target . " conf.php" .
  157. ($confdir === "" ? "" : " from " . $confdir));
  158. putenv("CONFIG_PATH=" . $confdir);
  159. $conf = new Configuration;
  160. putenv("CONFIG_PATH=");
  161. return $conf;
  162. }
  163. function dieerr ($text)
  164. {
  165. fprintf(STDERR, "ERROR: %s" . PHP_EOL, $text);
  166. die(1);
  167. }
  168. function debug ($text) {
  169. if ($GLOBALS["verbose"]) {
  170. printf("DEBUG: %s" . PHP_EOL, $text);
  171. }
  172. }
  173. function helpexit ()
  174. {
  175. print("migrate - Copy data between PrivateBin backends
  176. Usage:
  177. migrate [--delete-after] [--delete-during] [-f] [-n] [-v] srcconfdir
  178. [<dstconfdir>]
  179. migrate [-h|--help]
  180. Options:
  181. --delete-after delete data from source after all documents have successfully
  182. been copied to the destination
  183. --delete-during delete data from source after the current document have
  184. successfully been copied to the destination
  185. -f forcefully overwrite data which already exists at the
  186. destination
  187. -h, --help displays this help message
  188. -n dry run, do not copy data
  189. -v be verbose
  190. <srcconfdir> use storage backend configuration from conf.php found in
  191. this directory as source
  192. <dstconfdir> optionally, use storage backend configuration from conf.php
  193. found in this directory as destination; defaults to:
  194. " . PATH . "cfg" . DIRECTORY_SEPARATOR . "conf.php
  195. ");
  196. exit();
  197. }