### v.2.2 EARTH RC 1
-* Bug 34 - DB fix in config, removes associated RTF documents to logs, for some reason.
+* ✔ Bug 34 - DB fix in config, removes associated RTF documents to logs, for some reason.
* Page section plugins.
* Configured in main.cnf.
* Accessed via side menu to appear.
### Config Page config.cgi
-- ☑ Look & Feel, autonom variables, like release version showing at end of System Configuration, clustered as uneditable.
+- ☑ Look & Feel, autonom variables, like release version showing at end of System Configuration, clustered as edit enabled.
- ☑ Editing and changing works.
- ☐ Categories, adding, deleting, renaming works.
- ☐ Database fixes all work.
use DateTime::Format::SQLite;
use Date::Language;
+use Capture::Tiny ':all';
use Text::CSV;
use Scalar::Util qw(looks_like_number);
use Sys::Syslog qw(:DEFAULT :standard :macros); #openLog, closelog macros
}
-
sub processDBFix {
my $rs_syst = $cgi->param("reset_syst");
try{
- my %dates = ();
- my @dlts = ();
- #Hash is unreliable for returning sequential order of keys so array must do.
- my @updts = ();
- my $cntr_del =0;
- my $existing;
- my @row;
+ my %dates = ();
+ #Hash is unreliable for returning sequential order of keys so array must do.
+ my @dlts = ();
+ my $cntr_del =0;
+ my $existing;
+ my @row;
+
+ getHeader() if(&Settings::debug);
+ print "<h3>Database Records Fix Result</h3>\n<hr>" if(&Settings::debug);
+ print "<body><pre>Started transaction!\n" if(&Settings::debug);
$db->do('BEGIN TRANSACTION;');
- #Check for duplicates, which are possible during imports or migration as internal rowid is not primary in log.
+ # Check for duplicates, which are possible during imports or migration as internal rowid is not primary in log.
+ # @TODO This should be selecting an cross SQL compatibe view.
if(Settings::isProgressDB()){
$dbs = Settings::selectRecords($db, 'SELECT ID, DATE FROM LOG ORDER BY DATE;');
}else{
}
else{
$dates{$row[0]} = $row[1];
- $updts[$cntr_upd++] = $row[0];
}
}
}else{
$sql = "DELETE FROM LOG WHERE ID=$del;";
}
- #print "$sql\n<br>";
- my $st_del = $db->prepare($sql);
- $st_del->execute();
+ print "$sql\n<br>";
+ my $st_del = $db->prepare($sql);
+ $st_del->execute();
}
-
+ print "Doing renumerate next...\n" if(&Settings::debug);
&renumerate;
+ print "done!\n";
+ print "Doing removeOldSessions next..." if(&Settings::debug);
&Settings::removeOldSessions;
+ print "done!\n " if(&Settings::debug);
&resetCategories if $rs_cats;
&resetSystemConfiguration($db) if $rs_syst;
&wipeSystemConfiguration if $wipe_ss;
-
-
- $db->do('COMMIT;');
- $db->disconnect();
+ $db->do('COMMIT;')if(&Settings::debug);
+ print "Commited ALL!<br>"if(&Settings::debug);
+ # $db->disconnect();
$db = Settings::connectDB();
- $dbs = $db->do("VACUUM;");
-
-
+ $dbs = $db->do("VACUUM;")if(&Settings::debug);
+ print "Issued VACUUM!<br>"if(&Settings::debug);
+
if($LOGOUT){
&logout;
}
+ exit if(&Settings::debug);
}
catch{
}
}
+sub renumerate {
+
+ # NOTE: This is most likelly all performed under an transaction.
+ my $sql;
+ # Fetch list by date identified rtf attached logs, with possibly now an old LID, to be updated to new one.
+ if(Settings::isProgressDB()){
+ $sql = "SELECT ID, DATE FROM LOG WHERE RTF > 0;"
+ }else{
+ $sql = "SELECT rowid, DATE FROM LOG WHERE RTF > 0;"
+ }
+ my @row = Settings::selectRecords($db, $sql)->fetchrow_array();
+ my %notes = ();
+ if (scalar @row > 0){
+ $notes{$row[1]} = $row[0]; #<- This is current LID, will change.
+ print "Expecting Note entry for ".$row[1]." LOG.ID[".$row[0]."]<- LID...\n";
+ }
+
+ ### RENUMERATE LOG
+ $db->do("CREATE TABLE life_log_temp_table AS SELECT * FROM LOG;");
+ if(Settings::isProgressDB()){
+ $db->do('DROP TABLE LOG CASCADE;');
+ }
+ else{
+ $db->do('DROP TABLE LOG;');
+ }
+ $db->do(&Settings::createLOGStmt);
+ $db->do(q(INSERT INTO LOG (ID_CAT, DATE, LOG, RTF, AMOUNT,AFLAG)
+ SELECT ID_CAT, DATE, LOG, RTF, AMOUNT, AFLAG FROM life_log_temp_table ORDER by DATE;));
+ $db->do('DROP TABLE life_log_temp_table;');
+ ###
+
+ # Update notes with new log id, if it changed.
+
+ foreach my $date (keys %notes){
+ my $old = $notes{$date};
+ #my $sql_date = DateTime::Format::SQLite->parse_datetime($date);
+
+ if(Settings::isProgressDB()){
+ $sql = "SELECT ID FROM LOG WHERE RTF > 0 AND DATE = '".$date."';";
+ }else{
+ $sql = "SELECT rowid FROM LOG WHERE RTF > 0 AND DATE = '".$date."';";
+ }
+ print "Selecting -> $sql\n";
+ $dbs = Settings::selectRecords($db, $sql);
+ @row = $dbs->fetchrow_array();
+ if(scalar @row > 0){
+ my $new = $row[0];
+ if($new ne $old){
+ $db->do("UPDATE NOTES SET LID =$new WHERE LID=$old;");
+ print "Updated Note in LID[$old] to be LID[$new]\n";
+ }
+ else{
+ print "All fine skipping LID[$new]\n";
+ }
+ }else{
+ print "ERROR NOT FOUND: $date for LID:$old!\n";
+ }
+
+ }
+
+ # Delete Orphaned Notes entries if any?
+ if(Settings::isProgressDB()){
+ $dbs = Settings::selectRecords($db, "SELECT LID, LOG.ID from NOTES LEFT JOIN LOG ON
+ NOTES.LID = LOG.ID WHERE LOG.ID is NULL;");
+ }else{
+ $dbs = Settings::selectRecords($db, "SELECT LID, LOG.rowid from NOTES LEFT JOIN LOG ON
+ NOTES.LID = LOG.rowid WHERE LOG.rowid is NULL;");
+ }
+ if ($dbs) { foreach (@row = $dbs->fetchrow_array()) {
+ $db->do("DELETE FROM NOTES WHERELID=$row[0];") if $row[0]; # 0 is the place keeper for the shared zero record.
+ }}
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
sub resetCategories {
$db->do("DELETE FROM CAT;");
$db->do("DROP TABLE CAT;");
while(<$TAR>){print $_;}
close $TAR;
exit;
-
}
+package DBMigStats {
+
+
+ sub new {
+ my $class = shift;
+ my $self = bless {cats_ins => 0, cats_upd => 0, logs_ins => 0, logs_upd => 0, notes => 0}, $class;
+ }
+
+ sub cats_inserts(){my $s = shift;return $s->{cats_ins}}
+ sub cats_inserts_incr() {my $s = shift; $s->{cats_ins}++}
+ sub cats_updates(){my $s = shift;return $s->{cats_upd}}
+ sub cats_updates_incr() {my $s = shift; $s->{cats_upd}++}
+
+ sub logs_inserts(){my $s = shift;return $s->{logs_ins}}
+ sub logs_inserts_incr(){my $s = shift; $s->{logs_ins}++}
+ sub logs_updates(){my $s = shift;return $s->{logs_upd}}
+ sub logs_updates_incr(){my $s = shift; $s->{logs_upd}++}
+
+ sub notes() {my $s = shift;return $s->{notes}}
+ sub notes_incr() {my $s = shift; $s->{notes}++}
+
+}
sub restore {
+
my $file = shift;
- my ($tar,$pipe,@br);
+ my ($tar,$pipe,@br,$stdout,$b_db);
my $pass = Settings::pass();
my $hndl = $cgi->param('data_bck');
my $dbck = &Settings::logPath."bck/"; `mkdir $dbck` if (!-d $dbck);
+
try{
getHeader();
print $cgi->start_html;
+
+my $stdout = capture_stdout {
+
+ print "<h3>Restore Result</h3>\n<hr>";
+ print "Restore started: ".Settings::today(), "\n";
if($file){ #Open handle on server to backup to be restored.
my $f = &Settings::logPath.$file;
open($hndl, '<', $f) or die "Can't open $f: $!";
- print "<pre>Reading on server -> $file</pre>";
+ print "<pre>Reading on server backup file -> $file</pre>";
$tar = $dbck.$file;
}
else{
close $pipe; close $hndl;
print "<pre>\n";
+
+
my $m1 = "it is not permitted to restore another aliases log backup.";
$m1= "has your log password changed?" if ($tar=~/_data_$alias/);
my $cmd = `tar tvf $tar 2>/dev/null`
or die qq(, possible an security issue, $m1\nBACKUP FILE INVALID! $tar\nYour data alias is: <b>$alias</b>\nYour LifeLog version is:), Settings::release()."\n";
- print "Contents->".$cmd."\n\n";
+ print "Contents->\n".$cmd."\n\n";
$cmd = `tar xzvf $tar -C $dbck --strip-components 1 2>/dev/null` or die "Failed extracting $tar";
print "Extracted->\n".$cmd."\n" or die "Failed extracting $tar";;
my $b_base = $dbck.'data_'.$dbname.'_log.db';
my $dsn= "DBI:SQLite:dbname=$b_base";
- my $b_db = DBI->connect($dsn, $alias, $pass, { RaiseError => 1 }) or LifeLogException->throw(error=>"Invalid database! $dsn->$hndl [$@]", show_trace=>&Settings::debug);
+ $b_db = DBI->connect($dsn, $alias, $pass, { RaiseError => 1 }) or LifeLogException->throw(error=>"Invalid database! $dsn->$hndl [$@]", show_trace=>&Settings::debug);
print "Connected to -> $dsn\n";
- print "Merging from backup categories table...\n";
+ print "Merging from backup categories table...";
+ my $stats = DBMigStats -> new();
my $insCAT = $db->prepare('INSERT INTO CAT (ID, NAME, DESCRIPTION) VALUES(?,?,?);') or die "Failed CAT prepare.";
my $b_pst = Settings::selectRecords($b_db,'SELECT ID, NAME, DESCRIPTION FROM CAT;');
+
while ( @br = $b_pst->fetchrow_array() ) {
- my $pst = Settings::selectRecords($db, "SELECT ID,NAME,DESCRIPTION FROM CAT WHERE ID=".$br[0].";");
+ my $pst = Settings::selectRecords($db, "SELECT ID, NAME, DESCRIPTION FROM CAT WHERE ID=".$br[0].";");
my @ext = $pst->fetchrow_array();
if(scalar(@ext)==0){
$insCAT->execute($br[0],$br[1],$br[2]);
- print "Added CAT->".$br[0]."|".$br[1]."\n";
+ print "\nAdded CAT->".$br[0]."|".$br[1]; $stats->DBMigStats::cats_inserts_incr();
}
elsif($br[0] ne $ext[0] or $br[1] ne $ext[1]){
$db->do("UPDATE CAT SET NAME='".$br[1]."', DESCRIPTION='".$br[2]."' WHERE ID=$br[0];") or die "Cat update failed!";
- print "Updated->".$br[0]."|".$br[1]."|".$br[2]."\n";
+ print "\nUpdated->".$br[0]."|".$br[1]."|".$br[2]; $stats->DBMigStats::cats_updates_incr();
}
}
+
print "\nFinished with merging CAT table.\n";
+ print "There where -> ". $stats->cats_inserts(). " inserts, and ". $stats->cats_updates(). " updates.\n";
print "\n\nMerging from backup LOG table...\n";
- my $insLOG = $db->prepare('INSERT INTO LOG (ID_CAT, ID_RTF, DATE, LOG, AMOUNT, AFLAG, STICKY) VALUES(?,?,?,?,?,?,?);')or die "Failed LOG prepare.";
+ my %backupLIDS =();
+ my $insLOG = $db->prepare('INSERT INTO LOG (ID_CAT, DATE, LOG, RTF, AMOUNT, AFLAG, STICKY) VALUES(?,?,?,?,?,?,?);')or die "Failed LOG prepare.";
- $b_pst = Settings::selectRecords($b_db,'SELECT ID, ID_CAT, ID_RTF, DATE, LOG, AMOUNT, AFLAG, STICKY FROM '.Settings->VW_LOG);
+ $b_pst = Settings::selectRecords($b_db,'SELECT ID, ID_CAT, DATE, LOG, RTF, AMOUNT, AFLAG, STICKY FROM '.Settings->VW_LOG);
while ( @br = $b_pst->fetchrow_array() ) {
- my $pst = Settings::selectRecords($db,"SELECT DATE FROM ".Settings->VW_LOG." WHERE DATE='".$br[3]."';");
+ my $pst = Settings::selectRecords($db,"SELECT DATE FROM ".Settings->VW_LOG." WHERE DATE='".$br[2]."';");
my @ext = $pst->fetchrow_array();
if(scalar(@ext)==0){
$insLOG->execute($br[1],$br[2],$br[3],$br[4],$br[5],$br[6],$br[7]);
- print "Added->".$br[0]."|".$br[3]."|".$br[4]."\n";
+ print "Added->".$br[0]."|".$br[2]."|".$br[3]."\n"; $stats->logs_inserts_incr();
+ if($br[5]){
+ $pst = Settings::selectRecords($db, "SELECT max(id) FROM ".Settings->VW_LOG);
+ my @r = $pst->fetchrow_array();
+ $backupLIDS{$br[0]} = $r[0];
+ }
}
-
}
print "\nFinished with merging LOG table.\n";
+ print "There where -> ". $stats->logs_inserts(). " inserts.\n";
- print "\n\nMerging from backup NOTES table...\n";
- my $insNOTES = $db->prepare('INSERT INTO NOTES (LID, DOC) VALUES(?,?);')or die "Failed NOTESprepare.";
+ print "\nMerging from backup NOTES table...\n";
+ my $insNOTES = $db->prepare('INSERT INTO NOTES (LID, DOC) VALUES(?,?);')or die "Failed NOTES prepare.";
$b_pst = Settings::selectRecords($b_db,'SELECT LID, DOC FROM NOTES;');
while ( @br = $b_pst->fetchrow_array() ) {
- my $pst = Settings::selectRecords($db,"SELECT LID FROM NOTES WHERE LID=".$br[0].";");
- my @ext = $pst->fetchrow_array();
- if(@ext==0&&$br[0]&&$br[1]){
- $insNOTES->execute($br[0], $br[1]) or die "Failed NOTES INSERT[".$br[0]."]";
- print "Added NOTES->".$br[0]."\n";
+ my $in_id = $backupLIDS{$br[0]};
+ if($in_id){
+ my $pst = Settings::selectRecords($db,"SELECT LID FROM NOTES WHERE LID=".$br[0].";");
+ my @ext = $pst->fetchrow_array();
+ if(@ext==0&&$br[1]){
+ $insNOTES->execute($in_id, $br[1]) or die "Failed NOTES INSERT[".$br[0]."]";
+ print "Added NOTES -> LID:".$br[0]."\n";
+ }
}
-
}
print "\nFinished with merging NOTES table.\n";
-
- $b_db->disconnect();
- $db->disconnect();
+ print "Note that the merge didn't recover documents for any existing log entries.\n";
+ print "To do this, delete those log entries, then run restore again.\n";
`rm -rf $dbck/`;
print "Done!";
+ print "Restore ended: ".Settings::today(), "\n";
+}; print $stdout;
+
+ my $fh; open( $fh, ">>", Settings::logPath()."backup_restore.log");
+ print $fh $stdout;
+ close $fh;
+
+ $b_db->disconnect();
+ $db->disconnect();
}
catch{
$ERROR = "<font color='red'><b>Restore Failed!</b></font>hndl->$hndl $@ \n";
if(scalar(@fields)>6){
my $i = 0;
- my $id_cat = $fields[$i++];
- my $id_rtf = $fields[$i++];
+ my $id_cat = $fields[$i++];
my $date = $fields[$i++];
my $log = $fields[$i++];
+ my $rtf = $fields[$i++];
my $amv = $fields[$i++];
my $amf = $fields[$i++];
my $sticky = $fields[$i++];
# Is it old pre. 1.8 format -> ID, DATE, LOG, AMOUNT, AFLAG, RTF, STICKY
- if(!looks_like_number($id_rtf)){
+ if(!looks_like_number($rtf)){
$i = 0;
$id_cat = $fields[$i++];
- $date = $fields[$i++];
+ $rtf = $fields[$i++];
+ $date = $fields[$i++];
$log = $fields[$i++];
$amv = $fields[$i++];
- $amf = $fields[$i++];
- $id_rtf = $fields[$i++];
+ $amf = $fields[$i++];
$sticky = $fields[$i++];
}
my $pdate = DateTime::Format::SQLite->parse_datetime($date);
my @rows = $dbs->fetchrow_array();
if(scalar @rows == 0){
$dbs = $db->prepare('INSERT INTO LOG VALUES (?,?,?,?,?,?,?)');
- $dbs->execute($id_cat, $id_rtf, $pdate, $log, $amv, $amf, $sticky);
+ $dbs->execute($id_cat, $pdate, $log, $rtf, $amv, $amf, $sticky);
}
$dbs->finish();
}
}
-sub renumerate {
- #Renumerate Log! Copy into temp. table.
- my $sql;
- $db->do("CREATE TABLE life_log_temp_table AS SELECT * FROM LOG;");
- if(Settings::isProgressDB()){
- $dbs = Settings::selectRecords($db, 'SELECT ID, DATE FROM LOG WHERE ID_RTF > 0 ORDER BY DATE;');
- }else{
- $dbs = Settings::selectRecords($db, 'SELECT rowid, DATE FROM LOG WHERE ID_RTF > 0 ORDER BY DATE;');
- }
- #update notes with new log id
- while(my @row = $dbs->fetchrow_array()) {
- my $sql_date = $row[1];
- if($sql_date){#could be an improperly deleted record in there? Skip if there is!
- #$sql_date =~ s/T/ /;
- $sql_date = DateTime::Format::SQLite->parse_datetime($sql_date);
- if(Settings::isProgressDB()){
- $sql = "SELECT ID, DATE FROM life_log_temp_table WHERE ID_RTF > 0 AND DATE = '".$sql_date."';";
- }else{
- $sql = "SELECT rowid, DATE FROM life_log_temp_table WHERE ID_RTF > 0 AND DATE = '".$sql_date."';";
- }
- $dbs = Settings::selectRecords($db, $sql);
- my @new = $dbs->fetchrow_array();
- if(scalar @new > 0){
- $db->do("UPDATE NOTES SET LID =". $new[0]." WHERE LID==".$row[0].";");
- }
+ my %dates = ();
+ #Hash is unreliable for returning sequential order of keys so array must do.
+ my @dlts = ();
+ my $cntr_del =0;
+ my $existing;
+ my @row;
+
+ getHeader();
+ print "<body><pre>Started transaction!\n";
+
+ $db->do('BEGIN TRANSACTION;');
+ # Check for duplicates, which are possible during imports or migration as internal rowid is not primary in log.
+ # @TODO This should be done through an view?
+ if(Settings::isProgressDB()){
+ $dbs = Settings::selectRecords($db, 'SELECT ID, DATE FROM LOG ORDER BY DATE;');
+ }else{
+ $dbs = Settings::selectRecords($db, 'SELECT rowid, DATE FROM LOG ORDER BY DATE;');
+ }
+ while(@row = $dbs->fetchrow_array()) {
+ my $existing = $dates{$row[0]};
+ if($existing && $existing eq $row[1]){
+ $dlts[$cntr_del++] = $row[0];
+ }
+ else{
+ $dates{$row[0]} = $row[1];
+ }
}
- }
- # Delete Orphaned Notes entries.
- if(Settings::isProgressDB()){
- $dbs = Settings::selectRecords($db, "SELECT LID, LOG.ID from NOTES LEFT JOIN LOG ON
- NOTES.LID = LOG.ID WHERE LOG.ID is NULL;");
- }else{
- $dbs = Settings::selectRecords($db, "SELECT LID, LOG.rowid from NOTES LEFT JOIN LOG ON
- NOTES.LID = LOG.rowid WHERE LOG.rowid is NULL;");
- }
- while(my @row = $dbs->fetchrow_array()) {
- $db->do("DELETE FROM NOTES WHERE LID=$row[0];");
- }
- if(Settings::isProgressDB()){
- $db->do('DROP TABLE LOG CASCADE;');
- }
- else{
- $db->do('DROP TABLE LOG;');
- }
- $db->do(&Settings::createLOGStmt);
- $db->do(q(INSERT INTO LOG (ID_CAT, ID_RTF, DATE, LOG, AMOUNT,AFLAG)
- SELECT ID_CAT, ID_RTF, DATE, LOG, AMOUNT, AFLAG FROM life_log_temp_table ORDER by DATE;));
- $db->do('DROP TABLE life_log_temp_table;');
-}
+
1;
\ No newline at end of file
my $db = Settings::fetchDBSettings();
my $cgi = Settings::cgi();
my $dbname = Settings::dbName();
-my $imgw = 210;
-my $imgh = 120;
my $human = DateTime::Format::Human::Duration->new();
my $PRC_WIDTH = Settings::pagePrcWidth();
my $DEBUG = Settings::debug();
my $today = Settings::today();
-my $tbl_rc =0;
-
+my $tbl_rc = 0;
+my $imgw = 210;
+my $imgh = 120;
my $opr = $cgi->param("opr");
my $confirmed = $cgi->param('confirmed');
if ($opr == 1){
my $tbl = '<a name="top"></a><form name="frm_log_del" action="data.cgi" onSubmit="return formDelValidation();">
<table class="tbl_rem" width="'.$PRC_WIDTH.'%">
- <tr class="hdr" style="text-align:left;"><th>Date <a href="#bottom">↡</a></th> <th>Time</th> <th>Log</th> <th>Category</th></tr>';
+ <tr class="hdr" style="text-align:left;">
+ <th>Date <a href="#bottom">↡</a></th> <th>Time</th> <th>Log</th> <th>Category <a href="#bottom">↡</a></th></tr>';
while(my @row = $st->fetchrow_array()) {
my $dt = DateTime::Format::SQLite->parse_datetime( $row[3] );
my $log = log2html($row[4]);
- $tbl = $tbl . '<tr class="r1"><td class="'.$rs.'">'. $dt->ymd . "</td>" .
+ $tbl .= '<tr class="r1"><td class="'.$rs.'">'. $dt->ymd . "</td>" .
'<td class="'.$rs.'">' . $dt->hms . "</td>" .
- '<td class="'.$rs.'" style="font-weight:bold; color:maroon;">'."$log</td>\n".
+ '<td class="'.$rs.'" style="font-weight:bold; color:maroon;">
+ <div class="log" style="overflow-x:none; max-width:600">'."$log</div></td>\n".
'<td class="'.$rs.'">' . $ct. '<input type="hidden" name="chk" value="'.$row[0].'"></td></tr>';
if($rs eq "r1"){
- $rs = "r0";
+ $rs = "r0";
}
else{
$rs = "r1";
</td></tr>
</table><input type="hidden" name="confirmed" value="1"></form>';
- print "<center><div>\n$tbl\n</div></center>";
+ print "<center><div style='background-color:".&Settings::bgcol."'>\n$tbl\n</div></center>";
print $cgi->end_html();
}
use JSON;
use IO::Compress::Gzip qw(gzip $GzipError);
use Compress::Zlib;
+use Crypt::Blowfish;
+use Crypt::CBC;
use lib "system/modules";
require Settings;
});
}
+sub cryptKey {
+ $passw = $alias.$passw.Settings->CIPHER_KEY;
+ $passw =~ s/(.)/sprintf '%04x', ord $1/seg;
+ return substr $passw.Settings->CIPHER_PADDING, 0, 58;
+}
+
sub processSubmit {
# my $date = $cgi->param('date');
- my $st;
+ my ($st, @arr);
try {
if($action eq 'store'){
- $doc = qq({
- "lid":"$lid",
- "bg":"$bg",
- "doc":$doc
- });
- my $zip = compress($doc, Z_BEST_COMPRESSION);
- $st = $db->prepare("SELECT LID FROM NOTES WHERE LID = $lid;");
- $st -> execute();
- if($st->fetchrow_array() eq undef) {
- $st = $db->prepare("INSERT INTO NOTES(LID, DOC) VALUES (?, ?);");
- $st->execute($lid, $zip);
- $response = "Stored Document (id:$lid)!";
+ my $cipher = Crypt::CBC->new(-key => cryptKey(), -cipher => 'Blowfish');
+ $doc = qq({
+ "lid": "$lid",
+ "bg": "$bg",
+ "doc": $doc
+ });
+
+ my $zip = compress($cipher->encrypt($doc), Z_BEST_COMPRESSION);
+ @arr = Settings::selectRecords($db, "SELECT LID FROM NOTES WHERE LID = $lid;")->fetchrow_array();
+ if (!@arr) {
+ $st = $db->prepare("INSERT INTO NOTES(LID, DOC) VALUES (?, ?);");
+ $st->execute($lid, $zip);
+ $response = "Stored Document (id:$lid)!";
}
else{
- $st = $db->prepare("UPDATE NOTES SET DOC = ? WHERE LID = $lid;");
- $st->execute($zip);
- $response = "Updated Document (id:$lid)!";
+ $st = $db->prepare("UPDATE NOTES SET DOC = ? WHERE LID = $lid;");
+ $st->execute($zip);
+ $response = "Updated Document (id:$lid)!";
}
}
elsif($action eq 'load'){
- $st = $db->prepare("SELECT DOC FROM NOTES WHERE LID = $lid;");
- $st -> execute();
- my @arr = $st->fetchrow_array();
+ @arr = Settings::selectRecords($db, "SELECT DOC FROM NOTES WHERE LID = $lid;")->fetchrow_array();
if(@arr eq undef){
- $st = $db->prepare("SELECT DOC FROM NOTES WHERE LID = '0';");
- $st -> execute();
- @arr = $st->fetchrow_array();
+ @arr = Settings::selectRecords($db,"SELECT DOC FROM NOTES WHERE LID = '0';")->fetchrow_array();
}
+ my $cipher = Crypt::CBC->new(-key => cryptKey(), -cipher => 'Blowfish');
$doc = $arr[0];
- $doc = uncompress($doc);
- # print $cgi->header( -expires => "+0s", -charset => "UTF-8" );
- # print($doc);
- # exit;
+ my $d = uncompress($doc);
+ $doc = $cipher->decrypt($d);
+ # print $cgi->header( -expires => "+0s", -charset => "UTF-8" );
+ # print($doc);
+ # exit;
$response = "Loaded Document!";
}
- else{
+ else{
$error = "Your action ($action) sux's a lot!";
}
}catch {
- $error = ":LID[$lid]-> ".$_;
+ if($action eq 'load' && $@ =~ /Ciphertext does not begin with a valid header for 'salt'/){# Maybe an pre v.2.2 old document?
+ $doc = uncompress($doc);
+ $response = "Your document LID[$lid] is not secure. Please resave it.";
+ return;
+ }
+ $error = "Error on:LID[$lid]-> ".$@;
}
}
# We live check database for available tables now only once.
# If brand new database, this sill returns fine an empty array.
my %curr_tables = ();
+ #my %curr_colums = (); # %("table", @{...columns...})
if(Settings::isProgressDB()){
$changed = checkPreparePGDB();
}
}catch{$@.="\n$sup"; die "Failed[$@]"}
}
+ #Is it pre or around v.2.1, where ID_RTF is instead of RTF in the LOG table?
+ if($hasLogTbl && !Settings::isProgressDB()){
+ $pst = Settings::selectRecords($db, "SELECT * from pragma_table_info('LOG') where name like 'ID_RTF'");
+ if($pst->fetchrow_array()){
+ $db->do("ALTER TABLE LOG RENAME COLUMN ID_RTF TO RTF");
+ }
+ }
#
# From v.1.8 Log has changed, to have LOG to NOTES relation.
#
foreach my $date (keys %notes_ids){
#next if(ref($notes_ids{$date}) eq 'HASH');
my $nid = $notes_ids{$date};
- my $stmt= "UPDATE LOG SET ID_RTF =". $nid." WHERE DATE == '".$date."';";
+ my $stmt= "UPDATE LOG SET RTF =". $nid." WHERE DATE == '".$date."';";
try{
$db->do($stmt);
}
}
}
-my $sqlView = 'SELECT ID, ID_CAT, ID_RTF, DATE, LOG, AMOUNT, AFLAG, STICKY, PID FROM '.$VW_PAGE;#Only to be found here, the main SQL select statement.
+my $sqlView = 'SELECT ID, ID_CAT, DATE, LOG, RTF, AMOUNT, AFLAG, STICKY, PID FROM '.$VW_PAGE;#Only to be found here, the main SQL select statement.
my $stmS = $sqlView." WHERE";
my $stmE = ' LIMIT '.&Settings::viewAllLimit.';';
my $stmD = "";
</tr>);
#We use js+perl, trickery to filter by amount type, as well.
if($prm_aa >0){my $s = $prm_aa - 1;$prm_aa = " AFLAG=$s AND";}else{$prm_aa=""}
- if($prm_rtf){$stmS .= " ID_RTF>0 AND";}
+ if($prm_rtf){$stmS .= " RTF>0 AND";}
if($isPUBViewMode){
$sqlVWL = $stmS." ".Settings::sqlPubors().$stmE;
my $i = 0;
$id = $row[$i++]; #ID must be rowid in LOG.
my $cid = $row[$i++]; #CID ID_CAT not used.
- my $ct = $hshCats{$cid}; #ID_CAT
- my $rtf = $row[$i++]; #ID_RTF since v.1.8
+ my $ct = $hshCats{$cid}; #ID_CAT
my $dt = DateTime::Format::SQLite->parse_datetime( $row[$i++] ); #LOG.DATE
my $log = $row[$i++]; #LOG.LOG
+ my $rtf = $row[$i++]; #ID_RTF since v.1.8 but just RTF from v.2.1
my $am = $row[$i++]; #LOG.AMOUNT
my $af = $row[$i++]; #AFLAG -> Asset as 0, Income as 1, Expense as 2
my $sticky = $row[$i++]; #Sticky to top
#Apostroph's need to be replaced with doubles and white space to be fixed for the SQL.
$log =~ s/'/''/g;
- if ( $edit_mode && $edit_mode != "0" ) {
- #Update
+ if ( $edit_mode && $edit_mode != "0" ) {
$date = DateTime::Format::SQLite->parse_datetime($date); $date =~ s/T/ /g;
- $stm = qq(UPDATE LOG SET ID_CAT='$cat', ID_RTF='$rtf',
+ $stm = qq(UPDATE LOG SET ID_CAT='$cat', RTF='$rtf',
DATE='$date',
LOG='$log',
AMOUNT=$am,
STICKY=$sticky WHERE $SQLID=$edit_mode;);
#
toBuf $stm if $DEBUG;
- #
-
- my $dbUpd = Settings::connectDB($alias, $passw);#@ or LifeLogException->throw("Execute failed [$DBI::errstri]");
+ #
+
traceDBExe($stm);
return;
}
}
if ($dtCur > $dt){$sticky = 1; toBuf $cgi->p("<b>Insert forced to be sticky, it is in the past!</b>");}
$sticky=castToBool($sticky);
- $stm = qq(INSERT INTO LOG (ID_CAT, ID_RTF, DATE, LOG, AMOUNT, AFLAG, STICKY) VALUES ($cat,$rtf,'$date','$log',$am,$af,$sticky););
+ $stm = qq(INSERT INTO LOG (ID_CAT, DATE, LOG, RTF, AMOUNT, AFLAG, STICKY) VALUES ($cat,'$date','$log',$rtf, $am,$af,$sticky););
$st = traceDBExe($stm);
if($sssCDB){
#Allow further new database creation, it is not an login infinite db creation attack.
use v5.10;
use strict;
use warnings;
-use Exception::Class ('SettingsException','LifeLogException');
+use Exception::Class ('SettingsException','LifeLogException','SettingsLimitSizeException');
use Syntax::Keyword::Try;
use CGI;
use CGI::Session '-ip_match';
use DBI;
use experimental qw( switch );
-#This is the default developer release key, replace on istallation. As it is not secure.
+# This is the default developer release key, replace on istallation. As it is not secure.
use constant CIPHER_KEY => '95d7a85ba891da';
+use constant CIPHER_PADDING => 'fe0a2b6a83e81f13a2d76ab104763773310df6b0a01c7cf9807b4b0ce2a02';
# Default VIEW for all pages.
use constant VW_LOG => 'VW_LOG';
# Optional instructional VIEW from config file replacing above default.
}
}
my $try = $tz_map{$TIME_ZONE};
- $try = $tz_map{$to} if(!$try);
+ $try = $tz_map{$to} if(!$try && $to);
if($try){
$TIME_ZONE = $try; #translated to mapped lib. provided zone.
$ret -> set_time_zone($try);
);
CREATE INDEX idx_cat_name ON CAT (NAME);
)}
-sub createLOGStmt {
-if($IS_PG_DB){
+sub createLOGStmt {
+#ID_RTF in v.2.0 and lower is not an id, changed to byte from v.2.1.
+if($IS_PG_DB){
return qq(
CREATE TABLE LOG (
ID INT UNIQUE GENERATED ALWAYS AS IDENTITY,
- ID_CAT INT NOT NULL,
- ID_RTF INTEGER DEFAULT 0,
+ ID_CAT INT NOT NULL,
DATE TIMESTAMP NOT NULL,
LOG VARCHAR ($DBI_LVAR_SZ) NOT NULL,
+ RTF BOOL DEFAULT 0,
AMOUNT money,
- AFLAG INT DEFAULT 0,
+ AFLAG INT DEFAULT 0,
STICKY BOOL DEFAULT FALSE,
PRIMARY KEY(ID)
);)}
return qq(
CREATE TABLE LOG (
- ID_CAT INT NOT NULL,
- ID_RTF INTEGER DEFAULT 0,
+ ID_CAT INT NOT NULL,
DATE DATETIME NOT NULL,
LOG VARCHAR ($DBI_LVAR_SZ) NOT NULL,
+ RTF BYTE DEFAULT 0,
AMOUNT DOUBLE,
- AFLAG INT DEFAULT 0,
+ AFLAG INT DEFAULT 0,
STICKY BOOL DEFAULT 0
);
)}
selectRecords($db,'CREATE TABLE life_log_temp_table AS SELECT * FROM LOG;');
my $CI = 'rowid'; $CI = 'ID' if $IS_PG_DB;
#update notes table with new log id only for reference sake.
- my $st = selectRecords($db, "SELECT $CI, DATE FROM LOG WHERE ID_RTF > 0 ORDER BY DATE;");
+ my $st = selectRecords($db, "SELECT $CI, DATE FROM LOG WHERE RTF > 0 ORDER BY DATE;");
while(my @row =$st->fetchrow_array()) {
my $sql_date = $row[1];
#$sql_date =~ s/T/ /;
$sql_date = DateTime::Format::SQLite->parse_datetime($sql_date);
- $sql = "SELECT $CI, DATE FROM life_log_temp_table WHERE ID_RTF > 0 AND DATE = '".$sql_date."';";
+ $sql = "SELECT $CI, DATE FROM life_log_temp_table WHERE RTF > 0 AND DATE = '".$sql_date."';";
my @new = selectRecords($db, $sql)->fetchrow_array();
if(scalar @new > 0){
try{#can fail here, for various reasons.
if($IS_PG_DB){$db->do('DROP TABLE LOG CASCADE;');}else{$db->do('DROP TABLE LOG;');}
$db->do(&createLOGStmt);
- $db->do('INSERT INTO LOG (ID_CAT, ID_RTF, DATE, LOG, AMOUNT,AFLAG,STICKY)
- SELECT ID_CAT, ID_RTF, DATE, LOG, AMOUNT, AFLAG, STICKY FROM life_log_temp_table ORDER by DATE;');
+ $db->do('INSERT INTO LOG (ID_CAT, DATE, LOG, RTF ,AMOUNT, AFLAG, STICKY)
+ SELECT ID_CAT, DATE, LOG, RTF, AMOUNT, AFLAG, STICKY FROM life_log_temp_table ORDER by DATE;');
$db->do('DROP TABLE life_log_temp_table;');
}
sub selectRecords {
my ($db, $sql) = @_;
if(scalar(@_) < 2){
- SettingsException->throw("ERROR Argument number is wrong->db is:$db\n", show_trace=>$DEBUG);
+ die "Wrong number of arguments, expecting Settings::selectRecords(\$db, \$sql) got Settings::selectRecords('@_').\n";
}
try{
- my $pst = $db->prepare($sql);
- $pst->execute();
- return 0 if(!$pst);
- return $pst;
+ my $pst = $db->prepare($sql);
+ return 0 if(!$pst);
+ $pst->execute();
+ return $pst;
}catch{
- SettingsException->throw(error=>"Database error encountered!\n ERROR->".$@." SQL-> $sql DSN:".$DSN, show_trace=>$DEBUG);
+ SettingsException->throw(error=>"Database error encountered!\n ERROR->$@\n SQL-> $sql DSN:".$DSN, show_trace=>$DEBUG);
};
}
require CNFParser;
+my @set = ('0' ..'9', 'A' .. 'F');
+#@my $str = join '' => map $set[rand @set], 1 .. 56;
+#print join '' => map $set[rand @set], 1 .. 56, "\n\n";
+
+
+print cryptKey('admin','admin'), "\n";
+
+
+#B6B829430583F8C03EBEFB1677232194EEC8D211609226EC516F7BB4B
+sub cryptKey {
+ my $admin = shift;
+ my $passw = shift;
+ $passw = $admin.$passw.Settings->CIPHER_KEY;
+ $passw =~ s/(.)/sprintf '%04x', ord $1/seg;
+ return substr $passw.Settings->CIPHER_PADDING, 0, 58;
+}
+
+
# my $TIME_ZONE_MAP ="";
# open(my $fh, '<',$ENV{'PWD'}.'/dbLifeLog/main.cnf') or LifeLogException->throw("Can't open main.cnf: $!");
# while (my $line = <$fh>) {
# chomp $line;
# if($line =~ /<<TIME_ZONE_MAP</){
-# $TIME_ZONE_MAP = substr($line,16);
+# $TIME_ZONE_MAP = substr($line,16);prin
# while ($line = <$fh>) {
# chomp $line;
# last if($line =~ />$/);
# $where =~ s/\s+AND$//;
# return Settings::createViewLOGStmt(VW_LOG_WITH_EXCLUDES,$where);
# }
-my $server = 'DBI:Pg:host=elite;name=android';
-
-my $v1 = $server =~ qr/:/;
-my $v2 = $`;
-my $v3 = $' =~ qr/:/;
-# $var=1
-# $`=DBI
-# $&=:
-# $'=Pg:host=elite;name=androi
-print $v2.'->'.$`,"\n";
-$v1 ="";
-
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="1";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+1m";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+10minutes";
-print "[$v1]->".timeFormatValue($v1),"\n";
-#default
-$v1 ="+30m";
-print "[$v1]->".timeFormatValue($v1),"\n";
-
-#Let's try sneak in garbage.
-$v1 ="+20bitcons";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+20hitcons";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+30hr";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+1hr";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+8.2severe";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+8severe";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+2severe";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+120severe";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+119severe";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+121severe";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+280severe";
-print "[$v1]->".timeFormatValue($v1),"\n";
-$v1 ="+120";
-print "[$v1]->".timeFormatValue($v1),"\n";
-
-
-sub timeFormatValue {
- my $v = shift;
- my $ret = "+2m";
- if(!$v){$v=$ret}
- if($v !~ /^\+/){$v='+'.$v.'m'}# Must be positive added time
- # Find first match in whatever passed.
- my @a = $v =~ m/(\+\d+[shm])/gis;
- if(scalar(@a)>0){$v=$a[0]}
- # Test acceptable setting, which is any number from 2, having any s,m or h.
- if($v =~ m/(\+[2-9]\d*[smh])|(\+[1-9]+\d+[smh])/){
- # Next is actually, the dry booger in the nose. Let's pick it out!
- # Someone might try to set in seconds value to be under two minutes.
- @a = $v =~ m/(\d[2-9]\d+)/gs;
- if(scalar(@a)>0 && int($a[0])<120){return $ret}else{return $v}
- }
- elsif($v =~ m/\+\d+/){# is passedstill without time unit? Minutetise!
- $ret=$v."m"
- }
- return $ret;
-}
+# my $server = 'DBI:Pg:host=elite;name=android';
+
+# my $v1 = $server =~ qr/:/;
+# my $v2 = $`;
+# my $v3 = $' =~ qr/:/;
+# # $var=1
+# # $`=DBI
+# # $&=:
+# # $'=Pg:host=elite;name=androi
+# print $v2.'->'.$`,"\n";
+# $v1 ="";
+
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="1";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+1m";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+10minutes";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# #default
+# $v1 ="+30m";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+
+# #Let's try sneak in garbage.
+# $v1 ="+20bitcons";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+20hitcons";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+30hr";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+1hr";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+8.2severe";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+8severe";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+2severe";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+120severe";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+119severe";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+121severe";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+280severe";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+# $v1 ="+120";
+# print "[$v1]->".timeFormatValue($v1),"\n";
+
+
+# sub timeFormatValue {
+# my $v = shift;
+# my $ret = "+2m";
+# if(!$v){$v=$ret}
+# if($v !~ /^\+/){$v='+'.$v.'m'}# Must be positive added time
+# # Find first match in whatever passed.
+# my @a = $v =~ m/(\+\d+[shm])/gis;
+# if(scalar(@a)>0){$v=$a[0]}
+# # Test acceptable setting, which is any number from 2, having any s,m or h.
+# if($v =~ m/(\+[2-9]\d*[smh])|(\+[1-9]+\d+[smh])/){
+# # Next is actually, the dry booger in the nose. Let's pick it out!
+# # Someone might try to set in seconds value to be under two minutes.
+# @a = $v =~ m/(\d[2-9]\d+)/gs;
+# if(scalar(@a)>0 && int($a[0])<120){return $ret}else{return $v}
+# }
+# elsif($v =~ m/\+\d+/){# is passedstill without time unit? Minutetise!
+# $ret=$v."m"
+# }
+# return $ret;
+# }
# my @AUTOWORDS = ("searchificould","itworks","funeral","gasbottle","electricitybill","ctwodaysinrow","carrego","cartwonewtires","flashlightout","test","check","tmshsample","new");
# }
# print "\n";
+
+
+
+
+
+
1;
\ No newline at end of file
var css = $("#q-scroll"+id).prop('style');
if(css){css.backgroundColor = json.content.bg}
}
+ display(json.response, 5);
//alert(obj.response);
}