migrate 6.2 KB

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