Odyssey
ody_migr_server.prg
1 <?php
2 /**
3  * File: ody_migr_server.prg
4  * This file is a server for ody_migr_client.prg. Client/server communication happens via ajax post request and http response.
5  */
6 
7 // **********************************************************************************************
8 // Top portion: import required libraries, check permissions and extract string queries and/or post data
9 // **********************************************************************************************
10 
11 $monLibrary= dirname(__FILE__) . "/../library";
12 $sharedLibrary= dirname(__FILE__) . "/../../shared/library";
13 
14 // Includes necessary files
15 require_once("$monLibrary/cu_top.i");
16 require_once("$monLibrary/ck_hticket.i");
17 require_once("$sharedLibrary/hcuCommon.i");
18 require_once("$sharedLibrary/cu_flagconst.i");
19 
20 if (!CheckPerm($link, $Hu, basename($_SERVER['SCRIPT_NAME']), $_SERVER['REMOTE_ADDR'])) {
21  header("Location: /hcuadm/hcu_noperm.prg");
22  exit;
23 }
24 
25 // session id for migration audit log file
26 $AUDIT_LOG_TRANSACTION = bin2hex(openssl_random_pseudo_bytes(8));
27 
28 // **********************************************************************************************
29 // Specify some global variables and utility functions
30 // **********************************************************************************************
31 
32 /**
33  * function GetSecret()
34  * @return The secret string to create / verify the passphrase.
35  */
36 function GetSecret() {
37  return "n3c3s1t@m0\$Mud@rT0d@\$L@\$C0\$@\$!";
38 }
39 
40 /**
41  * function CreateHash($action, $cu)
42  * @return sha1 of the action, cu, and the secret string.
43  */
44 function CreateHash($action, $cu) {
45  return sha1("${action}${cu}" . GetSecret());
46 }
47 
48 $passed_arguments = "";
49 $secret_key = GetSecret();
50 putenv("ODY_MIGR_SECRET_KEY=$secret_key");
51 
52 $response = array("success"=> False, "message" => "");
53 
54 /**
55  * Get logs directory path
56  *
57  * @param $cu -- credit union code
58  * @return str path to logs directory
59  */
60 function GetLogsDir($cu) {
61  return "/home/" . strtolower($cu) . "/logs";
62 }
63 
64 /**
65  * Get tmp directory path
66  *
67  * @param $cu -- credit union code
68  * @return str path to tmp directory
69  */
70 function GetTmpDir($cu) {
71  return "/home/" . strtolower($cu) . "/tmp";
72 }
73 
74 /**
75  * Get wip lock file name given $cu and $category
76  *
77  * @param $cu -- credit union code
78  * @param $category -- migration data category
79  *
80  * @return wip lock file full path
81  */
82 function getWIPFile($cu, $category, $operation) {
83  return GetTmpDir($cu) . "/.ody_migr_" . $operation . "_" . $category . ".wip";
84 }
85 
86 /**
87  * Get switch accounts setting file
88  *
89  * @param $cu -- credit union code
90  *
91  * @return str path to switch accounts setting file
92  */
93 function getSwitchAccountsSettingFile($cu) {
94  return GetTmpDir($cu) . "/.ody_migr_include_switchaccounts_in_final_migr";
95 }
96 
97 /**
98  * Get done lock file name given $cu and $category
99  *
100  * @param $cu -- credit union code
101  * @param $category -- migration data category
102  *
103  * @return completed lock file full path
104  */
105 function getDoneFile($cu, $category, $operation) {
106  return GetTmpDir($cu) . "/.ody_migr_" . $operation . "_" . $category . ".done";
107 }
108 
109 /**
110  * Delete WIP file
111  *
112  * @param $cu -- credit union code
113  * @param $category -- migration data category
114  *
115  * @return success or failure response array
116  */
117 function deleteWIPFile($cu, $category, $operation) {
118  $wip_file = getWIPFile($cu, $category, $operation);
119 
120  if (unlink($wip_file)) {
121  return array("success"=> True, "message" => "Lock ('wip') file deleted successfully.");
122  } else {
123  return array("success"=> False, "message" => "Something went wrong while deleting lock ('wip') file: " . $wip_file);
124  }
125 }
126 
127 /**
128  * Mark wip lockfile as done (after migration completion)
129  *
130  * @param $cu -- credit union code
131  * @param $category -- migration data category
132  *
133  * @return success or failure response array
134  */
135 function markWIPAsComplete($cu, $category, $operation) {
136  $wip_file = getWIPFile($cu, $category, $operation);
137  $done_file = getDoneFile($cu, $category, $operation);
138 
139  if (file_exists($wip_file)) {
140  $cmd = "mv $wip_file $done_file";
141 
142  $results = system($cmd);
143 
144  if ($results === false) {
145  return array("success"=> False, "message" => "Marking WIP file as Done failed.");
146  } else {
147  // update memdata and memhist execution count
148  if ($category == "memdata" || $category == "memhist") {
149 
150  $final_migr_memcount_file = getFinalMigrationConfigFile($cu);
151  if(file_exists($final_migr_memcount_file) && (($fileStr = file_get_contents($final_migr_memcount_file)) != False)) {
152  $mem_count_arr = explode(",", explode("\n", $fileStr)[1]);
153  $memdata_count = (int)$mem_count_arr[0];
154  $memhist_count = (int)$mem_count_arr[1];
155  if ($category == "memdata") {
156  $memdata_count++;
157  }
158  if ($category == "memhist") {
159  $memhist_count++;
160  }
161  $new_vals = "memdata_count,memhist_count\n" . $memdata_count . "," . $memhist_count ."\n";
162  file_put_contents($final_migr_memcount_file, $new_vals);
163  }
164  }
165  return array("success"=> True, "message" => "WIP marked as Done." . $wip_file);
166  }
167  } else {
168  return array("success"=> False, "message" => "WIP file does not exist." . $wip_file);
169  }
170 }
171 
172 /**
173  * Get log file
174  *
175  * @param $cu -- credit union code
176  * @param $category -- migration data category
177  * @param $operation -- migration operation
178  *
179  * @return log file full path
180  */
181 function getLogFile($cu, $operation, $category) {
182  return GetLogsDir($cu) . "/ody_migr_" . $operation . "_" . $category . ".log";
183 }
184 
185 /**
186  * Get monitor lock file path
187  *
188  * @param $cu -- credit union code
189  *
190  * @return monitor lock file full path
191  */
192 function getMonitorLockFile($cu) {
193  return GetTmpDir($cu) . "/.ody_migr_monitor_lock";
194 }
195 
196 
197 /**
198  * Get public_html path
199  *
200  * @param $cu -- credit union code
201  *
202  * @return public_html full path
203  */
204 function getPublicHtmlPath($cu) {
205  return "/home/" . strtolower($cu) . "/public_html";
206 }
207 
208 /**
209  * Get public_html path
210  *
211  * @param $cu -- credit union code
212  *
213  * @return public_html full path
214  */
215 function getLockFileForPreventingFurtherMigration($cu, $cat_group) {
216  if($cat_group == "Settings") {
217  return GetTmpDir($cu) . "/.ody_migr_prevent_further_settings_migration";
218  } else { // Admin
219  return GetTmpDir($cu) . "/.ody_migr_prevent_further_admin_migration";
220  }
221 }
222 
223 
224 /**
225  * Update progress stats
226  *
227  * @param $line -- log string
228  * @param $category -- migration data category
229  *
230  * @return completed so far and total tables/members count statistic of $category migration
231  */
232 function updateProgress($line, $category) {
233  if ($category == "memdata") {
234  $res_progress_arr = explode("/", trim(explode("|", trim(explode("[PROGRESS] Members imported:", $line)[1]))[0]));
235  return $res_progress_arr;
236 
237  } else {
238  return array(0, 0);
239  }
240 }
241 
242 /**
243  * Get account cross reference csv file path
244  *
245  * @param $cu -- credit union code
246  *
247  * @return account cross reference file full path
248  */
249 function getAccCrossRefFile($cu) {
250  return GetTmpDir($cu) . "/ody_migr_user_id_cross_reference.csv";
251 }
252 
253 /**
254  * Get final migration main lock file
255  *
256  * @param $cu -- credit union code
257  *
258  * @return account cross reference file full path
259  */
260 function getFinalMigrationMainLock($cu) {
261  return GetTmpDir($cu) . "/.ody_migr_final";
262 }
263 
264 /**
265  * Get final migration main completion lock file
266  *
267  * @param $cu -- credit union code
268  *
269  * @return str final migration completion lock file
270  */
271 function getFinalMigrationDoneLock($cu) {
272  return GetTmpDir($cu) . "/.ody_migr_final.complete";
273 }
274 
275 /**
276  * Get orphan member list file path
277  *
278  * @param $cu -- credit union code
279  *
280  * @return str orphan member list file path
281  */
282 function getOrphanMemberListFile($cu) {
283  return GetTmpDir($cu) . "/ody_migr_mammoth_orphaned_members.csv";
284 }
285 
286 /**
287  * Get final migration config lock file
288  *
289  * @param $cu -- credit union code
290  *
291  * @return str final migration config lock file
292  */
293 function getFinalMigrationConfigFile($cu) {
294  return GetTmpDir($cu) . "/.ody_migr_members_exec_count";
295 }
296 
297 /**
298  * Parse a log file line by line
299  *
300  * @param $file -- log file to read
301  * @param $category -- migration data category
302  * @param $operation -- migration operation
303  *
304  * @return log_content => all logs written by migration process so far
305  end_of_log => flag to indicate if migration completed or not
306  file_status => file existence message
307  progress_status => total and so far completed progress information to be used to populate progress bar
308  */
309 function readContent($file, $operation, $category, $cu) {
310  $endOfLog = false;
311  $logContent = [];
312 
313  $progress_current = 0;
314  $progress_total = 0;
315 
316  if (!file_exists($file)) {
317  $progress_status = array("current"=>$progress_current, "total"=>$progress_total);
318  $file_status = "Log file '" .$file . "' does not exist.";
319  return array("does_not_exist" => True, "log_content" => $logContent, "end_of_log"=> $endOfLog, "file_status" => $file_status, "progress_status"=>$progress_status);
320  }
321 
322  $fileHandle = fopen($file, 'r');
323  $file_status = "Log file '" . $file . "' exists.";
324 
325  while (!feof($fileHandle)) {
326  $line = fgets($fileHandle);
327  if ($line == false) {
328  break;
329  }
330 
331  if (strpos($line, "[PROGRESS] ") !== false && $operation == "migrate") {
332  $progress_update = updateProgress($line, $category);
333  $progress_current = $progress_update[0];
334  $progress_total = $progress_update[1];
335  }
336 
337  $logContent[] = $line;
338 
339  if (strpos($line, "MIGRATION DONE") !== false) {
340  $endOfLog = true;
341  auditLogMigrationExecution($cu, "", $operation, $category, "Migration completed. Marked by browser auto-refresh.");
342  break;
343  }
344  }
345  fclose($fileHandle);
346 
347  $progress_status = array("current"=>$progress_current, "total"=>$progress_total);
348  return array("does_not_exist" => False, "log_content" => $logContent, "end_of_log"=> $endOfLog, "file_status" => $file_status, "progress_status"=>$progress_status);
349 }
350 
351 
352 /**
353  * function deleteOdysseyTemporaryFiles($cu)
354  *
355  * ****IMPORTANT: CAUTION CAUTION CAUTION****
356  *
357  * SINCE THIS FUNCTION WILL BE CALLED AFTER THE GO LIVE DAY, PLEASE
358  * DO NOT ADD ANY CODE THAT WILL DELETE ANY DATABASE RELATED DATA. AT
359  * THIS POINT, WE ARE DONE MIGRATING PRODDUCTION DATA FROM MAMMOTH TO
360  * ODYSSEY AND WE CERTAINLY DON'T WANT TO MESS AROUND WITH THE MIGRATED
361  * DATA ON THE DATABASE AFTER THE FINAL DATA MIGRATION.
362  *
363  * This function only deletes temporary files (in the filesystem) in
364  * Odyssey and Mammoth after migration completion and touches a lock
365  * file that prevents the "Import Mammoth Data" screen on the monitor
366  * from displaying the migration related html elements on the screen.
367  *
368  * @param $cu -- the Credit Union code (uppercase.)
369  *
370  * @return response text to append to notification bar in the client
371  */
372 function deleteOdysseyTemporaryFiles($cu) {
373 
374  $memhist_file = "memhist";
375  $memhist_acc_file = "memhist_accounthistory";
376  $memhist_loan_file = "memhist_loanhistory";
377 
378  $lowercaseCu = strtolower($cu);
379 
380  $dir = "/home/$lowercaseCu/tmp";
381  $memhist_file = "$dir/${memhist_file}";
382  $memhist_acc_file = "$dir/${memhist_acc_file}";
383  $memhist_loan_file = "$dir/${memhist_loan_file}";
384 
385  if (is_dir($dir)) {
386  $all_success = True;
387 
388  if (file_exists($memhist_file)) {
389  $all_success = $all_success && unlink($memhist_file);
390  }
391 
392  if (file_exists($memhist_acc_file)) {
393  $all_success = $all_success && unlink($memhist_acc_file);
394  }
395 
396  if (file_exists($memhist_loan_file)) {
397  $all_success = $all_success && unlink($memhist_loan_file);
398  }
399 
400  if($all_success) {
401  return "[Cleanup ODY] Temporary files deleted.";
402  } else {
403  // only a few files might have been deleted (not a critical operation)
404  return "[Cleanup ODY] Something went wrong while deleting temporary files.";
405  }
406  } else {
407  return "[Cleanup ODY] No such directory '$dir'.";
408  }
409 }
410 
411 /**
412  * function makeMammothEndpointCall($server, $cu, $action, $hash)
413  * Calls the Mammoth endpoint for the export.
414  *
415  * @param $server -- www4, www3, www5, or www6. www doesn't return anything specific to the Credit Union.
416  * @param $cu -- the Credit Union code (uppercase.)
417  * @param $action -- the action to perform.
418  * @param $hash -- the passphrase to check.
419  * @param $parameters -- any additional parameters that need to be passed to Mammoth.
420  *
421  * @return array of the response. Mammoth endpoint returns data in a JSON encoded structure.
422  */
423 function makeMammothEndpointCall($server, $cu, $action, $hash, $parameters = array()) {
424 
425  if (!isset($parameters) || !is_array($parameters)) {
426  $parameters = array();
427  }
428  $parameters["passphrase"] = $hash;
429  $parameters["action"] = $action;
430  $url = "";
431 
432  $parameters = http_build_query($parameters);
433  $url = "${server}.homecu.net/hcuadm/mOdysseyMigrExp.prg?cu=" . urlencode($cu) . "&" . $parameters;
434 
435  $ch = curl_init($url);
436 
437  curl_setopt($ch, CURLOPT_USERPWD, "nobody:no1home");
438  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // get response as string
439  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
440  curl_setopt($ch, CURLOPT_FORBID_REUSE, true); // For testing, there are a lot of the same calls but make sure that it is fresh.
441  curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); // For testing, there are a lot of the same calls but make sure that it is fresh.
442 
443  $response = curl_exec($ch);
444 
445  $response = isset($response) && trim($response) != "" ? HCU_JsonDecode($response)
446  : array("action" => $action, "error" => "CURL call didn't return anything. (" . __FILE__ . ":" . __LINE__ . ")", "data" => array());
447 
448  return $response;
449 }
450 
451 /**
452  * Validate migration options before execution
453  *
454  * @param $cu -- credit union code
455  * @param $operation -- clean/migrate/summar
456  * @param $category -- migration category
457  *
458  * @return Array response array
459  */
460 function validateOptionsBeforeScriptExecution($cu, $operation, $category) {
461  $valid_response = array("success"=> True, "message" => "Options validated.");
462  // Request validation if operation=clean
463  if ($operation == "clean") {
464  // check if Settings (settings) data category is locked from deleted.
465  $preventSettingsLockFile = getLockFileForPreventingFurtherMigration($cu, "Settings");
466  if(file_exists($preventSettingsLockFile) && $category == "settings") {
467  return array("success"=> False, "message" => "Data category '$category' ALREADY MIGRATED and (possibly) MODIFIED on the target system. 'clean' operations for 'settings' is LOCKED to PREVENT ACCIDENTAL DELETIONS.");
468  }
469  // check if Admin (admin) data category is locked from deleted.
470  $preventAdminLockFile = getLockFileForPreventingFurtherMigration($cu, "Admin");
471  if(file_exists($preventAdminLockFile) && $category == "admin") {
472  return array("success"=> False, "message" => "Data category '$category' ALREADY MIGRATED. 'clean' operation 'admin' is LOCKED to PREVENT ACCIDENTAL DELETIONS.");
473  }
474 
475  // do not allow to run 'clean-switchaccounts' -- UI also validates this
476  if($category == "switchaccounts") {
477  return array("success"=> False, "message" => "INVALID migration operation '$operation'" . "-" ."'$category' for direct deletion.");
478  }
479 
480  // do not allow clean if the WIP file exists for the same category
481  $wip_file_migrate = getWIPFile($cu, $category, "migrate");
482  if(file_exists($wip_file_migrate)) {
483  return array("success"=> False, "message" => "Cannot clean up in-progress work 'migrate-$category'");
484  }
485  }
486 
487  return $valid_response;
488 }
489 
490 /**
491  * Execute python migration script
492  *
493  * @param $server -- Mammoth endpoint
494  * @param $operation -- Migration operation (migrate, summary, clean)
495  * @param $cu -- credit union CU code
496  * @param $category -- migration data category
497  * @param $username -- Mammoth credential - username
498  * @param $password -- Mammoth credential - password
499  *
500  * @return success or failure response
501  */
502 function executeMigrationScript($server, $operation, $cu, $category, $username, $password, $bg=True) {
503 
504  $PYTHON_EXEC = "/usr/bin/python3";
505  $rootScriptsDir = "/opt/odyssey/tools/bin";
506  if (getenv("DEVMODE") == "1") {
507  $rootScriptsDir = "/project/app/tools/bin";
508  }
509 
510  $cmd = $PYTHON_EXEC . " " . $rootScriptsDir . "/ody_migr_executor.py "
511  . escapeshellarg($server) . " "
512  . escapeshellarg($operation) . " "
513  . escapeshellarg(strtoupper($cu)) . " "
514  . escapeshellarg($category) . " "
515  . escapeshellarg($username) . " "
516  . escapeshellarg($password) . " "
517  . " > /dev/null";
518 
519  if ($bg == True) {
520  $cmd .= " &";
521  }
522 
523  // audit log data migration execution
524  auditLogMigrationExecution($cu, $username, $operation, $category, "Started.");
525 
526  // cleanup exiting log before executing migrate and summary operations
527  if ($operation == "migrate" || $operation == "summary") {
528  $migrate_summary_log_file = getLogFile($cu, $operation, $category);
529  if (file_exists($migrate_summary_log_file)) {
530  unlink($migrate_summary_log_file);
531  }
532  }
533 
534  // execute migration script
535  exec($cmd, $scriptOutput, $returnStatus);
536 
537  if ($returnStatus > 0) {
538  return array("success"=> False,
539  "message" => "(" . $rootScriptsDir .") " . " ".join($scriptOutput));
540  } else {
541  return array("success"=> True,
542  "message" => " Migration operation ('" . $operation . " - " . $category . "') STARTED successfully. <br>(" . $rootScriptsDir .") " . " ".join($scriptOutput));
543  }
544 }
545 
546 /**
547  * Write migration execution audit log to a file
548  *
549  * @param $cu -- credit union CU code
550  * @param $atttempted_username -- Username used in the migration screen
551  * @param $migr_operation -- migration operation to be logged (migrate, clean, etc.)
552  * @param $migr_category -- {settings,admin,memdata,memhist,switchaccounts,final}
553  * @param $comment -- optional column for additional information about the log record
554  *
555  */
556 function auditLogMigrationExecution($cu, $attempted_username, $migr_operation, $migr_category, $comment="") {
557  global $AUDIT_LOG_TRANSACTION, $Hu;
558  $current_monitor_user = $Hu;
559  $date_now = new DateTime('now', new DateTimeZone('America/Boise'));
560  $date_log= $date_now->format('Y-m-d:H-i-s:T');
561  $audit_log_file = "/home/${cu}/tmp/ody_migr_execution_logs.csv";
562  $audit_log_record = array($AUDIT_LOG_TRANSACTION,
563  $date_log,
564  $cu,
565  $current_monitor_user,
566  strtoupper($attempted_username),
567  $migr_operation,
568  $migr_category,
569  $comment);
570 
571  # should only be created once, and not to be deleted
572  if (!file_exists($audit_log_file)) {
573  $audit_log_header = array("SessionId",
574  "Date",
575  "CreditUnion",
576  "MonitorUser",
577  "EnteredUsername",
578  "Operation",
579  "Category(ies)",
580  "Comment");
581  touch($audit_log_file);
582  $fp = fopen($audit_log_file, "a");
583  fputcsv($fp, $audit_log_header);
584  } else {
585  $fp = fopen($audit_log_file, "a");
586  }
587 
588  fputcsv($fp, $audit_log_record);
589  fclose($fp);
590 }
591 
592 
593 /**
594  * Cleanup lock files after clean operation is completed
595  *
596  * @param $cu -- credit union CU code
597  * @param $category -- Migration Category
598  * @param $operation -- Migration operation
599  * - only clean is relevant
600  *
601  * @return null
602  */
603 function cleanupAfterClean($cu, $category, $operation) {
604  if ($operation == "clean") {
605  // delete lock file for previous migrate-$category completion
606  $done_file = getDoneFile($cu, $category, "migrate");
607  if(file_exists($done_file)) {
608  unlink($done_file);
609 
610  // clean invalidates previous migration of the same category, delete
611  // the log file for migrate-$category, if any
612  $migrate_log_file = getLogFile($cu, "migrate", $category);
613  if(file_exists($migrate_log_file)) {
614  unlink($migrate_log_file);
615  }
616 
617  $summary_log_file = getLogFile($cu, "summary", $category);
618  if(file_exists($summary_log_file)) {
619  unlink($summary_log_file);
620  }
621 
622  if ($category == "memdata") {
623  // delete switchaccounts temp files when cleaning memdata
624  $sa_migrate_done_file = getDoneFile($cu, "switchaccounts", "migrate");
625  if(file_exists($sa_migrate_done_file)) {
626  // remove done file
627  unlink($sa_migrate_done_file);
628 
629  // remove log file
630  $sa_migrate_log_file = getLogFile($cu, "migrate", "switchaccounts");
631  if(file_exists($sa_migrate_log_file)) {
632  unlink($sa_migrate_log_file);
633  }
634 
635  // remove summary log file
636  $sa_summary_log_file = getLogFile($cu, "summary", "switchaccounts");
637  if(file_exists($sa_summary_log_file)) {
638  unlink($sa_summary_log_file);
639  }
640  }
641  // delete loanapps temp files when cleaning memdata
642  $loanapp_migrate_done_file = getDoneFile($cu, "loanapp", "migrate");
643  if(file_exists($loanapp_migrate_done_file)) {
644  // remove done file
645  unlink($loanapp_migrate_done_file);
646 
647  // remove log file
648  $loanapp_migrate_log_file = getLogFile($cu, "migrate", "loanapp");
649  if(file_exists($loanapp_migrate_log_file)) {
650  unlink($loanapp_migrate_log_file);
651  }
652 
653  // remove log file
654  $loanapp_summary_log_file = getLogFile($cu, "summary", "loanapp");
655  if(file_exists($loanapp_summary_log_file)) {
656  unlink($loanapp_summary_log_file);
657  }
658  }
659  }
660  }
661 
662  // deleting settings invalidates locking Settings
663  if($category == "settings") {
664  $preventSettingsLockFile = getLockFileForPreventingFurtherMigration($cu, "Settings");
665  if(file_exists($preventSettingsLockFile)) {
666  unlink($preventSettingsLockFile);
667  }
668  }
669 
670  // deleting admin invalidates locking of Admin
671  if($category == "admin") {
672  $preventAdminLockFile = getLockFileForPreventingFurtherMigration($cu, "Admin");
673  if(file_exists($preventAdminLockFile)) {
674  unlink($preventAdminLockFile);
675  }
676  }
677  }
678 }
679 
680 /**
681  * Execute finam members migration
682  *
683  * @param $server -- Mammoth endpoint
684  * @param $cu -- credit union CU code
685  * @param $username -- Mammoth credential - username
686  * @param $password -- Mammoth credential - password
687  *
688  * @return success or failure response
689  */
690 function executeFinalMigration($server, $cu, $username, $password) {
691  // return if final migration execution already completed
692  if (file_exists(getFinalMigrationDoneLock($cu))) {
693  return array("success"=> False,
694  "message" => "<b>Final migration (migrate-{memdata,memhist}) already executed once."
695  . " Re-migration is not advised. If you really need to run this again, speak to a"
696  . " develolper to reset final migration before trying again. </b>");
697  }
698 
699  $python_exec = "/usr/bin/python3";
700  $root_script_dir = "/opt/odyssey/tools/bin";
701  if (getenv("DEVMODE") == "1") {
702  $root_script_dir = "/project/app/tools/bin";
703  }
704  $developer_help_msg = " Please contact a developer to look into it.";
705 
706  $final_migr_lck = getFinalMigrationMainLock($cu);
707 
708  // if final migration lock file exist, return without execution
709  if (file_exists($final_migr_lck)) {
710  return array("success"=> False,
711  "message" => "Final migration (members data) already IN PROGRESS."
712  . $developer_help_msg);
713  }
714  // if in-progress (memdata/switchaccounts/loanapp/memhist) lock files exist,
715  // return without execution
716  elseif (file_exists(getWIPFile($cu, "memdata", "migrate"))
717  || file_exists(getWIPFile($cu, "switchaccounts", "migrate"))
718  || file_exists(getWIPFile($cu, "loanapp", "migrate"))
719  || file_exists(getWIPFile($cu, "memhist", "migrate"))) {
720 
721  return array("success"=> False,
722  "message" => "Final migration (members data) cannot be executed."
723  . $developer_help_msg);
724  } else { // compose a execute final migration
725  // add memdata migration script
726  $executing_categories = "memdata";
727  $cmd_memdata = $python_exec . " " . $root_script_dir . "/ody_migr_executor.py "
728  . escapeshellarg($server) . " "
729  . escapeshellarg("migrate") . " "
730  . escapeshellarg(strtoupper($cu)) . " "
731  . escapeshellarg("memdata") . " "
732  . escapeshellarg($username) . " "
733  . escapeshellarg($password) . " "
734  . " > /dev/null";
735 
736  // add switchaccounts if configured
737  if (file_exists(getSwitchAccountsSettingFile($cu))) {
738  $cmd_switchaccounts = $python_exec . " " . $root_script_dir . "/ody_migr_executor.py "
739  . escapeshellarg($server) . " "
740  . escapeshellarg("migrate") . " "
741  . escapeshellarg(strtoupper($cu)) . " "
742  . escapeshellarg("switchaccounts") . " "
743  . escapeshellarg($username) . " "
744  . escapeshellarg($password) . " "
745  . " > /dev/null";
746 
747  $cmd_memdata = $cmd_memdata . " && " . $cmd_switchaccounts;
748  $executing_categories .= ", switchaccounts";
749  }
750 
751  // add loanapp; credit unions with no associated loan apps will complete
752  // safely (i.e. migrate no data)
753  $cmd_loanapp = $python_exec . " " . $root_script_dir . "/ody_migr_executor.py "
754  . escapeshellarg($server) . " "
755  . escapeshellarg("migrate") . " "
756  . escapeshellarg(strtoupper($cu)) . " "
757  . escapeshellarg("loanapp") . " "
758  . escapeshellarg($username) . " "
759  . escapeshellarg($password) . " "
760  . " > /dev/null";
761 
762  $cmd_memdata = $cmd_memdata . " && " . $cmd_loanapp;
763  $executing_categories .= ", loanapp";
764 
765  $cmd_memhist = $python_exec . " " . $root_script_dir . "/ody_migr_executor.py "
766  . escapeshellarg($server) . " "
767  . escapeshellarg("migrate") . " "
768  . escapeshellarg(strtoupper($cu)) . " "
769  . escapeshellarg("memhist") . " "
770  . escapeshellarg($username) . " "
771  . escapeshellarg($password) . " "
772  . " > /dev/null";
773 
774  $cmd = "(" . $cmd_memdata . " && " . $cmd_memhist . ") > /dev/null 2>&1 &";
775  $executing_categories .= ", memhist";
776 
777  // create an initial wip file for memdata, and execute the command
778  if (touch(getWIPFile($cu, "memdata", "migrate")) && touch($final_migr_lck)) {
779  // log final migration execution
780  auditLogMigrationExecution($cu, $username, "migrate", "Final", "Started.");
781  // execute migration script
782  exec($cmd, $script_output, $return_status);
783  } else {
784  // cleanup after itself
785  if(file_exists($final_migr_lck)) {
786  unlink($final_migr_lck);
787  }
788  if(file_exists(getWIPFile($cu, "memdata", "migrate"))) {
789  unlink(getWIPFile($cu, "memdata", "migrate"));
790  }
791  return array("success"=> True,
792  "message" => " Failed creating initial WIP lock file (memdata) for Final migration. "
793  . $developer_help_msg);
794  }
795 
796  if ($return_status > 0) {
797  // cleanup after itself
798  if(file_exists($final_migr_lck)) {
799  unlink($final_migr_lck);
800  }
801  if(file_exists(getWIPFile($cu, "memdata", "migrate"))) {
802  unlink(getWIPFile($cu, "memdata", "migrate"));
803  }
804  return array("success"=> False,
805  "message" => "Final migration (" + $executing_categories + ") execution returned non-zero exit code. ("
806  . $root_script_dir . ") " . " ".join($script_output) . "."
807  . $developer_help_msg);
808  } else {
809  return array("success"=> True,
810  "message" => " Final migration ('migrate-{" . $executing_categories . "}'') STARTED successfully. ("
811  . $root_script_dir . ") ");
812  }
813  }
814 
815 }
816 
817 /**
818  * Delete multiple categories
819  *
820  * @param $cu -- credit union CU code
821  * @param $cat_del_list -- list of categories to delete
822  * @param $is_forced_cleanup -- do not check for validation if true for final migration
823  *
824  * @return success or failure response
825  */
826 function deleteMultipleCategories($cu, $cat_del_list, $is_forced_cleanup=False) {
827 
828  if (count($cat_del_list) == 0 && $is_forced_cleanup == False) {
829  return array("success"=> True, "message" => "No categories selected for deletion.");
830  } else {
831  $all_success = True;
832  $success_categories = array();
833  $failed_categories = array();
834  // log multiple categories deletion execution
835  auditLogMigrationExecution($cu, "", "attempted-multiple-clean", implode(":", $cat_del_list));
836  foreach($cat_del_list as $category) {
837 
838  if ($is_forced_cleanup == True) {
839  // do not check for validation if the call is for reset final migration
840  $validationResponseStatus = True;
841  } else {
842  // validate options before execution
843  $validationResponse = validateOptionsBeforeScriptExecution($cu, "clean", $category);
844  $validationResponseStatus = $validationResponse["success"];
845  }
846 
847  if ($validationResponseStatus == True) {
848  // server=www4 is just to meet the argument validation, Mammoth server identification is not required for deletion
849  // do not execute migration script in background
850  $response_category = executeMigrationScript("www4", "clean", $cu, $category, "", "", $bg=False);
851 
852  if ($response_category["success"]) {
853  // delete completion lock file and log files if $operation == "clean"
854  // ONLY after SUCCESSFUL completion of clean operation
855  cleanupAfterClean($cu, $category, "clean");
856 
857  $success_categories[] = $category;
858  } else {
859  $failed_categories[] = $category;
860  }
861  } else {
862  $response_category = $validationResponse;
863  $failed_categories[] = $category;
864  }
865 
866  $all_success = $response_category["success"] && $all_success;
867  $response_category["category"] = $category;
868  }
869  // log categories that were deleted successfully
870  auditLogMigrationExecution($cu, "", "successful-multiple-clean", implode(":", $success_categories));
871  if($is_forced_cleanup == False) {
872  if ($all_success) {
873  return array("success"=> True, "message" => "Successfully cleaned up all SELECTED (and UNLOCKED) categories. [ " . implode(", ", $success_categories) . " ] were cleaned. ");
874  } else {
875  return array("success"=> False, "message" => "Cleaned categories: [ " . implode(", ", $success_categories) . " ]. Categories not cleaned (probably set LOCKED): [ " .implode(",", $failed_categories) . " ]. ");
876  }
877  }
878  }
879 }
880 
881 /**
882  * Get a list of completed categories
883  *
884  * @param $cu -- credit union CU code
885  *
886  * @return array list of completed categories
887  */
888 function getCurrentDoneCategoryList($cu) {
889  $done_list = array();
890  foreach (glob(GetTmpDir($cu) . "/.ody_migr_migrate_*.done") as $filename) {
891  $filename_pieces = explode("_", $filename);
892  $category_frm_filename = explode(".", $filename_pieces[count($filename_pieces) - 1])[0];
893  $done_list[] = $category_frm_filename;
894  }
895  return $done_list;
896 }
897 
898 /**
899  * Get a list of WIP categories
900  *
901  * @param $cu -- credit union CU code
902  *
903  * @return array list of WIP categories
904  */
905 function getCurrentWIPCategoryList($cu, $migrate_only=False) {
906  $wip_list = array();
907  $glob_collection = array();
908  if ($migrate_only) {
909  $glob_collection = glob(GetTmpDir($cu) . "/.ody_migr_migrate*.wip");
910  } else {
911  $glob_collection = glob(GetTmpDir($cu) . "/.ody_migr_*.wip");
912  }
913  foreach ($glob_collection as $filename) {
914  $filename_only = explode(".", $filename)[1];
915  $cat_operation_str = explode("ody_migr_", $filename_only)[1];
916  $wip_list[] = str_replace("_", "-", $cat_operation_str);
917  }
918  return $wip_list;
919 }
920 
921 /**
922  * Get a list of currently available log files
923  *
924  * @param $cu -- credit union CU code
925  *
926  * @return array list of currently available log files
927  */
928 function getCurrentLogsList($cu) {
929  $logs_list= array();
930 
931  foreach (glob(GetLogsDir($cu) . "/ody_migr_*.log") as $log_file) {
932  $filename_only = explode(".", $log_file)[0];
933  $cat_operation_str = explode("ody_migr_", $filename_only)[1];
934 
935  list($op, $cat) = explode("_", $cat_operation_str);
936 
937  // list only completed logs for migrate operation; not clean and summary
938  // 2019/09/11: including "clean" logs has a bug that removes
939  // migrate-{category} logs when "Fetch Log" is clicked from the monitor
940  if ($op == "migrate") {
941  if (file_exists(getDoneFile($cu, $cat, $op))) {
942  $logs_list[] = str_replace("_", "-", $cat_operation_str);
943  }
944  }
945  }
946  return $logs_list;
947 }
948 
949 
950 /**
951  * Execute fix_public_html.pl script
952  *
953  * @param $cu -- credit union CU code
954  * @param $from -- from domain
955  * @param $to -- to domain
956  *
957  * @return success or failure response
958  */
959 function executeFixPublicHtmlScript($cu, $from, $to) {
960  $perl_exec = "/usr/bin/env perl";
961  $root_script_dir = "/opt/odyssey/tools/bin";
962  if (getenv("DEVMODE") == "1") {
963  $root_script_dir = "/project/app/tools/bin";
964  }
965 
966  $cmd = $perl_exec . " " . $root_script_dir . "/fix_public_html.pl " . escapeshellarg($cu) . " " . escapeshellarg($from) . " " . escapeshellarg($to) . " " . " > /dev/null";
967 
968  exec($cmd, $script_output, $return_status);
969 
970  if ($return_status > 0) {
971  return array("success"=> False, "message" => "(" . $root_script_dir .") " . " ".join($script_output));
972  } else {
973  return array("success"=> True, "message" => "public_html embedded links updated successfully. (" . $root_script_dir .") " . " ".join($script_output));
974  }
975 }
976 
977 /**
978  * function GetCuList($dbh)
979  * Gets a list of open Credit Unions, which server they are on, and if they are live, batch, or web only.
980  *
981  * @param $dbh -- the database connection
982  *
983  * @return $error -- the error message if there is an error
984  * @return $cuinfo -- a list of open CUs.
985  */
986 function GetCuList($dbh) {
987  try {
988  global $SYS_TYPE_CLOSED, $SYS_TYPE_LIVE, $SYS_TYPE_BATCH, $SYS_TYPE_WEBONLY;
989  $sql = "select user_name, www_server, case when (coalesce(system_options, 0)" .
990  " & $SYS_TYPE_LIVE) <> 0 then 'Live'" .
991  " when (coalesce(system_options, 0) & $SYS_TYPE_BATCH) <> 0 then 'Batch'" .
992  " when (coalesce(system_options, 0) & $SYS_TYPE_WEBONLY) <> 0 then 'Web Only'" .
993  " else 'Other' end as cutype from cuinfo" .
994  " where (coalesce(system_options, 0) & $SYS_TYPE_CLOSED) = 0" .
995  " order by user_name";
996 
997  $sth = db_query($sql, $dbh);
998  if (!$sth) {
999  throw new exception ("Select query failed.", 2);
1000  }
1001 
1002  $results = db_fetch_all($sth);
1003  $results = $results === false ? array() : $results;
1004 
1005  $returnArray = array("error" => "", "cuinfo" => $results);
1006  } catch (exception $e) {
1007  $returnArray = array("error" => $e->getMessage());
1008  }
1009  return $returnArray;
1010 }
1011 /**
1012  * Main function to respond to ajax post request made from Monitor UI client (ody_migr_client.prg)
1013  *
1014  * Each post request MUST contain 'post_purpose' parameter, based on which, this function serves the resource. Each option might have differntly
1015  * prepared response object which is handled accordingly on the client side. Here are the options for post_purpose or get_puspose:
1016  *
1017  * post_purpose:
1018  * [POST] execute_script: Runs python migration script in background
1019  * [POST] execute_final_migration: migrate both memdata and memhist
1020  * [POST] start_memhist_sa_wip_for_final_migration: execute memhist as a part of final migration
1021  * [POST] reset_migration_state: remove final migration related lock files and cleanup memdata and memhist
1022  * [POST] manage_migration_state: handle on-page-load and on-completion migration states
1023  * [POST] handle_switchaccounts_setting: create/delete lock file to persist switchaccounts setting
1024  * [POST] fetch_log: This option parses log file for given data category and returns response with log content and information to update progress bar.
1025  * [POST] disable_monitor: This creates the monitor lock file in intented location to disable monitor UI.
1026  * [POST] check_monitor_lock: This checks if the monitor lock file exist or not and returns the boolean flag as a part of response.
1027  * [POST] delete_wip: This deletes work in progress lock file for a particular data category.
1028  * [POST] get_wip_done_list: This collects and returns list of files .wip and .done extensions for a particular credit union and data category.
1029  * [POST] get_logs_list: This collects and returns list of log files for current credit union.
1030  * [POST] clean_all_categories: cleanup multiple selected categories
1031  * [POST] update_servers_list: This returns a list of updated servers list.
1032  * [POST] update_categories_list: This returns a list of updated categories list
1033  * [POST] display_accref_download: This checks if the account reference mappings file exist
1034  * [POST] fix_public_html: This executes fix_public_html.pl script to update embedded links in public_html in Odyssey
1035  * [POST] display_hb_info_text: This returns CU settings status (Home Banking, offline status, etc.) information
1036  * [POST] display_lock_unlock_preventive_buttons: This checks existence of 'done' lock files for settings and member data categories.
1037  * [POST] lock_unlock_cat_group: toggle preventive button settings using creating and deleting lock files
1038  * [POST] get_final_migration_flag: return flags to specify if the current migration state is ready to run as final migration
1039 
1040  *
1041  * get_purpose:
1042  * GET] acc_cross_ref: This return the account cross reference csv file content
1043  *
1044  * @return $response -- final response w.r.t the 'post_purpose' parameter in the http post request
1045  */
1046 function serveMigrationPurpose() {
1047  global $link;
1048  try {
1049 
1050  if ( isset($_GET["get_purpose"]) ) {
1051 
1052  if ($_GET["get_purpose"] == "acc_cross_ref") {
1053  // WIP files are only created for migrate operation
1054  if ( isset($_GET["cu"]) ) {
1055  $cu = $_GET["cu"];
1056  } else {
1057  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1058  }
1059 
1060  $accountCrossRefFile = getAccCrossRefFile($cu);
1061 
1062  if (!file_exists($accountCrossRefFile)) {
1063  $response = array("success"=> False, "message" => "'$accountCrossRefFile' file does not exist.");
1064  } else {
1065  // send header information to the browser
1066  header("Content-type: text/plain");
1067  header("Content-disposition: inline; filename=$accountCrossRefFile");
1068 
1069  // read the file and send to standard output
1070  @readfile($accountCrossRefFile);
1071  exit;
1072  }
1073  }
1074 
1075  } elseif ( isset($_POST["post_purpose"]) ) {
1076 
1077  // **********************************************************************************************
1078  // Execute Python script in background and return status
1079  // **********************************************************************************************
1080 
1081  if ($_POST["post_purpose"] == "execute_script") {
1082 
1083  if ( isset($_POST["server"]) ) {
1084  $server = $_POST["server"];
1085  } else {
1086  throw new exception("'server' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1087  }
1088 
1089  if ( isset($_POST["cu"]) ) {
1090  $cu = $_POST["cu"];
1091  } else {
1092  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1093  }
1094 
1095  if ( isset($_POST["operation"]) ) {
1096  $operation = $_POST["operation"];
1097  } else {
1098  throw new exception("'operation' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 6);
1099  }
1100 
1101  if ( isset($_POST["category"]) ) {
1102  $category = $_POST["category"];
1103  } else {
1104  throw new exception("'category' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 21);
1105  }
1106 
1107  if ( isset($_POST["username"]) ) {
1108  $username = $_POST["username"];
1109  } else {
1110  throw new exception("'username' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 3);
1111  }
1112 
1113  if ( isset($_POST["password"]) ) {
1114  $password = $_POST["password"];
1115  } else {
1116  throw new exception("'password' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 4);
1117  }
1118 
1119  // operation validation before execution
1120  // if final migration lock file exists, return without execution
1121  if (file_exists(getFinalMigrationDoneLock($cu))) {
1122  return array("success"=> False,
1123  "message" => "<b>Operation NOT ALLOWED. Final migration ('migrate-{memdata,memhist}') already COMPLETED. </b>");
1124  }
1125 
1126  // if final migration lock file exists, return without execution
1127  if (file_exists(getFinalMigrationMainLock($cu))) {
1128  return array("success"=> False,
1129  "message" => "<b>Operation NOT ALLOWED. Final migration step ('migrate-{memdata,memhist}') is IN PROGRESS. </b>");
1130  }
1131 
1132  $validationResponse = validateOptionsBeforeScriptExecution($cu, $operation, $category);
1133  if (!$validationResponse["success"]) {
1134  return $validationResponse;
1135  }
1136 
1137  $migration_started_lock = getWIPFile($cu, $category, $operation);
1138  $migration_done_lock = getDoneFile($cu, $category, $operation);
1139 
1140  if (file_exists($migration_started_lock)) {
1141  $response = array("success"=> False,
1142  "message" => "[WIP] Migration process is already IN PROGRESS for '$operation-$category'.");
1143  } elseif (file_exists($migration_done_lock)) {
1144  $response = array("success"=> False,
1145  "message" => "[Done] Migration already COMPLETED for '$operation-$category'.");
1146  }else {
1147  if (touch($migration_started_lock)) {
1148  $response = executeMigrationScript($server, $operation, $cu,
1149  $category, $username, $password);
1150  } else {
1151  $response = array("success"=> False,
1152  "message" => "Failed to create WIP lock file.");
1153  }
1154  }
1155  }
1156 
1157  // **********************************************************************************************
1158  // Execute final members migration script
1159  // **********************************************************************************************
1160  elseif ($_POST["post_purpose"] == "execute_final_migration") {
1161 
1162  if ( isset($_POST["server"]) ) {
1163  $server = $_POST["server"];
1164  } else {
1165  throw new exception("'server' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1166  }
1167 
1168  if ( isset($_POST["cu"]) ) {
1169  $cu = $_POST["cu"];
1170  } else {
1171  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1172  }
1173 
1174  if ( isset($_POST["username"]) ) {
1175  $username = $_POST["username"];
1176  } else {
1177  throw new exception("'username' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 3);
1178  }
1179 
1180  if ( isset($_POST["password"]) ) {
1181  $password = $_POST["password"];
1182  } else {
1183  throw new exception("'password' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 4);
1184  }
1185 
1186  $response = executeFinalMigration($server, $cu, $username, $password);
1187  }
1188 
1189  // **********************************************************************************************
1190  // Create WIP file for memhist as a part of final migration
1191  // **********************************************************************************************
1192 
1193  elseif ($_POST["post_purpose"] == "start_memhist_sa_wip_for_final_migration") {
1194  if ( isset($_POST["cu"]) ) {
1195  $cu = $_POST["cu"];
1196  } else {
1197  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1198  }
1199 
1200  if ( isset($_POST["category"]) ) {
1201  $category = $_POST["category"];
1202  } else {
1203  throw new exception("'category' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1204  }
1205 
1206  $memhist_sa_wip = getWIPFile($cu, $category, "migrate");
1207  if (touch($memhist_sa_wip)) {
1208  $response = array("success"=> True, "message" => "[Final Migration] WIP file created for " . $category . " category.");
1209  } else {
1210  $response = array("success"=> False, "message" => "[Final Migration] WIP file could not be created for " . $category . " category.");
1211  }
1212  }
1213 
1214  // **********************************************************************************************
1215  // reset migration state
1216  // **********************************************************************************************
1217 
1218  elseif ($_POST["post_purpose"] == "reset_migration_state") {
1219  if ( isset($_POST["cu"]) ) {
1220  $cu = $_POST["cu"];
1221  } else {
1222  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1223  }
1224  // audit log Reset Migration State click
1225  auditLogMigrationExecution($cu, "", "Reset (Final) Migration State", "memdata:memhist", "Button clicked");
1226  $resp = "";
1227  $final_migr_lck = getFinalMigrationMainLock($cu);
1228  $final_migr_lck_done = getFinalMigrationDoneLock($cu);
1229 
1230  if (file_exists($final_migr_lck)) {
1231  unlink($final_migr_lck);
1232  }
1233 
1234  if (file_exists($final_migr_lck_done)) {
1235  unlink($final_migr_lck_done);
1236  }
1237 
1238  $categories_toclean = array("memdata", "memhist");
1239  deleteMultipleCategories($cu, $categories_toclean, $is_forced_cleanup=True);
1240  $categories_toclean[] = "switchaccounts";
1241 
1242  // make sure there are no dangling lock files
1243  foreach ($categories_toclean as $category) {
1244  foreach(array("migrate", "summary") as $op) {
1245  $lg_file = getLogFile($cu, $op, $category);
1246  if(file_exists($lg_file)) {
1247  unlink($lg_file);
1248  }
1249  }
1250  $wip_file = getWIPFile($cu, $category, $op);
1251  if(file_exists($wip_file)) {
1252  unlink($wip_file);
1253  }
1254  $done_file = getDoneFile($cu, $category, $op);
1255  if(file_exists($done_file)) {
1256  unlink($done_file);
1257  }
1258  }
1259 
1260  $response = array("success" => True, "message" => "Migration state (members data and history) has been reset and cleaned. You may proceed with the members migration normally now. ");
1261 
1262  }
1263 
1264  // **********************************************************************************************
1265  // Complete Final Migration
1266  // **********************************************************************************************
1267 
1268  elseif ($_POST["post_purpose"] == "manage_migration_state") {
1269  if ( isset($_POST["cu"]) ) {
1270  $cu = $_POST["cu"];
1271  } else {
1272  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1273  }
1274 
1275  if ( isset($_POST["final_migration_when"]) ) {
1276  $final_migration_when = $_POST["final_migration_when"];
1277  } else {
1278  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1279  }
1280 
1281  $final_lck_file = getFinalMigrationMainLock($cu);
1282  $final_lck_file_complete = getFinalMigrationDoneLock($cu);
1283 
1284  if ($final_migration_when == "on_completion") {
1285  $final_migr_completion_msg = "";
1286  if (file_exists($final_lck_file)) {
1287  if (touch($final_lck_file_complete)) {
1288  $final_migr_completion_msg = "[Final Migration] All Migrations COMPLETED. Altering settings and over-writing migrations is not advised. ";
1289  $response = array("success"=> True,
1290  "message" => $final_migr_completion_msg);
1291  } else {
1292  $final_migr_completion_msg = "[Error] Final Migration could not be completed (migration completed but error creating completed lock file.) ";
1293  $response = array("success"=> False,
1294  "message" => $final_migr_completion_msg);
1295  }
1296  }
1297  else {
1298  $final_migr_completion_msg = "[Error] Final Migration seem to be completed, but required internal migration state violated (not started, but trying to complete? Please consult issue with a developer.) ";
1299  $response = array("success"=> False,
1300  "message" => $final_migr_completion_msg);
1301  }
1302  // log final migration completion
1303  auditLogMigrationExecution($cu, "", "migrate", "final", $final_migr_completion_msg);
1304  }
1305  // on_pageload
1306  else {
1307  if (file_exists($final_lck_file_complete) && file_exists($final_lck_file)) {
1308  $response = array("success"=> True,
1309  "message" => "[Final Migration] All Migrations COMPLETED. Altering settings and over-writing migrations is not advised. ",
1310  "migr_status" => "completed",
1311  "migr_type" => "final");
1312  } else {
1313  if (file_exists($final_lck_file)) {
1314  $migr_type = "final";
1315  $msg_prefix = "[Final Migration] ";
1316  } else {
1317  $migr_type = "regular";
1318  $msg_prefix = "[Regular Migration] ";
1319  }
1320 
1321  $wips = getCurrentWIPCategoryList($cu);
1322 
1323  if (count($wips) > 1) {
1324  $response = array("success"=> False,
1325  "message" => "[Invalid] Unexpected multiple in-progress migrations found. Please reset migration states from Settings and re-run migration. ",
1326  "migr_status" => "invalid");
1327  } elseif (count($wips) == 1){
1328  $category = $wips[0];
1329  $response = array("success"=> True,
1330  "message" => "Migration in progress: " . $category,
1331  "migr_status" => "inprogress",
1332  "inprogress_category" => $category);
1333  } else {
1334  if($migr_type == "final") {
1335  $response = array("success"=> False,
1336  "message" => "No in-progress migration operation found. Please consult issue with a developer. ",
1337  "migr_status" => "invalid");
1338  } else {
1339  $response = array("success"=> True,
1340  "message" => "Normal start up. Good to proceed with the migration steps. ",
1341  "migr_status" => "normalstart");
1342  }
1343  }
1344  $response["migr_type"] = $migr_type;
1345  $response["message"] = $msg_prefix . $response["message"];
1346 
1347  }
1348  }
1349  }
1350 
1351  // **********************************************************************************************
1352  // Create WIP file for memhist as a part of final migration
1353  // **********************************************************************************************
1354 
1355  elseif ($_POST["post_purpose"] == "handle_switchaccounts_setting") {
1356  if ( isset($_POST["cu"]) ) {
1357  $cu = $_POST["cu"];
1358  } else {
1359  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1360  }
1361 
1362  if ( isset($_POST["action"]) ) {
1363  $action = $_POST["action"];
1364  } else {
1365  throw new exception("'action' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1366  }
1367 
1368  if ( isset($_POST["entity"]) ) {
1369  $entity = $_POST["entity"];
1370  } else {
1371  throw new exception("'entity' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1372  }
1373 
1374 
1375  if ($entity == "switchaccounts") {
1376  $config_file= getSwitchAccountsSettingFile($cu);
1377  }
1378 
1379  if ($action == "get_setting") {
1380  $response = array("success"=> True, "include_or_not" => (file_exists($config_file)));
1381  }
1382  // toggle_setting
1383  else {
1384  if(file_exists($config_file)) {
1385  $response = array("success"=> (unlink($config_file)));
1386  } else {
1387  $response = array("success"=> (touch($config_file)));
1388  }
1389  }
1390  }
1391 
1392  // **********************************************************************************************
1393  // Fetch log file/content for specific migration
1394  // **********************************************************************************************
1395 
1396  elseif ($_POST["post_purpose"] == "fetch_log") {
1397 
1398  if ( isset($_POST["cu"]) ) {
1399  $cu = $_POST["cu"];
1400  } else {
1401  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1402  }
1403 
1404  if ( isset($_POST["operation"]) ) {
1405  $operation = $_POST["operation"];
1406  } else {
1407  throw new exception("'operation' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 6);
1408  }
1409 
1410  if ( isset($_POST["category"]) ) {
1411  $category = $_POST["category"];
1412  } else {
1413  throw new exception("'category' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 21);
1414  }
1415 
1416  $log_path = getLogFile($cu, $operation, $category);
1417  $result = readContent($log_path, $operation, $category, $cu);
1418 
1419  // audit log any error while fetching log file
1420  $lastline =end($result["log_content"]);
1421  if (strpos($lastline, "Error") !== false) {
1422  auditLogMigrationExecution($cu, "", $operation, $category, "Log Fetch Error: " . trim(preg_split("/::/", $lastline)[1]));
1423  }
1424 
1425  $success_msg_prefix = "";
1426  if ($result["does_not_exist"]) {
1427  $msg = "Log file does not exist: " . $log_path . ". ";
1428  }
1429  elseif ($result["end_of_log"]) {
1430  if ($operation != "migrate") {
1431  // delete completion lock file and log files if $operation == "clean"
1432  // ONLY after SUCCESSFUL completion of clean operation
1433  if($operation == "clean") {
1434  cleanupAfterClean($cu, $category, $operation);
1435  }
1436  $msg = "<b>Operation ('$operation - $category') COMPLETED.</b> Displayed log is COMPLETE. ";
1437 
1438  } else { // migrate
1439  $success_msg_prefix = "<b>Migration ('$operation - $category') COMPLETED.</b> Displayed log is COMPLETE. ";
1440  }
1441 
1442  if ($operation == "migrate") {
1443  $handle_wip_response = markWIPAsComplete($cu, $category, $operation);
1444  } else {
1445  $handle_wip_response = deleteWIPFile($cu, $category, $operation);
1446  }
1447 
1448  if ($handle_wip_response["success"] == False) {
1449  $msg = $success_msg_prefix . " WIP file COULD NOT be marked as Done or Deleted. ";
1450  } else {
1451  $msg = $success_msg_prefix;
1452  }
1453 
1454  } else {
1455  if ($operation == "migrate") {
1456  $msg = "<b>Migration ('$operation - $category') is IN PROGRESS.</b> Displayed log is NOT COMPLETE. ";
1457  } else {
1458  $msg = "<b>Operation ('$operation - $category') is IN PROGRESS.</b> Displayed log is NOT COMPLETE. ";
1459  }
1460  }
1461 
1462  $response = array("success"=> True, "message" => $msg, "category"=>$category, "log_report" => $result);
1463  }
1464 
1465  // **********************************************************************************************
1466  // Fetch log content only for displaying history (no side effects; only display)
1467  // **********************************************************************************************
1468  elseif ($_POST["post_purpose"] == "fetch_log_history_only") {
1469 
1470  if ( isset($_POST["cu"]) ) {
1471  $cu = $_POST["cu"];
1472  } else {
1473  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1474  }
1475 
1476  if ( isset($_POST["operation"]) ) {
1477  $operation = $_POST["operation"];
1478  } else {
1479  throw new exception("'operation' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 6);
1480  }
1481 
1482  if ( isset($_POST["category"]) ) {
1483  $category = $_POST["category"];
1484  } else {
1485  throw new exception("'category' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 21);
1486  }
1487 
1488  $log_path = getLogFile($cu, $operation, $category);
1489  $response = readContent($log_path, $operation, $category, $cu);
1490 
1491  if ($response["does_not_exist"]) {
1492  $response["success"] = False;
1493  $response["message"] = "[Log History] Log file does not exist for '$operation-$category'";
1494  } else {
1495  $response["success"] = True;
1496  $response["message"] = "[Log History] Displaying logs: '$operation-$category'";
1497  }
1498  }
1499 
1500  // **********************************************************************************************
1501  // Disable Monitor access by creating lock file
1502  // **********************************************************************************************
1503 
1504  elseif ($_POST["post_purpose"] == "disable_monitor") {
1505 
1506  if ( isset($_POST["cu"]) ) {
1507  $cu = $_POST["cu"];
1508  if ($cu == "") {
1509  throw new exception("Empty 'cucode' name provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1510  }
1511  } else {
1512  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1513  }
1514 
1515  if ( isset($_POST["server"]) ) {
1516  $server = $_POST["server"];
1517  if ($server == "") {
1518  throw new exception("Empty 'server' name provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1519  }
1520  } else {
1521  throw new exception("'server' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1522  }
1523 
1524  // maintain audit log
1525  auditLogMigrationExecution($cu, "", "Disable Migration Menu.", "Temporary files cleanup.", "Button clicked.");
1526 
1527  $monitor_lock_file = getMonitorLockFile($cu);
1528 
1529  if (file_exists($monitor_lock_file)) {
1530  $response = array("success"=> True, "message" => "Monitor UI already disabled.");
1531  } else {
1532  // create a lock file
1533  if (touch($monitor_lock_file)) {
1534  // Now, run cleanup of temporary files in Mammoth
1535  // Note, success/failure of temporary file cleanup is not that critical
1536  // As of 2018-10-05, the only temporary file that we want to cleanup is
1537  // /home/*/tmp/memhist.gz file in Mammoth servers. In case this step produces
1538  // an error in log message, simply go to the Mammoth location of this $cu
1539  // and carefully delete the file.
1540 
1541  $cleanup_hash = CreateHash("cleanup", $cu);
1542  $cleanup_response = makeMammothEndpointCall($server, $cu, "cleanup", $cleanup_hash);
1543 
1544  $temp_file_deletion_msg_append = "";
1545 
1546  if ($cleanup_response["error"] == "") {
1547  # temporary files are deleted successfully
1548  $temp_file_deletion_msg_append = "[Cleanup MMTH] " . $cleanup_response["info"] . ".";
1549  } else {
1550  $temp_file_deletion_msg_append = "[Cleanup MMTH] " . $cleanup_response["error"] . ".";
1551  }
1552 
1553  // Also, delete temporary 'memhist' files from odyssey.
1554  $ody_cleanup_msg = deleteOdysseyTemporaryFiles($cu);
1555 
1556  $response = array("success"=> True, "message" => "[Monitor Disable] Migration Monitor UI disabled. $temp_file_deletion_msg_append $ody_cleanup_msg");
1557 
1558  } else {
1559  $response = array("success"=> False, "message" => "[Monitor Disable] Something went wrong, could not disable Monitor UI. $temp_file_deletion_msg_append");
1560  }
1561  }
1562 
1563  }
1564 
1565  // **********************************************************************************************
1566  // Check if monitor lock file exists
1567  // **********************************************************************************************
1568 
1569  elseif ($_POST["post_purpose"] == "check_monitor_lock") {
1570 
1571  if ( isset($_POST["cu"]) ) {
1572  $cu = $_POST["cu"];
1573  } else {
1574  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1575  }
1576 
1577  $monitor_lock_file = getMonitorLockFile($cu);
1578 
1579  if (file_exists($monitor_lock_file)) {
1580  $response = array("exists"=> True, "lock_file" => $monitor_lock_file);
1581  } else {
1582  $response = array("exists"=> False, "lock_file" => $monitor_lock_file);
1583  }
1584  }
1585 
1586  // **********************************************************************************************
1587  // Delete WIP lock file for specific category after completion or error
1588  // **********************************************************************************************
1589 
1590  elseif ($_POST["post_purpose"] == "delete_wip") {
1591  // WIP files are only created for migrate operation
1592 
1593  if ( isset($_POST["cu"]) ) {
1594  $cu = $_POST["cu"];
1595  } else {
1596  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1597  }
1598 
1599  if ( isset($_POST["category"]) ) {
1600  $category = $_POST["category"];
1601  } else {
1602  throw new exception("'category' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 21);
1603  }
1604 
1605  if ( isset($_POST["operation"]) ) {
1606  $operation = $_POST["operation"];
1607  } else {
1608  throw new exception("'operation' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 21);
1609  }
1610 
1611  if ( isset($_POST["is_final_migr"]) ) {
1612  $is_final_migr = $_POST["is_final_migr"];
1613  } else {
1614  throw new exception("'operation' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 21);
1615  }
1616 
1617  $response = deleteWIPFile($cu, $category, $operation);
1618 
1619  if($is_final_migr) {
1620  $final_migr_main_lock = getFinalMigrationMainLock($cu);
1621  if (file_exists($final_migr_main_lock)) {
1622  $final_migr_unlink_response = unlink($final_migr_main_lock);
1623  if($final_migr_unlink_response) {
1624  $response["message"] .= " Successfully removed final migration lock file. ";
1625  } else {
1626  $response["message"] .= " Removing final migration lock file FAILED. ";
1627  }
1628  $response["success"] = ($response["success"] && $final_migr_unlink_response);
1629  }
1630  }
1631 
1632  }
1633 
1634  // **********************************************************************************************
1635  // Return list of in-progress and done categories
1636  // **********************************************************************************************
1637 
1638  elseif ($_POST["post_purpose"] == "get_wip_done_list") {
1639  // WIP files are only created for migrate operation
1640 
1641  if ( isset($_POST["cu"]) ) {
1642  $cu = $_POST["cu"];
1643  } else {
1644  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1645  }
1646 
1647  $wip_list = getCurrentWIPCategoryList($cu);
1648  $done_list = getCurrentDoneCategoryList($cu);
1649  $final_migr_done = file_exists(getFinalMigrationDoneLock($cu));
1650 
1651  $response = array("success"=> True,
1652  "message" => "Successfully fetched list of wip and done migrations.",
1653  "wip_list" => $wip_list,
1654  "done_list"=>$done_list,
1655  "final_migr_done" => $final_migr_done);
1656  }
1657 
1658  // **********************************************************************************************
1659  // Return logs list
1660  // **********************************************************************************************
1661 
1662  elseif ($_POST["post_purpose"] == "get_logs_list") {
1663 
1664  if ( isset($_POST["cu"]) ) {
1665  $cu = $_POST["cu"];
1666  } else {
1667  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1668  }
1669 
1670  $logs_list = getCurrentLogsList($cu);
1671 
1672  $response = array("success"=> True, "message" => "Successfully fetched all existing log files.", "logs_list" => $logs_list);
1673  }
1674 
1675  // **********************************************************************************************
1676  // Cleanup All Categories
1677  // **********************************************************************************************
1678 
1679  elseif ($_POST["post_purpose"] == "clean_all_categories") {
1680 
1681  if ( isset($_POST["cu"]) ) {
1682  $cu = $_POST["cu"];
1683  } else {
1684  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1685  }
1686 
1687  if (file_exists(getFinalMigrationMainLock($cu)) || file_exists(getFinalMigrationDoneLock($cu))) {
1688  $response = array("success"=> False, "message" => "Deletion NOT ALLOWED. Final migration already executed or is in progress. ");
1689  } else {
1690 
1691  $delete_done_list = array();
1692  if ( isset($_POST["delete_done_list"]) ) {
1693  $delete_done_list = $_POST["delete_done_list"];
1694  } else {
1695  throw new exception("'delete_done_list' not provided (must be a list of categories to run clean operation.). (" . __FILE__ . ":" . __LINE__ . ")", 1);
1696  }
1697  $response = deleteMultipleCategories($cu, $delete_done_list);
1698  }
1699  }
1700 
1701  // **********************************************************************************************
1702  // Update DDL's Categories list for specific CU
1703  // **********************************************************************************************
1704  //
1705  elseif ($_POST["post_purpose"] == "update_server_list") {
1706  $dbh = $link;
1707  if ( isset($_POST["cu"]) ) {
1708  $cu = $_POST["cu"];
1709  } else {
1710  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1711  }
1712 
1713  $associated_servers = array();
1714  $cu_info_arr = array();
1715 
1716  if (in_array(strtoupper($cu), array("SCRUBCU", "CRUISECU"))) {
1717  // return www4 for CUs used for development
1718  $associated_servers[] = "www4";
1719  } else {
1720 
1721  $cu_info_response = GetCuList($dbh);
1722  if (HCU_array_key_exists("cuinfo", $cu_info_response)) {
1723  $cu_info_arr = $cu_info_response["cuinfo"];
1724  foreach($cu_info_arr as $cuinfo) {
1725  if (in_array(trim($cuinfo["cutype"]), array("Live")) && strtoupper(trim($cuinfo["user_name"])) == strtoupper($cu)) {
1726  $associated_servers[] = trim($cuinfo["www_server"]);
1727  }
1728  }
1729  }
1730  }
1731 
1732  if(count($associated_servers) > 0) {
1733  $response = array("success"=> True, "message" => "Successfully obtained server list for CU '$cu'.", "server_list" => $associated_servers);
1734  } else {
1735  $response = array("success"=> False, "message" => "CU '$cu' does not exist in any of the Mammoth Servers.");
1736  }
1737  }
1738 
1739  // **********************************************************************************************
1740  // Update DDL's Server list for specific CU
1741  // **********************************************************************************************
1742  //
1743  elseif ($_POST["post_purpose"] == "update_categories_list") {
1744 
1745  if ( isset($_POST["cu"]) ) {
1746  $cu = $_POST["cu"];
1747  } else {
1748  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1749  }
1750  $categories_list = array();
1751 
1752  $memdata_done_file = getDoneFile($cu, "memdata", "migrate");
1753  $switchaccount_done_file = getDoneFile($cu, "switchaccounts", "migrate");
1754 
1755  $include_switchaccount_settings_file = getSwitchAccountsSettingFile($cu);
1756 
1757  // first element is used to display as default i.e. settings
1758  $general_list = array("settings", "admin", "memdata");
1759 
1760  if (file_exists($memdata_done_file)) {
1761  $categories_list = $general_list;
1762 
1763  // only allow switchaccounts if set up in settings for this $cu
1764  if (file_exists($include_switchaccount_settings_file)) {
1765  if (!file_exists(getDoneFile($cu, "switchaccounts", "migrate"))
1766  && !file_exists(getWIPFile($cu, "switchaccounts", "migrate"))) {
1767  $categories_list[] = "switchaccounts";
1768  }
1769  }
1770 
1771  // allow loanapps after switchaccounts (if configured)
1772  if (file_exists($include_switchaccount_settings_file)){
1773  if (file_exists(getDoneFile($cu, "switchaccounts", "migrate"))) {
1774  $categories_list[] = "loanapp";
1775  }
1776  } else {
1777  $categories_list[] = "loanapp";
1778  }
1779  }
1780 
1781  else {
1782  $categories_list = $general_list;
1783  }
1784 
1785  // make memhist the last element
1786  $categories_list[] = "memhist";
1787 
1788  $response = array("success"=> True,
1789  "message" => "Updated categories list for CU '$cu'.",
1790  "categories_list" => $categories_list);
1791  }
1792 
1793  // **********************************************************************************************
1794  // Show/Hide Account Ref Download Button
1795  // **********************************************************************************************
1796  //
1797  elseif ($_POST["post_purpose"] == "display_accref_download") {
1798 
1799  if ( isset($_POST["cu"]) ) {
1800  $cu = $_POST["cu"];
1801  } else {
1802  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1803  }
1804 
1805  // get account cross-reference file
1806  $accCrossRefFile = getAccCrossRefFile($cu);
1807  // get migration completion mark file
1808  $memdataDoneFile = getDoneFile($cu, "memdata", "migrate");
1809 
1810  if (file_exists($accCrossRefFile) && file_exists($memdataDoneFile)) {
1811  $response = array("success"=> True, "message" => "Show account reference download button.", "show_btn" => True );
1812  } else {
1813  $response = array("success"=> True, "message" => "'migrate-memdata' not completed. Disable account reference download button.", "show_btn" => False );
1814  }
1815  }
1816 
1817  // **********************************************************************************************
1818  // Show/Hide HomeBanking Informational Text
1819  // **********************************************************************************************
1820  //
1821  elseif ($_POST["post_purpose"] == "display_hb_info_text") {
1822 
1823  if ( isset($_POST["cu"]) ) {
1824  $cu = $_POST["cu"];
1825  } else {
1826  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1827  }
1828 
1829  $cu = trim($cu);
1830  $dbh = $link;
1831 
1832  // First, see if there's a record for this CU in cuadmin table at all
1833  $sql = "select count(*) from cuadmin where cu='" . strtoupper($cu) . "';";
1834  if($qr_result = db_query($sql, $dbh)) {
1835  $result_arr = db_fetch_array($qr_result);
1836  }
1837  $cuadmin_count = $result_arr[0];
1838 
1839  // If a record exists in cuadmin table for this CU
1840  if($cuadmin_count == "1") {
1841  // fetch flagset2, offlinestat and livebatch infor from cuadmin table
1842  $sql_flagset2 = "select flagset2, offlinestat, livebatch from cuadmin where cu='" . strtoupper($cu) . "';";
1843  $query_result_record = db_query($sql_flagset2, $dbh);
1844  $row = db_fetch_array($query_result_record);
1845 
1846  $livebatch = trim($row["livebatch"]);
1847  $offlinestat = trim($row["offlinestat"]);
1848  $flagset2 = $row["flagset2"];
1849 
1850  // Check if the Allow Member Alerts Processing info is marked CHECKED or not
1851  if ($flagset2 & GetFlagsetValue("CU2_ALLOW_MBR_ALERTS")) $flag2_33554432_ck = "CHECKED"; else $flag2_33554432_ck = "";
1852 
1853  // Check if the Allow Repeating Transactions info is marked CHECKED or not
1854  if ($flagset2 & GetFlagsetValue("CU2_PROCRECUR")) $flag2_32_ck = "CHECKED"; else $flag2_32_ck = "";
1855 
1856  // Get the offline status of the CU, Only applicable for Live CUs
1857  if ($livebatch == 'L') {
1858  $show_offline_status = True;
1859 
1860  // initial status "" is considered as "N"
1861  if ($offlinestat == 'N' || $offlinestat == "") {
1862  $return_offlinestat = "Active";
1863  }
1864  elseif ($offlinestat == 'U') {
1865  $return_offlinestat = "Offline (Auto Up)";
1866  }
1867  elseif ($offlinestat == 'Y') {
1868  $return_offlinestat = "Offline (Stay Down)";
1869  }
1870  else {
1871  $return_offlinestat = "Undefined (Live)";
1872  }
1873  }
1874  else {
1875  $show_offline_status = False;
1876  $return_offlinestat = "Not Applicable (Batch)";
1877  }
1878 
1879  // Prepare a response accordingly
1880  $response = array("success"=> True, "message" => "Settings flags retrieved successfully.", "CU2_ALLOW_MBR_ALERTS" => $flag2_33554432_ck, "CU2_PROCRECUR" => $flag2_32_ck, "show_offline_status" => $show_offline_status, "offlinestat" => $return_offlinestat);
1881  }
1882  // if there isn't any record for this CU in cuadmin table
1883  else {
1884  $response = array("success"=> False, "message" => "No 'cuadmin' record exist for " . strtoupper($cu) . ". Run 'migrate-settings'?");
1885  }
1886  }
1887 
1888 
1889  // **********************************************************************************************
1890  // Execute fix_public_html.pl script
1891  // **********************************************************************************************
1892  //
1893  elseif ($_POST["post_purpose"] == "fix_public_html") {
1894 
1895  if ( isset($_POST["cu"]) ) {
1896  $cu = $_POST["cu"];
1897  } else {
1898  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1899  }
1900 
1901  if ( isset($_POST["from"]) ) {
1902  $from = $_POST["from"];
1903  } else {
1904  throw new exception("'from domain' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1905  }
1906 
1907  if ( isset($_POST["to"]) ) {
1908  $to = $_POST["to"];
1909  } else {
1910  throw new exception("'to domain' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1911  }
1912  // maintain audit log
1913  auditLogMigrationExecution($cu, "", "public_html update ($from->$to)", "public_html directory contents", "Button clicked.");
1914 
1915  $publichtmlPath = getPublicHtmlPath($cu);
1916 
1917  if (file_exists($publichtmlPath)) {
1918  $response = executeFixPublicHtmlScript($cu, $from, $to);
1919  } else {
1920  $response = array("success"=> False, "message" => "'public_html' directory does not exist.");
1921  }
1922  }
1923 
1924  // **********************************************************************************************
1925  // Show/Hide Settings and Members Lock/Unlock buttons
1926  // **********************************************************************************************
1927  //
1928  elseif ($_POST["post_purpose"] == "display_lock_unlock_preventive_buttons") {
1929 
1930  if ( isset($_POST["cu"]) ) {
1931  $cu = $_POST["cu"];
1932  } else {
1933  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1934  }
1935 
1936  if ( isset($_POST["cat_group"]) ) {
1937  $cat_group = $_POST["cat_group"];
1938  } else {
1939  throw new exception("'cat_group' (Settings or Admin) not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1940  }
1941 
1942  if($cat_group == "Admin" or $cat_group == "Settings") {
1943  $msg = "";
1944  if ($cat_group == "Settings") {
1945 
1946  if (file_exists(getDoneFile($cu, "settings", "migrate"))) {
1947  $msg = "'settings' data category migration has completed. Show Lock/Unlock Settings button.";
1948  $show_btn = True;
1949  } else {
1950  $msg = "'settings' data category migration has not completed. Disable Lock/Unlock Settings button.";
1951  $show_btn = False;
1952  }
1953  } else {
1954 
1955  if (file_exists(getDoneFile($cu, "admin", "migrate"))) {
1956  $msg = "'admin' data category migration has completed completed. Show Lock/Unlock Admin button.";
1957  $show_btn = True;
1958  } else {
1959  $msg = "'admin' data category migration has not completed. Disable Lock/Unlock Admin button.";
1960  $show_btn = False;
1961  }
1962  }
1963  if(file_exists(getLockFileForPreventingFurtherMigration($cu, $cat_group))) {
1964  $locked = True;
1965  } else {
1966  $locked = False;
1967  }
1968 
1969  $response = array("success"=> True, "message" => $msg, "show_btn" => $show_btn, "locked" => $locked );
1970  } else {
1971  throw new exception("Invalid 'cat_group': must be either Settings or Admin. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1972  }
1973  }
1974 
1975  // **********************************************************************************************
1976  // Handle lock files for Settings and Members Lock/Unlock button operation
1977  // **********************************************************************************************
1978  //
1979  elseif ($_POST["post_purpose"] == "lock_unlock_cat_group") {
1980 
1981  if ( isset($_POST["cu"]) ) {
1982  $cu = $_POST["cu"];
1983  } else {
1984  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1985  }
1986 
1987  if ( isset($_POST["cat_group"]) ) {
1988  $cat_group = $_POST["cat_group"];
1989  } else {
1990  throw new exception("'cat_group' (Admin or Settings) not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1991  }
1992 
1993  if ( isset($_POST["lock_or_unlock"])) {
1994  $lock_or_unlock = $_POST["lock_or_unlock"];
1995  } else {
1996  throw new exception("'lock_or_unlock' (lock or unlock) not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
1997  }
1998 
1999  if ($lock_or_unlock == "lock" or $lock_or_unlock == "unlock") {
2000 
2001  if($cat_group == "Settings" || $cat_group == "Admin") {
2002  if ($cat_group == "Settings") {
2003  $settingsDoneFile = getDoneFile($cu, "settings", "migrate");
2004 
2005  if (file_exists($settingsDoneFile)) {
2006  $preventSettingsLockFile = getLockFileForPreventingFurtherMigration($cu, $cat_group);
2007  if($lock_or_unlock == "lock") {
2008  touch($preventSettingsLockFile);
2009  }
2010  // unlock
2011  else {
2012  if(file_exists($preventSettingsLockFile)) {
2013  unlink($preventSettingsLockFile);
2014  }
2015  }
2016  }
2017 
2018  } else { // Admin
2019  $adminDoneFile = getDoneFile($cu, "admin", "migrate");
2020 
2021  if (file_exists($adminDoneFile)) {
2022  $preventAdminLockFile = getLockFileForPreventingFurtherMigration($cu, $cat_group);
2023  if($lock_or_unlock == "lock") {
2024  touch($preventAdminLockFile);
2025  }
2026  // unlock
2027  else {
2028  if(file_exists($preventAdminLockFile)) {
2029  unlink($preventAdminLockFile);
2030  }
2031  }
2032  }
2033  }
2034 
2035  } else {
2036  throw new exception("Invalid 'cat_group': must be Admin or Settings. (" . __FILE__ . ":" . __LINE__ . ")", 1);
2037  }
2038  } else {
2039  throw new exception("Invalid 'lock_or_unlock': must be lock or unlock. (" . __FILE__ . ":" . __LINE__ . ")", 1);
2040  }
2041  $lock_unlock_msg = "'". $cat_group . "' is '" . $lock_or_unlock . "ed'.";
2042  // log Settings/Migrations lock/unlock settings changes
2043  auditLogMigrationExecution($cu, "", "Toggle lock-unlock", $cat_group, $lock_unlock_msg);
2044  $response = array("success"=> True, "message" => $lock_unlock_msg);
2045  }
2046 
2047  // **********************************************************************************************
2048  // Prepare ready for final migration flag
2049  // **********************************************************************************************
2050  //
2051  elseif ($_POST["post_purpose"] == "get_final_migr_flag") {
2052 
2053  if ( isset($_POST["cu"]) ) {
2054  $cu = $_POST["cu"];
2055  } else {
2056  throw new exception("'CU' not provided. (" . __FILE__ . ":" . __LINE__ . ")", 1);
2057  }
2058 
2059  // get migration completion mark file
2060  $final_migr_memcount_file = getFinalMigrationConfigFile($cu);
2061  $show_final_migr_button = False;
2062  $memdata_count = 0;
2063  $memhist_count = 0;
2064  $noWIP = False;
2065 
2066  if (!file_exists($final_migr_memcount_file)) {
2067  if(touch($final_migr_memcount_file)) {
2068  file_put_contents($final_migr_memcount_file, "memdata_count,memhist_count\n$memdata_count".",". "$memhist_count\n");
2069  }
2070  } else {
2071  if (($fileStr = file_get_contents($final_migr_memcount_file)) != False) {
2072  $mem_count_arr = explode(",", explode("\n", $fileStr)[1]);
2073  $memdata_count = (int)$mem_count_arr[0];
2074  $memhist_count = (int)$mem_count_arr[1];
2075  }
2076  }
2077 
2078  // make sure Settings (settings) and Admin(admin) are migrated, updated and locked from accidental deletion
2079  $SettingsLocked = (file_exists(getLockFileForPreventingFurtherMigration($cu, "Settings")));
2080  $AdminLocked = (file_exists(getLockFileForPreventingFurtherMigration($cu, "Admin")));
2081  // but memdata and memhist were ran atleast once each earlier for testing ($memdata_count > 0 && $memhist_count > 0), and
2082  // memdata and memhist are cleaned up before final migration
2083  $memdataIsClean = (!file_exists(getDoneFile($cu, "memdata", "migrate")));
2084  $memhistIsClean = (!file_exists(getDoneFile($cu, "memhist", "migrate")));
2085 
2086  $wip_list = getCurrentWIPCategoryList($cu);
2087  $noWIP = (count($wip_list) == 0);
2088 
2089 
2090  if($memdata_count > 0 && $memhist_count > 0 && $SettingsLocked && $AdminLocked && $memdataIsClean && $memhistIsClean && $noWIP) {
2091  $show_final_migr_button = True;
2092  }
2093  $response_options = array();
2094  $response_options["memdata_gt0"] = ($memdata_count >0);
2095  $response_options["memhist_gt0"] = ($memhist_count >0);
2096  $response_options["SettingsAdminLocked"] = ($SettingsLocked && $AdminLocked);
2097  $response_options["memdata_is_clean"] = $memdataIsClean;
2098  $response_options["memhist_is_clean"] = $memhistIsClean;
2099  $response_options["no_wip_exists"] = $noWIP;
2100  $response_options["show_final_migr_button"] = $show_final_migr_button;
2101 
2102 
2103  $response = array("success"=> True, "message" => "", "final_migr_resp" => $response_options );
2104  }
2105 
2106  // **********************************************************************************************
2107  // Otherwise, unknown request
2108  // **********************************************************************************************
2109 
2110  else {
2111  unset($_POST["password"]);
2112  $passed_arguments = http_build_query($_POST, '', ', ') . " (password not displayed.)";
2113  $response = array("success"=> False, "message" => "Unknown request. Passed arguments: " . $passed_arguments );
2114  }
2115 
2116  } else {
2117  $msg_suffix = "";
2118  if (isset($_POST["password"])) {
2119  unset($_POST["password"]);
2120  $passed_arguments = http_build_query($_POST, '', ', ') . " (password not displayed.)";
2121  $msg_suffix = "Passed arguments: " . $passed_arguments;
2122  }
2123  $response = array("success"=> False, "message" => "[HTTP parameters error] Not a valid request." . $msg_suffix );
2124 
2125  }
2126  } catch (exception $e) {
2127  $msg_suffix = "";
2128  if (isset($_POST["password"])) {
2129  unset($_POST["password"]);
2130  $passed_arguments = http_build_query($_POST, '', ', ') . " (password not displayed.)";
2131  $msg_suffix = "Passed arguments: " . $passed_arguments;
2132  }
2133  $response = array("success"=> False, "message" => "[HTTP parameters error]" . $e->getMessage()) . $msg_suffix;
2134  }
2135 
2136  return $response;
2137 }
2138 
2139 // return http response to the client for this specific request
2140 echo HCU_JsonEncode(serveMigrationPurpose());
2141 
2142 ?>