From 788902c69d079b8fddd200247837064946897889 Mon Sep 17 00:00:00 2001 From: TLINDEN Date: Fri, 10 Feb 2012 20:22:14 +0100 Subject: [PATCH] - --- README | 4 +- VERSION | 2 +- bin/note | 59 +- binary-db/README | 4 - binary-db/note | 1317 ---------------- config/noterc | 14 +- mysql-db/note | 1225 --------------- mysql-db/note.mysql | 1246 --------------- note-1.0.7/Changelog | 277 ++++ note-1.0.7/Makefile.PL | 108 ++ note-1.0.7/NOTEDB/README | 7 + note-1.0.7/NOTEDB/binary.pm | 388 +++++ note-1.0.7/NOTEDB/dbm.pm | 261 +++ note-1.0.7/NOTEDB/mysql.pm | 349 ++++ note-1.0.7/README | 517 ++++++ note-1.0.7/UPGRADE | 73 + note-1.0.7/VERSION | 1 + note-1.0.7/bin/note | 1662 ++++++++++++++++++++ note-1.0.7/config/noterc | 148 ++ {mysql-db => note-1.0.7/mysql}/README | 6 +- {mysql-db => note-1.0.7/mysql}/install.sh | 0 {mysql-db => note-1.0.7/mysql}/permissions | 0 {mysql-db => note-1.0.7/mysql}/sql | 0 note-1.0.7/note | 1639 +++++++++++++++++++ note-1.0.7/stresstest.sh | 55 + noterc | 71 - sql | 8 - 27 files changed, 5541 insertions(+), 3900 deletions(-) delete mode 100644 binary-db/README delete mode 100755 binary-db/note delete mode 100755 mysql-db/note delete mode 100755 mysql-db/note.mysql create mode 100644 note-1.0.7/Changelog create mode 100644 note-1.0.7/Makefile.PL create mode 100644 note-1.0.7/NOTEDB/README create mode 100644 note-1.0.7/NOTEDB/binary.pm create mode 100644 note-1.0.7/NOTEDB/dbm.pm create mode 100644 note-1.0.7/NOTEDB/mysql.pm create mode 100644 note-1.0.7/README create mode 100644 note-1.0.7/UPGRADE create mode 100644 note-1.0.7/VERSION create mode 100755 note-1.0.7/bin/note create mode 100644 note-1.0.7/config/noterc rename {mysql-db => note-1.0.7/mysql}/README (93%) rename {mysql-db => note-1.0.7/mysql}/install.sh (100%) rename {mysql-db => note-1.0.7/mysql}/permissions (100%) rename {mysql-db => note-1.0.7/mysql}/sql (100%) create mode 100755 note-1.0.7/note create mode 100755 note-1.0.7/stresstest.sh delete mode 100644 noterc delete mode 100644 sql diff --git a/README b/README index 06a62fb..781316c 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -note 1.0.7 by Thomas Linden, 27/06/2000 +note 1.0.8 by Thomas Linden, 11/07/2000 ======================================= Introduction @@ -514,4 +514,4 @@ Contributors / Credits Last changed ============ - 27/06/2000 + 11/07/2000 diff --git a/VERSION b/VERSION index af0b7dd..b0f3d96 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.6 +1.0.8 diff --git a/bin/note b/bin/note index 1c2e56a..de90eb6 100755 --- a/bin/note +++ b/bin/note @@ -1,5 +1,5 @@ #!/usr/bin/perl -# $Id: note,v 1.29 2000/06/25 20:13:23 scip Exp scip $ +# $Id: note,v 1.2 2000/07/09 22:10:03 zarahg Exp $ # # # note - console notes management with database and encryption support. @@ -95,7 +95,7 @@ my ( # # internals # - $TYPE, $mode, $NoteKey, + $TYPE, $mode, $NoteKey, $TempDir, $version, $number, $CurTopic, $CurDepth, $WantTopic, $sizeof, %TP, $TreeType, $ListType, $SetTitle, @ArgTopics, $key, $typedef, @NumBlock, $has_nothing, @@ -126,13 +126,13 @@ $TIME_COLOR = "black"; $TOPIC_COLOR = "BLACK"; $TOPIC = 1; $TopicSep = '/'; -$version = "1.0.7"; +$version = "1.0.8"; if($TOPIC) { $CurDepth = 1; # the current depth inside the topic "directory" structure... } $USE_CRYPT = "NO"; - +$TempDir = "/tmp"; @@ -320,12 +320,6 @@ if($DEFAULT_LIST eq "LONG") # *if* loading of the config was successful, try to load the # configured database backend. Currently supported: mysql and binary. push @INC, $libpath; -#if($dbdriver eq "mysql") { -# eval { -# require NOTEDB::mysql; -# $db = new NOTEDB($dbdriver, $dbname, $dbhost, $dbuser, $dbpasswd, $table, $fnum, $fnote, $fdate); -# } -#} if($dbdriver eq "binary") { eval { require NOTEDB::binary; @@ -361,12 +355,8 @@ $_TOPICC = ""; $NoteKey = $TopicSep . "notes" . $TopicSep; - -if($ListType ne "LONG" && $mode ne "interactive") -{ - #$maxlen += $timelen; # no time will be displayed! -} - +# default permissions on new files (tmp) +umask 077; # check if the user wants to use encryption: if($USE_CRYPT eq "YES" && $NOTEDB::crypt_supported == 1) { @@ -640,11 +630,13 @@ sub new $date = &getdate; if($ALWAYS_EDIT eq "YES") { - $TEMP = "/tmp/note.$$"; + $TEMP = &gettemp; # let the user edit it... $editor = &find_editor; if($editor) { + system "touch", $TEMP && die $!; + system "chattr", "+s", $TEMP; # ignore errors, since only on ext2 supported! system $editor, $TEMP; } else @@ -750,10 +742,12 @@ sub edit print "no note with that number found!\n\n"; exit(0) if($mode ne "interactive"); } - $TEMP = "/tmp/note.$USER.$$"; + $TEMP = &gettemp; open NOTE,">$TEMP" or die "Could not open $TEMP\n"; select NOTE; - + + system "chattr", "+s", $TEMP; # ignore errors, like in new() + print $note; close NOTE; select STDOUT; @@ -777,7 +771,7 @@ sub edit chomp $note; close NOTE; - unlink $TEMP; + unlink $TEMP || die $!; if($KEEP_TIMESTAMP eq "YES") { @@ -1387,6 +1381,24 @@ sub getdate } +sub gettemp +{ + my($random, @range); + @range=('0'..'9','a'..'z','A'..'Z'); + srand(time||$$); + for (0..10) { + $random .= $range[rand(int($#range)+1)]; + } + my $tempfile = $TempDir . "/" . $USER . "." . $random; + if (-e $tempfile) { + # avoid race conditions! + unlink $tempfile; + } + return $tempfile; +} + + + sub help { my $B = ""; @@ -1558,6 +1570,7 @@ sub getconfig $TOPIC_COLOR = $value if (/^TopicColor/); $PreferredEditor = $value if (/^PreferredEditor/); $FormatText = $value if (/^FormatText/); + $TempDir = $value if (/^TempDirectory/); } chomp $home; $home =~ s/\/*$//; # cut eventually / at the end @@ -1576,6 +1589,12 @@ sub getconfig __END__ # # $Log: note,v $ +# Revision 1.2 2000/07/09 22:10:03 zarahg +# tempfile management more secure now. new option TempDirectory. thx to Donald. +# +# Revision 1.30 2000/07/09 21:59:48 scip +# secure temp files +# # Revision 1.29 2000/06/25 20:13:23 scip # *** empty log message *** # diff --git a/binary-db/README b/binary-db/README deleted file mode 100644 index b9ed1e5..0000000 --- a/binary-db/README +++ /dev/null @@ -1,4 +0,0 @@ -This is the binary version of note. - -all informations are available in the -main README file! diff --git a/binary-db/note b/binary-db/note deleted file mode 100755 index 3b55e5d..0000000 --- a/binary-db/note +++ /dev/null @@ -1,1317 +0,0 @@ -#!/usr/bin/perl -# -# $Id: note,v 1.9 2000/03/08 23:11:08 tom Exp tom $ $Author: tom $ $Revision: 1.9 $ -# -# $Log: note,v $ -# Revision 1.9 2000/03/08 23:11:08 tom -# added cd -# -# Revision 1.8 2000/03/08 22:49:50 tom -# Added the $KEEP_TIMESTAMP option and fixed a bug regarding topic names -# and invalid resolution of them in case it started with "1 name". -# -# Revision 1.7 2000/02/25 21:00:15 tom -# corrected small timestamp problem in &edit and &new -# -# Revision 1.6 2000/02/25 13:23:25 tom -# fixed a small bug, that caused to use the last line for a note title instead the 2nd. -# -# Revision 1.5 2000/02/25 10:19:58 tom -# help modified about topic sep... -# -# Revision 1.4 2000/02/25 10:13:06 tom -# added $TopicSep -# -# Revision 1.3 2000/02/25 09:46:06 tom -# removed usage of gnu date, use localtime instead -# -# Revision 1.2 2000/02/25 09:24:27 tom -# changed to use strict, seems all still working ;-) -# -# Revision 1.1 2000/02/25 08:23:20 tom -# Initial revision -# -# -# this is the small console program "note" (BINARY version) -# It works similar to some well known GUI note programs, -# but instead of using X11 it uses the UN*X console. -# You can edit existing notes, delete them, create new -# ones and, of course display them. -# The notes will be stored in a binary data file (~/.notedb) -# -# If there exists a configfile called ~/.noterc then it will -# be processed. You can overwrite some default values of note. -# -# If you find it usefull or find a bug, please let me know: -# Thomas Linden - -#use Data::Dumper; - - - -sub usage; -sub find_editor; -sub output; -sub C; -sub uen; -sub ude; -sub num_bereich; -sub getdate; - -sub new; -sub edit; -sub del; -sub display; -sub list; -sub help; -sub import; - -use IO::Seekable; -use strict; - - -my ( - $maxlen, $timelen, $TOPIC, $TYPE, $mode, $NOTEDB, - $version, $number, $CurTopic, $CurDepth, $PATH, $CONF, - $sizeof, $MAX_TIME, $PreferredEditor, %TP, $TopicSep, - $ListType, $searchstring, $dump_file, $ALWAYS_INT, $KEEP_TIMESTAMP, - $BORDERC, $BORDER_COLOR, $_BORDERC, $NOTEC, $NOTE_COLOR, - $NUMC, $NUM_COLOR, $_NUMC, $_NOTEC, $TIMEC, $TIME_COLOR, - $_TIMEC, $TOPICC, $TOPIC_COLOR, $_TOPICC, $SetTitle, $COLOR, - $typedef, $MAX_NOTE, $MAX_TIME, @NumBlock, $ALWAYS_EDIT, $HOME - ); - -################################################# -# define some default values. -# You can change them, but be carefull! -# Instead you can define each of them in a configfile -# called ~/.noterc. -$MAX_NOTE = 1024; -$MAX_TIME = 64; - -$maxlen = 20; -$timelen = 22; -$HOME = `echo \$HOME`; -chomp $HOME; - -$CONF = $HOME . "/.noterc"; - -$NOTEDB = $HOME . "/.notedb"; - -$COLOR = "NO"; -# if $COLOR equals NO, then the following color-definitions -# will be replaced by "". -$BORDER_COLOR = "BLACK"; -$NUM_COLOR = "blue"; -$NOTE_COLOR = "magenta"; -$TIME_COLOR = "black"; -$TOPIC_COLOR = "BLACK"; - -# Turns Topic Support on -$TOPIC = 1; - -# Default topic separator: \ -$TopicSep = '/'; - -$version = "0.7 (binary database)"; - -if($TOPIC) -{ - $CurDepth = 1; # the current depth inside the topic "directory" structure... -} -################################################# - - -# process command line args -if($ARGV[0] eq "") -{ - $mode = "new"; -} -else -{ - while($ARGV[0] ne "" ) - { - if($ARGV[0] =~ /^\d/) - { - # first arg is a digit! - $number = $ARGV[0]; - if($mode eq "") - { - # change mode only, if started with an option - # ($mode will be already set) - $mode = "display"; - } - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-i" || $ARGV[0] eq "--interactive") - { - $mode = "interactive"; - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-l" || $ARGV[0] eq "--list") - { - $mode = "list"; - my @ArgTopics = split /$TopicSep/,$ARGV[1]; - $CurDepth += $#ArgTopics + 1 if $ARGV[1]; - $CurTopic = $ArgTopics[$#ArgTopics]; # use the last element everytime... - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-L" || $ARGV[0] eq "--longlist") - { - $mode = "list"; - $ListType = "LONG"; - $CurTopic = $ARGV[1]; - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-s" || $ARGV[0] eq "--search") - { - # searching - $mode = "search"; - $searchstring = $ARGV[1]; - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-e" || $ARGV[0] eq "--edit") - { - if($mode eq "edit") - { - # note -e -e ! - &usage; - exit(1); - } - else - { - $mode = "edit"; - shift; - } - } - elsif($ARGV[0] eq "-d" || $ARGV[0] eq "--delete") - { - if($mode eq "delete") - { - &usage; - exit(1); - } - else - { - $mode = "delete"; - shift; - } - } - elsif($ARGV[0] eq "-D" || $ARGV[0] eq "--Dump" || $ARGV[0] eq "--dump") - { - $mode = "dump"; - $dump_file = $ARGV[1]; - $ARGV[0] = ""; - if($dump_file eq "") - { - $dump_file = "note.dump.$$"; - print "not dumpfile specified, using $dump_file.\n"; - } - } - elsif($ARGV[0] eq "-I" || $ARGV[0] eq "--Import" || $ARGV[0] eq "--import") - { - $mode = "import"; - $dump_file = $ARGV[1]; - $ARGV[0] = ""; - if($dump_file eq "") - { - print "No dumpfile specified.\n"; - exit(1); - } - } - elsif($ARGV[0] eq "-v" || $ARGV[0] eq "--version") - { - print "This is note $version by Thomas Linden .\n"; - exit(0); - } - elsif($ARGV[0] eq "-h" || $ARGV[0] eq "--help") - { - &usage; - exit(0); - } - else - { - &usage; - exit(0); - } - } -} - -###################### CONFIG ~/.noterc exists? ######################### -# If not, use the predefined Values! -if(-e $CONF) -{ - eval `cat $CONF`; -} - -# Always interactive? -if($ALWAYS_INT eq "YES" && $mode ne "dump" && $mode ne "import") -{ - $mode = "interactive"; -} - - -###################### db exists? ####################################### -# if not, create it! -if(! -e $NOTEDB) -{ - open(TT,">$NOTEDB") or die "Could not create $NOTEDB: $!\n"; - close (TT); -} -elsif(! -w $NOTEDB) -{ - print "$NOTEDB is not writable!\n"; - exit(1); -} - - -# calculate some constants... -$BORDERC = "<$BORDER_COLOR>"; -$_BORDERC = ""; -$NUMC = "<$NUM_COLOR>"; -$_NUMC = ""; -$NOTEC = "<$NOTE_COLOR>"; -$_NOTEC = ""; -$TIMEC = "<$TIME_COLOR>"; -$_TIMEC = ""; -$TOPICC = "<$TOPIC_COLOR>"; -$_TOPICC = ""; - - -$typedef = "i a$MAX_NOTE a$MAX_TIME"; -$sizeof = length pack($typedef, () ); - - -if($ListType ne "LONG" && $mode ne "interactive") -{ - $maxlen += $timelen; # no time will be displayed! -} - - -# main loop: ############### -if($mode eq "display") -{ - &display; -} -elsif($mode eq "search") -{ - &search; -} -elsif($mode eq "list") -{ - &list; -} -elsif($mode eq "new") -{ - &new; -} -elsif($mode eq "delete") -{ - del; -} -elsif($mode eq "edit") -{ - &edit; -} -elsif($mode eq "dump") -{ - &dump; -} -elsif($mode eq "import") -{ - &import; -} -elsif($mode eq "interactive") -{ - &interactive; -} -else -{ - #undefined :-( -} - - -exit(0); -################## EOP ################ - - - -############################### DISPLAY ################################## -sub display -{ - my($N,$address,$buffer,$n,$t,$match,$note,$time,$num); - open (NOTE, "+<$NOTEDB") or die "could not open .notedb\n"; - &num_bereich; # get @NumBlock from $numer - foreach $N (@NumBlock) - { - $address = ($N -1 ) * $sizeof; - seek(NOTE, $address, SEEK_SET); - read(NOTE, $buffer, $sizeof); - ($num, $note, $time) = unpack($typedef, $buffer); - $n = ude($note); - $t = ude($time); - if($num) - { - output($num, $n, $t, "SINGLE"); - print "\n"; - $match = 1; - } - } - close(NOTE); - if(!$match) - { - print "no note with that number found!\n"; - } -} - - -############################### SEARCH ################################## -sub search -{ - my($n,$t,$match,$note,$time,$num,$buffer); - $maxlen += $timelen; - if($searchstring eq "") - { - &usage; - exit(1); - } - print "searching the database $NOTEDB for \"$searchstring\"...\n"; - open (NOTE, "+<$NOTEDB") or die "could not open .notedb\n"; - seek(NOTE, 0, 0); # START FROM BEGINNING - while(read(NOTE, $buffer, $sizeof)) - { - ($num, $note, $time) = unpack($typedef, $buffer); - $n = ude($note); - $t = ude($time); - if($n =~ /$searchstring/i) - { - output($num, $n, $t); - $match = 1; - } - } - if(!$match) - { - print "no matching note found!\n"; - } - close(NOTE); - print "\n"; -} - - -############################### LIST ################################## -sub list -{ - #system("clear") or print "\n\n\n\n"; - my(@topic,@RealTopic, $i,$buffer,$t,$n,$num,$note,$time,@CurItem,$top,$in); - if($mode ne "interactive") - { - print "List of all existing notes:\n\n"; - } - open (NOTE, "+<$NOTEDB") or die "could not open .notedb\n"; - seek(NOTE, 0, 0); # START FROM BEGINNING - if($TOPIC) - { - undef %TP; # the beginning! - } - $i = 0; - while(read(NOTE, $buffer, $sizeof)) - { - ($num, $note, $time) = unpack($typedef, $buffer); - $t = ude($time); - $n = ude($note); - if($TOPIC) - { - # this allows us to have multiple topics (subtopics!) - my ($firstline,$dummy) = split /\n/, $n, 2; - if($firstline =~ /^($TopicSep)/) - { - @topic = split(/$TopicSep/,$firstline); - } - else - { - @topic = (); - } - # looks like: "\topic\" - # collect a list of topics under the current topic - if($topic[$CurDepth-1] eq $CurTopic && $topic[$CurDepth] ne "") - { - if(exists $TP{$topic[$CurDepth]}) - { - $TP{$topic[$CurDepth]}++; - } - else - { - # only if the next item *is* a topic! - $TP{$topic[$CurDepth]} = 1 if(($CurDepth) <= $#topic); - } - } - elsif($topic[$CurDepth-1] eq $CurTopic || ($topic[$CurDepth] eq "" && $CurDepth ==1)) - { - # cut the topic off the note-text - if($n =~ /^($TopicSep)/) - { - $CurItem[$i]->{'note'} = $dummy; - } - else - { - $CurItem[$i]->{'note'} = $n; - } - - # save for later output() call - $CurItem[$i]->{'num'} = $num; - $CurItem[$i]->{'time'} = $t; - $i++; - # use this note for building the $PATH! - if($RealTopic[0] eq "") - { - @RealTopic = @topic; - } - } - } - else - { - output($num, $n, $t); - } - } - if($TOPIC) - { - if($CurTopic ne "") - { - undef $PATH; - foreach (@RealTopic) - { - $PATH .= $_ . $TopicSep; - last if($_ eq $CurTopic); - } - } - else - { - $PATH = $TopicSep; - } - - # we are at top level, print a list of topics... - foreach $top (sort(keys %TP)) - { - output("-", " => ". $top . "$TopicSep ($TP{$top} notes)", - " Sub Topic "); - } - for($in=0;$in<$i;$in++) - { - output( $CurItem[$in]->{'num'}, - $CurItem[$in]->{'note'}, - $CurItem[$in]->{'time'} ); - } - } - close(NOTE); - print "\n"; -} - - -############################### NEW ################################## -sub new -{ - my($time, $TEMP,$editor, $note, $WARN, $c, $line, $num, $te, $me, $buff,$buffer, @topic,$n,$t); - $time = &getdate; - if($ALWAYS_EDIT eq "YES") - { - $TEMP = "/tmp/note.$$"; - # let the user edit it... - $editor = &find_editor; - if($editor) - { - system $editor, $TEMP; - } - else - { - print "Could not find an editor to use!\n"; - exit(0); - } - # read it in ($note) - $note = ""; - #open E, "<$TEMP" or die "Could not open $TEMP\n"; - open E, "<$TEMP" or $WARN = 1; - if($WARN) - { - print "...edit process interupted! No note has been saved.\n"; - undef $WARN; - return; - } - $c = 0; - while() - { - $note = $note . $_; - } - chomp $note; - close E; - # privacy! - system "/bin/rm -f $TEMP"; - } - else - { - $note = ""; - $line = ""; - #local $num = 0; - # create a new note - print "enter the text of the note, end with .\n"; - do - { - $line = ; - $note = $note . $line; - } until $line eq ".\n"; - # remove the . ! - chop $note; - chop $note; - } - open (N, "<$NOTEDB") or die "could not open .notedb\n"; - # since we have not number, look for the next available: - seek(N, 0, 0); # START FROM BEGINNING - while(read(N, $buff, $sizeof)) - { - ($num, $te, $me) = unpack($typedef, $buff); - } - seek(N, 0, 0); - close (N); - $num++; # use the highest plus 1 - - if($TOPIC && $CurTopic ne "") - { - @topic = split(/$TopicSep/,$note); - if($topic[1] eq "") - { - #$note = "\\$CurTopic\\\n$note"; - $note = $PATH . "\n$note"; - } - } - - - open (NOTE, "+<$NOTEDB") or die "could not open .notedb\n"; - seek(NOTE, 0, SEEK_END); # APPEND - $n = uen($note); - $t = uen($time); - $buffer = pack($typedef, $num, $n, $t); - - print NOTE $buffer; - close(NOTE); - print "note stored. it has been assigned the number $num.\n\n"; -} - - -############################### DELETE ################################## -sub del -{ - my($TEMP,$count, $buff, %Merk, $num, $note, $time, $droped, $buffer); - &num_bereich; # get @NumBlock from $number - $TEMP = "/tmp/note.$$"; # save temporarily in $TEMP - system("/bin/touch", $TEMP); - open TEMP, "+<$TEMP" or die "Could not open $TEMP($!)\n"; - open (NOTE, "<$NOTEDB") or die "could not open .notedb\n"; - - seek(TEMP, 0, SEEK_END); # APPEND - - $count = 1; - - # read from notedb and write to temp (without number to - # be deleted, and with recounted numbers) - - foreach (@NumBlock) - { - # define $Merk's for the exists() test later on... - $Merk{$_} = "got"; - } - - while(read(NOTE, $buff, $sizeof)) - { - ($num, $note, $time) = unpack($typedef, $buff); - if(exists $Merk{$num}) - { - # drop it, just ignore the contents. - $droped = 1; - print "note number $num has been deleted.\n"; - } - else - { - # no keep it - $buffer = pack($typedef, $count, $note, $time); - seek(TEMP, 0, SEEK_END); # APPEND - print TEMP $buffer; - $count++; - } - } - - - - - close(TEMP); - close(NOTE); - - # done, inform the user - if($droped eq 1) - { - # copy the new one over the old one - system("/bin/cp",$TEMP, $NOTEDB); - } - else - { - print "no note with that number found!\n"; - } - system "/bin/rm -f $TEMP"; -} - - -############################### EDIT ################################## -sub edit -{ - my($keeptime, $time,$editor, $TEMP, $address, $n, $buff, $c, $note, $t, $buffer, $num); - $time = &getdate; - $address = ($number -1 ) * $sizeof; - open (NOTE, "+<$NOTEDB") or die "could not open .notedb\n"; - seek(NOTE, $address, SEEK_SET); - read(NOTE, $buff, $sizeof) or die "no note with that number found!\n"; - ($num, $note, $t) = unpack($typedef, $buff); - $n = ude($note); - $keeptime = ude($t); - # got current enties... - - # now edit them - $TEMP = "/tmp/note.$$"; - open N, ">$TEMP" or die "Could not open $TEMP\n"; - select N; - print $n; # save decoded to $TEMP - close N; - select STDOUT; - - # let the user edit it... - $editor = &find_editor; - if($editor) - { - system $editor, $TEMP; - } - else - { - print "Could not find an editor to use!\n"; - exit(0); - } - - # read it in ($note) - $note = ""; - open N, "<$TEMP" or die "Could not open $TEMP\n"; - $c = 0; - while() - { - $note = $note . $_; - } - chomp $note; - close N; - - # privacy! - system "/bin/rm -f $TEMP"; - - # we got it, now save to db - seek(NOTE, $address, SEEK_SET); - $n = ""; - $n = uen($note); - if($KEEP_TIMESTAMP eq "YES") - { - $t = uen($keeptime); - } - else - { - $t = uen($time); - } - $buffer = pack($typedef, $number, $n, $t); - print NOTE $buffer; - close(NOTE); - print "note number $number has been changed.\n"; -} - - -sub dump -{ - my($buffer,$num, $note, $time,$n, $t); - # $dump_file - open (DUMP, ">$dump_file") or die "could not open $dump_file\n"; - select DUMP; - open (NOTE, "+<$NOTEDB") or die "could not open .notedb\n"; - seek(NOTE, 0, 0); # START FROM BEGINNING - while(read(NOTE, $buffer, $sizeof)) - { - ($num, $note, $time) = unpack($typedef, $buffer); - $n = ude($note); - $t = ude($time); - print STDOUT "dumping note number $num to $dump_file\n"; - print "Number: $num\nTimestamp: $t\n$n\n"; - } - close(NOTE); - print "\n"; - close(DUMP); - select STDOUT; -} - -sub import -{ - my($buff, $num,$te, $me, $start, $complete, $dummi, $n, $t, $buffer, $note, $time, $date); - open (N, "<$NOTEDB") or die "could not open .notedb\n"; - # since we have not number, look for the next available: - seek(N, 0, 0); # START FROM BEGINNING - while(read(N, $buff, $sizeof)) - { - ($num, $te, $me) = unpack($typedef, $buff); - } - seek(N, 0, 0); - close (N); - $num++; # use the highest plus 1 - - # open $dump_file and import it into the notedb - open (DUMP, "<$dump_file") or die "could not open $dump_file\n"; - $complete=0; - $start = 0; - open (NOTE, "+<$NOTEDB") or die "could not open .notedb\n"; - while() - { - chomp $_; - if($_ =~ /^Number:\s\d+/) - { - if($start == 0) - { - # we have no previous record - ($dummi,$number) = split(/\s/,$_); - $start = 1; - } - else - { - # we got a complete record, save it! - - seek(NOTE, 0, SEEK_END); # APPEND - $n = uen($note); - $t = uen($date); - $buffer = pack($typedef, $num, $n, $t); - print NOTE $buffer; - $num++; - - print "note number $number from $dump_file inserted into notedb.\n"; - $complete = 0; # restet $complete - $note = ""; # reset $note - $date = ""; # reset $date - ($dummi,$number) = split(/\s/,$_); - } - } - elsif($_ =~ /^Timestamp:\s\d+/ && $complete == 0) - { - ($dummi,$date,$time) = split(/\s/,$_); - $date = "$date $time"; - $complete = 1; - } - else - { - $note .= $_ . "\n"; - } - } - if($note ne "" && $date ne "") - { - # the last record, if existent - seek(NOTE, 0, SEEK_END); # APPEND - $n = uen($note); - $t = uen($date); - $buffer = pack($typedef, $num, $n, $t); - print NOTE $buffer; - print "note number $number from $dump_file inserted into notedb.\n"; - close(NOTE); - } -} - - - - - - -sub interactive -{ - my($maxlen_save, $B, $BB, $menu, $time, $char, @LastTopic); - $maxlen_save = $maxlen; - # create menu: - $B = ""; - $BB = ""; - $menu = "[" . $B . "L" . $BB . " List " - . $B . "N" . $BB . " New " - . $B . "D" . $BB . " Delete " - . $B . "S" . $BB . " Search " - . $B . "E" . $BB . " Edit " - . $B . "?" . $BB . " Help " - . $B . "Q" . $BB . " Quit] "; # $CurTopic will be empty if $TOPIC is off! - # Initially do a list command! - $maxlen += $timelen; - print "\n"; - &list; - undef $SetTitle; - # per default let's list all the stuff: - for(;;) - { - # reset time - $ListType = ""; - $maxlen = $maxlen_save; - if($CurDepth > 2) - { - print C $menu . $TOPICC . "../" . $CurTopic . $_TOPICC . ">"; - } - else - { - print C $menu . $TOPICC . $CurTopic . $_TOPICC . ">"; - } - # endless until user press "Q" or "q"! - $char = ; - chomp $char; - if($char =~ /^\d+$/) - { - # display notes - $maxlen += $timelen; - $number = $char; - &display; - undef $SetTitle; - } - elsif($char =~ /^n$/i) - { - # create a new one - &new; - } - elsif($char =~ /^l$/ || $char =~ /^$/) - { - # list - print "\n"; - $ListType = ""; - $maxlen += $timelen; - &list; - undef $SetTitle; - } - elsif($char =~ /^L$/) - { - $ListType = "LONG"; - print "\n"; - &list; - undef $SetTitle; - } - elsif($char =~ /^h$/i || $char =~ /^\?/) - { - # zu dumm der Mensch ;-) - &help; - } - elsif($char =~ /^d\s+(\d+\-*\,*\d*)/i) - { - # delete one! - $number = $1; - &del; - } - elsif($char =~ /^d$/i) - { - # we have to ask her: - print "enter number(s) of note(s) you want to delete: "; - $char = ; - chomp $char; - $number = $char; - &del; - } - elsif($char =~ /^e\s+(\d+\-*\,*\d*)/i) - { - # edit one! - $number = $1; - &edit; - } - elsif($char =~ /^e$/i) - { - # we have to ask her: - #$maxlen += $timelen; - print "enter number of the note you want to edit: "; - $char = ; - chomp $char; - $number = $char; - &edit; - } - elsif($char =~ /^s\s+/i) - { - # she want's to search - $searchstring = $'; - chomp $searchstring; - &search; - } - elsif($char =~ /^s$/i) - { - # we have to ask her: - print "enter the string you want to search for: "; - $char = ; - chomp $char; - $char =~ s/^\n//; - $searchstring = $char; - &search; - } - elsif($char =~ /^q$/i) - { - # schade!!! - print "\n\ngood bye\n"; - exit(0); - } - elsif($char =~ /^\.\.$/ || $char =~ /^cd\s*\.\.$/) - { - $CurDepth-- if ($CurDepth > 1); - $CurTopic = $LastTopic[$CurDepth]; - $maxlen += $timelen; - print "\n"; - &list; - undef $SetTitle; - } - else - { - # unknown - my $unchar = $char; - $unchar =~ s/^cd //; # you may use cd now! - if(exists $TP{$char} || exists $TP{$unchar}) - { - $char = $unchar if(exists $TP{$unchar}); - $LastTopic[$CurDepth] = $CurTopic; - $CurTopic = $char; - $maxlen += $timelen; - $CurDepth++; - print "\n"; - &list; - undef $SetTitle; - } - else - { - print "\nunknown command!\n"; - } - undef $unchar; - } - } -} - - - -sub usage -{ -print qq~This is the program note $version by Thomas Linden (c) 1999-2000. -It comes with absolutely NO WARRANTY. It is distributed under the -terms of the GNU General Public License. Use it at your own risk :-) -Usage: note [-i | --interactive] | [ options ] [ number [,number...]] -Options: - -h --help displays this help screen - -v --version displays the version number - -l --list [] lists all existing notes. If no topic were specified, - it will display a list of all existing topics. - -L --longlist [] the same as -l but prints also the timestamp - -s --search searches for trough the notes database - -e --edit edit note with - -d --delete delete note with - -D --Dump [] dumps the notes to the textfile - -I --Import imports a previously dumped textfile into the - note-database. Dumps from the mysql and the binary - version are in the same format. - -i --interactive interactive mode - - o if you specify only a number (i.e. "note 4"), then the note with that - number will be displayed. - o you can specify more then one number for delete and display, for example: - "note -d 3,4" deletes #3 and #4. "note 5-7" displays #5, #6 and #7. - o if you run note without any parameter and if \$ALWAYS_INT in the config is - not set, then note will create a new note and prompt you for new text. - o If it finds \~/.noterc, it will process it. Refer to the manpage for more - informations about the configuration. - o In interactive mode you can get help at any time by typing "?" or "h" at - the prompt. -~; - exit 1; -} -sub find_editor { - return $PreferredEditor || $ENV{"VISUAL"} || $ENV{"EDITOR"} || "vim" || "vi" || "pico"; -} - -#/ - -sub output -{ - my($SSS, $LINE, $num, $note, $time, $TYPE, $L, $LONGSPC, $R, $PathLen, $SP, $title, $CUTSPACE, - $len, $diff, $Space); - # 0 = Num, 1 = Note, 2 = Time - if($ListType ne "LONG") - { - $SSS = "-" x ($maxlen + 31 - $timelen); - } - else - { - $SSS = "-" x ($maxlen + 31); - } - $LINE = "$BORDERC $SSS $_BORDERC\n"; - $num = $_[0]; - $note = $_[1]; - $time = $_[2]; - $TYPE = $_[3]; - $L = $BORDERC . "[" . $_BORDERC; - $LONGSPC = " " x (22 + 3); - $R = $BORDERC . "]" . $_BORDERC; - $PathLen = length($PATH); # will be ZERO, if not in TOPIC mode! - if($TYPE ne "SINGLE") - { - if(!$SetTitle) - { - $SP = ""; - # print only if it is the first line! - if($ListType ne "LONG") - { - $SP = " " x ($maxlen-2 - $timelen - $PathLen); - } - else - { - $SP = " " x ($maxlen-2 - $PathLen); - } - print C $LINE; - - print C "$L $NUMC#$_NUMC "; - if($ListType eq "LONG") - { - print C " $TIMEC" . "creation date$_TIMEC "; - } - else - { - print $LONGSPC; - } - if($TOPIC) - { - print C $TOPICC . "$PATH $_TOPICC$SP$R\n"; - } - else - { - print C $NOTEC . "note$_NOTEC$SP$R\n"; - } - - print C $LINE; - $SetTitle = 1; - } - $title = ""; - $CUTSPACE = " " x $maxlen; - $note =~ s/\n/$CUTSPACE/g; - $len = length($note); - if($len < $maxlen-3) - { - $diff = $maxlen - $len; - $Space = " " x $diff; - if($num eq "-") - { - $title = $BORDERC . $TOPICC . "\"" . $note . "\"" . $_TOPICC . $Space . "$_BORDERC"; - } - else - { - $title = $BORDERC . $NOTEC . "\"" . $note . "\"" . $_NOTEC . $Space . "$_BORDERC"; - } - } - else - { - $title = substr($note,0,$maxlen - 3); - if($num eq "-") - { - $title = $BORDERC . $TOPICC . "\"" . $title . "...\"$_TOPICC$_BORDERC"; - } - else - { - $title = $BORDERC . $NOTEC . "\"" . $title . "...\"$_NOTEC$_BORDERC"; - } - } - # $title should now look as: "A sample note " - print C "$L $NUMC$num$_NUMC $R"; - if($ListType eq "LONG") - { - print C "$L$TIMEC" . $time . " $_TIMEC$R"; - } - print C "$L $NOTEC" . $title . "$_NOTEC $R\n"; - - - print C $LINE; - } - else - { - chomp $note; - $Space = " " x ($maxlen - 16); - $SP = " " x ($maxlen + 13); - #print C $LINE; - #print C "$L $NUMC#$_NUMC " . $TIMEC . "creation date$_TIMEC$SP$R\n"; - print C $LINE; - print C "$L $NUMC$num$_NUMC $R$L$TIMEC$time$_TIMEC $Space$R\n"; - print C $LINE; - print C $NOTEC . $note . $_NOTEC . "\n"; - print C $LINE; - } - -} - - - -sub C -{ - my(%Color, $default, $S, $Col, $NC, $T); - # \033[1m%30s\033[0m - %Color = ( 'black' => '0;30', - 'red' => '0;31', - 'green' => '0;32', - 'yellow' => '0;33', - 'blue' => '0;34', - 'magenta' => '0;35', - 'cyan' => '0;36', - 'white' => '0;37', - 'B' => '1;30', - 'BLACK' => '1;30', - 'RED' => '1;31', - 'GREEN' => '1;32', - 'YELLOW' => '1;33', - 'BLUE' => '1;34', - 'MAGENTA' => '1;35', - 'CYAN' => '1;36', - 'WHITE' => '1;37', - 'black_' => '4;30', - 'red_' => '4;31', - 'green_' => '4;32', - 'yellow_' => '4;33', - 'blue_' => '4;34', - 'magenta_' => '4;35', - 'cyan_' => '4;36', - 'white_' => '4;37', - 'blackI' => '7;30', - 'redI' => '7;31', - 'greenI' => '7;32', - 'yellowI' => '7;33', - 'blueI' => '7;34', - 'magentaI' => '7;35', - 'cyanI' => '7;36', - 'whiteI' => '7;37' - ); - $default = "\033[0m"; - $S = $_[0]; - foreach $Col (%Color) - { - if ($S =~ /<$Col>/g) - { - if($COLOR ne "NO") - { - $NC = "\033[" . $Color{$Col} . "m"; - $S =~ s/<$Col>/$NC/g; - $S =~ s/<\/$Col>/$default/g; - } - else - { - $S =~ s/<$Col>//g; - $S =~ s/<\/$Col>//g; - } - } - } - return $S; -} - - -sub uen -{ - my($T); - $T = pack("u", $_[0]); - chomp $T; - return $T; -} - -sub ude -{ - my($T); - $T = unpack("u", $_[0]); - return $T; -} - -sub num_bereich -{ - # $number is the one we want to delete! - # But does it contain kommas? - my($m,@LR,@Sorted_LR,$i); - if($number =~ /\,/) - { - # accept -d 3,4,7 - @NumBlock = split(/\,/,$number); - } - elsif($number =~ /^\d+\-\d+$/) - { - # accept -d 3-9 - @LR = split(/\-/,$number); - @Sorted_LR = (); - - if($LR[0] > $LR[1]) - { - @Sorted_LR = ($LR[1], $LR[0]); - } - elsif($LR[0] == $LR[1]) - { - # 0 and 1 are the same - @Sorted_LR = ($LR[0], $LR[1]); - } - else - { - @Sorted_LR = ($LR[0], $LR[1]); - } - - for($i=$Sorted_LR[0]; $i<=$Sorted_LR[1]; $i++) - { - # from 3-6 create @NumBlock (3,4,5,6) - $NumBlock[$m] = $i; - $m++; - } - } - else - { - @NumBlock = ($number); - } - -} - - -sub getdate -{ - my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); - $year += 1900; - $mon += 1; - $mon =~ s/^(\d)$/0$1/; - $hour =~ s/^(\d)$/0$1/; - $min =~ s/^(\d)$/0$1/; - $sec =~ s/^(\d)$/0$1/; - $mday =~ s/^(\d)$/0$1/; - return "$mday.$mon.$year $hour:$min:$sec"; -} - -sub help -{ -print qq~ --------------------------------------------------------------- -HELP for interactive note $version - -The following commands are available: -L/l List notes. L=long, with timestamp and l=short without timestamp. - You can also just hit for short list.~; -if($TOPIC) -{ -print qq~ - If a "note" starts with a - instead of a number, then it is a - topic. In the brackets you will se, how many notes exists under - that specific topic. Just type the name of the topic to change - to that, it works, just like using cd on a filesystem (without the - cd command). If you type just "..", you will go to the last topic, - you were before (works like "cd .."). - You can create a new topic by creating a new note, the first line - must be the topic borderd by "$TopicSep", i.e.: "/newtopic/". The default - topic separator is "/". - You can have as many subtopics, as you like, i.e.: "/pc/games/x11/". - If you create a new note without a topic-specification, then it - will be put into the current subtopic.~; -} -print qq~ -N Create a new note. -D Delete a note. You can either hit "d 1" or "d 1-4" or just hit "d". - If you don't specify a number, you will be asked for. -S Search trough the notes database. Usage is similar to Delete, use - a string instead of a number to search for. -E Edit a note. Usage is similar to Delete but you can only edit note - a time. -?/H This help screen. -Q Exit the program. - -All commands except the List command are case insensitive. ---------------------------------------------------------------- -~; -} diff --git a/config/noterc b/config/noterc index b396d70..ee85127 100644 --- a/config/noterc +++ b/config/noterc @@ -1,4 +1,4 @@ -# 1.0.6 -*- sh -*- +# 1.0.8 -*- sh -*- # This is a sample config for the note script # There are useful defaults set in note itself. # @@ -68,7 +68,7 @@ UseEncryption 0 # Specify the encryption protocol. The appropriate perl # module needs to be installed. Possible velues are -# IDEA, DES or BLOWFISH, the default is IDEA. +# IDEA, DES or Blowfish, the default is IDEA. CryptMethod IDEA @@ -143,6 +143,16 @@ TopicColor BLACK # capabily FormatText 1 + +# You might specify your own directory for temporary files. +# note needs to create some temp files during editing of notes. +# You could protect this directory using the command: chmod 700 directory. +# The default is /tmp +TempDirectory /home/you/tmp + + + + # That's all about it for now. # If you still have any questiosn, please feel free to contact # me by email: Thomas Linden diff --git a/mysql-db/note b/mysql-db/note deleted file mode 100755 index 7e4bead..0000000 --- a/mysql-db/note +++ /dev/null @@ -1,1225 +0,0 @@ -#!/usr/bin/perl -# $Author: tom $ $Id: note.mysql,v 1.5 2000/02/25 20:59:30 tom Exp tom $ $Revision: 1.5 $ -# -# $Log: note.mysql,v $ -# Revision 1.5 2000/02/25 20:59:30 tom -# corrected small timestamp problem in &edit and &new -# -# Revision 1.4 2000/02/25 13:24:11 tom -# fixed a small bug, that caused to use the last line for a note title instead the 2nd. -# -# Revision 1.3 2000/02/25 11:28:53 tom -# all changes from bin version applied to sql version -# -# Revision 1.2 2000/02/25 10:30:06 tom -# *** empty log message *** -# -# -# this is the small console program "note" (MYSQL version) -# It works similar to some well known GUI note programs, -# but instead of using X11 it uses the UN*X console. -# You can edit existing notes, delete them, create new -# ones and, of course display them. -# The notes will be stored in a mysql database. Refer to -# the README of the desitribution for details about -# installation. -# It requires a configfile named .noterc in the users home. -# If it does not exist, note will create one for you, which -# you will have to edit. -# -# If you find it usefull or find a bug, please let me know: -# Thomas Linden -# -# note is GPL software. - -use Mysql; -use strict; -use Data::Dumper; - -sub usage; -sub find_editor; -sub output; -sub C; -sub uen; -sub ude; -sub num_bereich; -sub getdate; - -sub new; -sub edit; -sub del; -sub display; -sub list; -sub help; -sub import; - -my ( - $maxlen, $timelen, $TOPIC, $TYPE, $mode, $NOTEDB, - $version, $number, $CurTopic, $CurDepth, $PATH, $CONF, - $sizeof, $MAX_TIME, $PreferredEditor, %TP, $TopicSep, - $ListType, $searchstring, $dump_file, $ALWAYS_INT, - $BORDERC, $BORDER_COLOR, $_BORDERC, $NOTEC, $NOTE_COLOR, - $NUMC, $NUM_COLOR, $_NUMC, $_NOTEC, $TIMEC, $TIME_COLOR, - $_TIMEC, $TOPICC, $TOPIC_COLOR, $_TOPICC, $SetTitle, $COLOR, - $typedef, $MAX_NOTE, $MAX_TIME, @NumBlock, $ALWAYS_EDIT, $HOME, - $db, $dbname, $dbhost, $DEFAULTDBNAME, $dbuser, $USER, $dbpasswd, - $table, $fnum, $fnote, $fdate, $date - ); - -################################## -# define some default values. -# don't change them, instead use the config file! - -$maxlen = 20; -$timelen = 22; - -$date = &getdate; - -$USER = getlogin || getpwuid($<); -chomp $USER; - -$HOME = `echo \$HOME`; -chomp $HOME; - -$CONF = $HOME . "/.noterc"; - -$DEFAULTDBNAME = $USER . "_note"; - -# database settings, override them within the config! -$dbname = "$DEFAULTDBNAME"; -$dbhost = "localhost"; -$dbuser = $USER; -$dbpasswd = ""; -$table = "note"; -$fnum = "number"; -$fnote = "note"; -$fdate = "date"; - - -$COLOR = "NO"; -# if $COLOR equals NO, then the following color-definitions -# will be replaced by "". -$BORDER_COLOR = "BLACK"; -$NUM_COLOR = "blue"; -$NOTE_COLOR = "magenta"; -$TIME_COLOR = "black"; -$TOPIC_COLOR = "BLACK"; - -# Turns Topic Support on -$TOPIC = 1; - -# Default topic separator: \ -$TopicSep = '/'; - -$version = "0.6 (mysql database)"; - -if($TOPIC) -{ - $CurDepth = 1; # the current depth inside the topic "directory" structure... -} -################################### - -# process command line args -if($ARGV[0] eq "") -{ - $mode = "new"; -} -else -{ - while($ARGV[0] ne "" ) - { - if($ARGV[0] =~ /^\d/) - { - # first arg is a digit! - $number = $ARGV[0]; - if($mode eq "") - { - # change mode only, if started with an option - # ($mode will be already set) - $mode = "display"; - } - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-i" || $ARGV[0] eq "--interactive") - { - $mode = "interactive"; - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-l" || $ARGV[0] eq "--list") - { - $mode = "list"; - my @ArgTopics = split /$TopicSep/,$ARGV[1]; - $CurDepth += $#ArgTopics + 1 if $ARGV[1]; - $CurTopic = $ArgTopics[$#ArgTopics]; # use the last element everytime... - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-L" || $ARGV[0] eq "--longlist") - { - $mode = "list"; - $ListType = "LONG"; - $CurTopic = $ARGV[1]; - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-s" || $ARGV[0] eq "--search") - { - # searching - $mode = "search"; - $searchstring = $ARGV[1]; - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-e" || $ARGV[0] eq "--edit") - { - if($mode eq "edit") - { - # note -e -e ! - &usage; - exit(1); - } - else - { - $mode = "edit"; - shift; - } - } - elsif($ARGV[0] eq "-d" || $ARGV[0] eq "--delete") - { - if($mode eq "delete") - { - &usage; - exit(1); - } - else - { - $mode = "delete"; - shift; - } - } - elsif($ARGV[0] eq "-D" || $ARGV[0] eq "--Dump" || $ARGV[0] eq "--dump") - { - $mode = "dump"; - $dump_file = $ARGV[1]; - $ARGV[0] = ""; - if($dump_file eq "") - { - $dump_file = "note.dump.$$"; - print "not dumpfile specified, using $dump_file.\n"; - } - } - elsif($ARGV[0] eq "-I" || $ARGV[0] eq "--Import" || $ARGV[0] eq "--import") - { - $mode = "import"; - $dump_file = $ARGV[1]; - $ARGV[0] = ""; - if($dump_file eq "") - { - print "No dumpfile specified.\n"; - exit(1); - } - } - elsif($ARGV[0] eq "-v" || $ARGV[0] eq "--version") - { - print "This is note $version by Thomas Linden .\n"; - exit(0); - } - elsif($ARGV[0] eq "-h" || $ARGV[0] eq "--help") - { - &usage; - exit(0); - } - else - { - &usage; - exit(0); - } - } -} - -# open the configfile. - - - -if(-e $CONF) -{ - eval `cat $CONF`; -} - - -# Always interactive? -if($ALWAYS_INT eq "YES" && $mode ne "dump" && $mode ne "import") -{ - $mode = "interactive"; -} - - -# calculate some constants... -$BORDERC = "<$BORDER_COLOR>"; -$_BORDERC = ""; -$NUMC = "<$NUM_COLOR>"; -$_NUMC = ""; -$NOTEC = "<$NOTE_COLOR>"; -$_NOTEC = ""; -$TIMEC = "<$TIME_COLOR>"; -$_TIMEC = ""; -$TOPICC = "<$TOPIC_COLOR>"; -$_TOPICC = ""; - - - -if($ListType ne "LONG" && $mode ne "interactive") -{ - $maxlen += $timelen; # no time will be displayed! -} - - - -# ok, if still here, we got it all, now let's connect to the database -$db = Mysql->connect($dbhost,$dbname,$dbuser,$dbpasswd) - or die "ERROR: $Mysql::dberrstr\n"; - - - -# main loop: ############### -if($mode eq "display") -{ - &display; -} -elsif($mode eq "search") -{ - &search; -} -elsif($mode eq "list") -{ - &list; -} -elsif($mode eq "new") -{ - &new; -} -elsif($mode eq "delete") -{ - del; -} -elsif($mode eq "edit") -{ - &edit; -} -elsif($mode eq "dump") -{ - &dump; -} -elsif($mode eq "import") -{ - &import; -} -elsif($mode eq "interactive") -{ - &interactive; -} -else -{ - #undefined :-( -} - - -exit(0); -################## EOP ################ - - - -############################### DISPLAY ################################## -sub display -{ - my($N,$address,$buffer,$n,$t,$match,$note,$time,$num,@row,$res); - # display a certain note - print "\n"; - &num_bereich; # get @NumBlock from $numer - foreach $N (@NumBlock) - { - $res = $db->query("SELECT $fnote,$fdate FROM $table WHERE $fnum = $N") - or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - output($N, $row[0], $row[1], "SINGLE"); - print "\n"; - $match = 1; - } - } - if(!$match) - { - print "no note with that number found!\n"; - } -} -############################### SEARCH ################################## -sub search -{ - my($n,$t,$match,$note,$time,$num,$buffer,@row,$res, $sqlstatement); - $maxlen += $timelen; - if($searchstring eq "") - { - &usage; - exit(1); - } - print "searching the database $dbname for \"$searchstring\"...\n\n"; - - $sqlstatement = "SELECT DISTINCT $fnum,$fnote,$fdate FROM $table WHERE " - . "$fnote LIKE '%$searchstring%'" - . " ORDER BY $fnum"; - - $res = $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - output($row[0], $row[1], $row[2]); - $match = 1; - } - - - if(!$match) - { - print "no matching note found!\n"; - } - print "\n"; -} - - -############################### LIST ################################## -sub list -{ - my(@topic,@RealTopic, $i,$buffer,$t,$n,$num,$note,$time,@CurItem,$top,$in, $res, @row); - if($mode ne "interactive") - { - print "List of all existing notes:\n\n"; - } - - # list all available notes (number and firstline) - $res = $db->query("SELECT $fnum,$fnote,$fdate FROM $table ORDER BY $fnum") - or die "ERROR: $Mysql::dberrstr\n"; - if($TOPIC) - { - undef %TP; - } - - while(@row = $res->fetchrow) - { - #output($row[0], $row[1], $row[2]); - $num = $row[0]; $n = $row[1]; $t = $row[2]; - if($TOPIC) - { - # this allows us to have multiple topics (subtopics!) - my ($firstline,$dummy) = split /\n/, $n, 2; - if($firstline =~ /^($TopicSep)/) - { - @topic = split(/$TopicSep/,$firstline); - } - else - { - @topic = (); - } - # looks like: "\topic\" - # collect a list of topics under the current topic - if($topic[$CurDepth-1] eq $CurTopic && $topic[$CurDepth] ne "") - { - if(exists $TP{$topic[$CurDepth]}) - { - $TP{$topic[$CurDepth]}++; - } - else - { - # only if the next item *is* a topic! - $TP{$topic[$CurDepth]} = 1 if(($CurDepth) <= $#topic); - } - } - elsif($topic[$CurDepth-1] eq $CurTopic || ($topic[$CurDepth] eq "" && $CurDepth ==1)) - { - # cut the topic off the note-text - if($n =~ /^($TopicSep)/) - { - $CurItem[$i]->{'note'} = $dummy; - } - else - { - $CurItem[$i]->{'note'} = $n; - } - # save for later output() call - $CurItem[$i]->{'num'} = $num; - $CurItem[$i]->{'time'} = $t; - $i++; - # use this note for building the $PATH! - if($RealTopic[0] eq "") - { - @RealTopic = @topic; - } - } - } - else - { - output($num, $n, $t); - } - } - if($TOPIC) - { - if($CurTopic ne "") - { - undef $PATH; - foreach (@RealTopic) - { - $PATH .= $_ . $TopicSep; - last if($_ eq $CurTopic); - } - } - else - { - $PATH = $TopicSep; - } - - # we are at top level, print a list of topics... - foreach $top (sort(keys %TP)) - { - output("-", " => ". $top . "$TopicSep ($TP{$top} notes)", - " Sub Topic "); - } - #print Dumper(@CurItem); - for($in=0;$in<$i;$in++) - { - output( $CurItem[$in]->{'num'}, - $CurItem[$in]->{'note'}, - $CurItem[$in]->{'time'} ); - } - } - - print "\n"; -} - -############################### NEW ################################## -sub new -{ - my($TEMP,$editor, $time, $note, $WARN, $c, $line, $num, $te, $me, $buff,$buffer, @topic,$n,$t,$res, @row,$sqlstatement); - $time = &getdate; - if($ALWAYS_EDIT eq "YES") - { - $TEMP = "/tmp/note.$$"; - # let the user edit it... - $editor = &find_editor; - if($editor) - { - system $editor, $TEMP; - } - else - { - print "Could not find an editor to use!\n"; - exit(0); - } - # read it in ($note) - $note = ""; - #open E, "<$TEMP" or die "Could not open $TEMP\n"; - open E, "<$TEMP" or $WARN = 1; - if($WARN) - { - print "...edit process interupted! No note has been saved.\n"; - undef $WARN; - return; - } - $c = 0; - while() - { - $_ =~ s/'/`/g; - $note = $note . $_; - } - chomp $note; - close E; - # privacy! - system "/bin/rm -f $TEMP"; - } - else - { - $note = ""; - $line = ""; - #$num = 0; - # create a new note - print "enter the text of the note, end with .\n"; - do - { - $line = ; - $_ =~ s/'/\\'/g; - $note = $note . $line; - } until $line eq ".\n"; - # remove the . ! - chop $note; - chop $note; - } - - # since we have not number, look for the next available: - $res = $db->query("SELECT max($fnum) FROM $table") or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - $number = $row[0]; - } - $number++; - if($TOPIC && $CurTopic ne "") - { - @topic = split(/$TopicSep/,$note); - if($topic[1] eq "") - { - $note = $PATH . "\n$note"; - } - } - - # mask all occuring \'s - $note =~ s/\\/\\\\/g; - - $sqlstatement = "INSERT INTO $table VALUES ($number,'$note','$date')"; - $db->query($sqlstatement) - or die "ERROR: $Mysql::dberrstr\n"; - - # everything ok until here! - print "note stored. it has been assigned the number $number.\n\n"; -} - - -############################### DELETE ################################## -sub del -{ - my($i,@count, $setnum, $buff, %Merk, $num, $note, $pos, $droped, $buffer, $sqlstatement,$res, @row, $ERR); - # delete a note - &num_bereich; # get @NumBlock from $number - - foreach $_ (@NumBlock) - { - $sqlstatement = "DELETE FROM $table WHERE $fnum = $_"; - $res = $db->query($sqlstatement) or $ERR = $Mysql::dberrstr; - # do not exit if an error occurs - good for int mode! - if($ERR) - { - print "no note with number $_ found!\n"; - } - else - { - print "note number $_ has been deleted.\n"; - } - } - # recount the notenumbers: - $i = 0; - $pos = 0; - $sqlstatement = "SELECT $fnum FROM $table ORDER BY $fnum"; - $res = $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - $count[$i] = $row[0]; - $i++; - } - #have all real id's, now recount it: - for($pos=0;$pos<$i;$pos++) - { - $setnum = $pos +1; - $sqlstatement = "UPDATE $table SET $fnum = '$setnum' WHERE $fnum = $count[$pos]"; - $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - } -} - -############################### EDIT ################################## -sub edit -{ - my($time, $editor, $TEMP, $address, $n, $buff, $c, $note, $t, $buffer, $num, $sqlstatement, $res, @row, $match); - # edit a note - $time = &getdate; - $sqlstatement = "SELECT $fnote FROM $table WHERE $fnum = $number"; - $res = $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - $note = $row[0]; - $match = "yes"; - } - if($match eq "") - { - print "no note with that number found!\n\n"; - exit(0); - } - $TEMP = "/tmp/note.$USER.$$"; - open NOTE,">$TEMP" or die "Could not open $TEMP\n"; - select NOTE; - - print $note; - close NOTE; - select STDOUT; - $editor = &find_editor; - if($editor) - { - system $editor, $TEMP; - } - else - { - print "Could not find an editor to use!\n"; - exit(0); - } - $note = ""; - open NOTE,"<$TEMP" or die "Could not open $TEMP\n"; - $c = 0; - while() - { - $_ =~ s/'/`/g; - $note = $note . $_; - } - chomp $note; - close NOTE; - - system "/bin/rm -f $TEMP"; - - # mask all occuring \'s - $note =~ s/\\/\\\\/g; - - # we got it, now save to db - $sqlstatement = "UPDATE $table SET " - . "$fnote = '$note', " - . "$fdate = '$time' " - . "WHERE $fnum = $number"; - $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - - print "note number $number has been changed.\n"; -} - - -sub dump -{ - my($buffer,$num, $note, $time,$n, $t, $res, @row); - # $dump_file - open (DUMP, ">$dump_file") or die "could not open $dump_file\n"; - select DUMP; - $res = $db->query("SELECT $fnum,$fnote,$fdate FROM $table ORDER BY $fnum") - or die "ERROR: $Mysql::dberrstr\n"; - - while(@row = $res->fetchrow) - { - print STDOUT "dumping note number $row[0] to $dump_file\n"; - print "Number: $row[0]\nTimestamp: $row[2]\n$row[1]\n"; - } - - - print "\n"; - close(DUMP); - select STDOUT; -} - -sub import -{ - my($buff, $num,$te, $me, $start, $complete, $dummi, $n, $t, $buffer, $note, $time, $date); - # open $dump_file and import it into the notedb - open (DUMP, "<$dump_file") or die "could not open $dump_file\n"; - $complete=0; - $start = 0; - while() - { - chomp $_; - if($_ =~ /^Number:\s\d+/) - { - if($start == 0) - { - # we have no previous record - ($dummi,$number) = split(/\s/,$_); - $start = 1; - } - else - { - # we got a complete record, save it! - $db->query("INSERT INTO $table VALUES (0,'$note','$date')") - or die "ERROR: $Mysql::dberrstr\n"; - print "note number $number from $dump_file inserted into notedb.\n"; - $complete = 0; # restet $complete - $note = ""; # reset $note - $date = ""; # reset $date - ($dummi,$number) = split(/\s/,$_); - } - } - elsif($_ =~ /^Timestamp:\s\d+/ && $complete == 0) - { - ($dummi,$date,$time) = split(/\s/,$_); - $date = "$date $time"; - $complete = 1; - } - else - { - $note .= $_ . "\n"; - } - } - if($note ne "" && $date ne "") - { - # the last record, if existent - $db->query("INSERT INTO $table VALUES (0,'$note','$date')") - or die "ERROR: $Mysql::dberrstr\n"; - print "note number $number from $dump_file inserted into notedb.\n"; - } -} - - - -sub interactive -{ - my($maxlen_save, $B, $BB, $menu, $char, @LastTopic); - $maxlen_save = $maxlen; - # create menu: - $B = ""; - $BB = ""; - $menu = "[" . $B . "L" . $BB . " List " - . $B . "N" . $BB . " New " - . $B . "D" . $BB . " Delete " - . $B . "S" . $BB . " Search " - . $B . "E" . $BB . " Edit " - . $B . "?" . $BB . " Help " - . $B . "Q" . $BB . " Quit] "; # $CurTopic will be empty if $TOPIC is off! - # per default let's list all the stuff: - # Initially do a list command! - $maxlen += $timelen; - print "\n"; - &list; - undef $SetTitle; - for(;;) - { - $ListType = ""; - $maxlen = $maxlen_save; - if($CurDepth > 2) - { - print C $menu . $TOPICC . "../" . $CurTopic . $_TOPICC . ">"; - } - else - { - print C $menu . $TOPICC . $CurTopic . $_TOPICC . ">"; - } - - # endless until user press "Q" or "q"! - $char = ; - chomp $char; - if($char =~ /^\d+/) - { - # display notes - $maxlen += $timelen; - $number = $char; - &display; - undef $SetTitle; - } - elsif($char =~ /^n$/i) - { - # create a new one - &new; - } - elsif($char =~ /^l$/ || $char =~ /^$/) - { - # list - print "\n"; - $ListType = ""; - $maxlen += $timelen; - &list; - undef $SetTitle; - } - elsif($char =~ /^L$/) - { - $ListType = "LONG"; - print "\n"; - &list; - undef $SetTitle; - } - elsif($char =~ /^h$/i || $char =~ /^\?/) - { - # zu dumm der Mensch ;-) - &help; - } - elsif($char =~ /^d\s+(\d+\-*\,*\d*)/i) - { - # delete one! - $number = $1; - &del; - } - elsif($char =~ /^d$/i) - { - # we have to ask her: - print "enter number(s) of note(s) you want to delete: "; - $char = ; - chomp $char; - $number = $char; - &del; - } - elsif($char =~ /^e\s+(\d+\-*\,*\d*)/i) - { - # edit one! - $number = $1; - &edit; - } - elsif($char =~ /^e$/i) - { - # we have to ask her: - print "enter number of the note you want to edit: "; - $char = ; - chomp $char; - $number = $char; - &edit; - } - elsif($char =~ /^s\s+/i) - { - # she want's to search - $searchstring = $'; - chomp $searchstring; - &search; - } - elsif($char =~ /^s$/i) - { - # we have to ask her: - print "enter the string you want to search for: "; - $char = ; - chomp $char; - $char =~ s/^\n//; - $searchstring = $char; - &search; - } - elsif($char =~ /^q$/i) - { - # schade!!! - print "\n\ngood bye\n"; - exit(0); - } - elsif($char =~ /^\.\.$/) - { - $CurDepth-- if ($CurDepth > 1); - $CurTopic = $LastTopic[$CurDepth]; - $maxlen += $timelen; - print "\n"; - &list; - undef $SetTitle; - } - else - { - # unknown - if(exists $TP{$char}) - { - $LastTopic[$CurDepth] = $CurTopic; - $CurTopic = $char; - $maxlen += $timelen; - $CurDepth++; - print "\n"; - &list; - undef $SetTitle; - } - else - { - print "\nunknown command!\n"; - } - } - } -} - - - -sub usage -{ -print qq~This is the program note $version by Thomas Linden (c) 1999-2000. -It comes with absolutely NO WARRANTY. It is distributed under the -terms of the GNU General Public License. Use it at your own risk :-) -Usage: note [-i | --interactive] | [ options ] [ number [,number...]] -Options: - -h --help displays this help screen - -v --version displays the version number - -l --list [] lists all existing notes If no topic were specified, - it will display a list of all existing topics. - -L --longlist [] the same as -l but prints also the timestamp - -s --search searches for trough the notes database - -e --edit edit note with - -d --delete delete note with - -D --Dump [] dumps the notes to the textfile - -I --Import imports a previously dumped textfile into the - note-database. Dumps from the mysql and the binary - version are in the same format. - -i --interactive interactive mode - - o if you specify only a number (i.e. "note 4"), then the note with that - number will be displayed. - o you can specify more then one number for delete and display, for example: - "note -d 3,4" deletes #3 and #4. "note 5-7" displays #5, #6 and #7. - o if you run note without any parameter and if \$ALWAYS_INT in the config is - not set, then note will create a new note and prompt you for new text. - o If it finds \~/.noterc, it will process it. Refer to the manpage for more - informations about the configuration. - o In interactive mode you can get help at any time by typing "?" or "h" at - the prompt. -~; - exit 1; -} -sub find_editor { - return $PreferredEditor || $ENV{"VISUAL"} || $ENV{"EDITOR"} || "vim" || "vi" || "pico"; -} -#/ -sub output -{ - my($SSS, $LINE, $num, $note, $time, $TYPE, $L, $LONGSPC, $R, $PathLen, $SP, $title, $CUTSPACE, - $len, $diff, $Space); - # 0 = Num, 1 = Note, 2 = Time - if($ListType ne "LONG") - { - $SSS = "-" x ($maxlen + 31 - $timelen); - } - else - { - $SSS = "-" x ($maxlen + 31); - } - $LINE = "$BORDERC $SSS $_BORDERC\n"; - $num = $_[0]; - $note = $_[1]; - $time = $_[2]; - $TYPE = $_[3]; - $L = $BORDERC . "[" . $_BORDERC; - $LONGSPC = " " x (22 + 3); - $R = $BORDERC . "]" . $_BORDERC; - $PathLen = length($PATH); # will be ZERO, if not in TOPIC mode! - if($TYPE ne "SINGLE") - { - if(!$SetTitle) - { - $SP = ""; - # print only if it is the first line! - if($ListType ne "LONG") - { - $SP = " " x ($maxlen-2 - $timelen - $PathLen); - } - else - { - $SP = " " x ($maxlen-2 - $PathLen); - } - print C $LINE; - - print C "$L $NUMC#$_NUMC "; - if($ListType eq "LONG") - { - print C " $TIMEC" . "creation date$_TIMEC "; - } - else - { - print $LONGSPC; - } - if($TOPIC) - { - print C $TOPICC . "$PATH $_TOPICC$SP$R\n"; - } - else - { - print C $NOTEC . "note$_NOTEC$SP$R\n"; - } - - print C $LINE; - $SetTitle = 1; - } - $title = ""; - $CUTSPACE = " " x $maxlen; - $note =~ s/\n/$CUTSPACE/g; - $len = length($note); - if($len < $maxlen-3) - { - $diff = $maxlen - $len; - $Space = " " x $diff; - if($num eq "-") - { - $title = $BORDERC . $TOPICC . "\"" . $note . "\"" . $_TOPICC . $Space . "$_BORDERC"; - } - else - { - $title = $BORDERC . $NOTEC . "\"" . $note . "\"" . $_NOTEC . $Space . "$_BORDERC"; - } - - } - else - { - $title = substr($note,0,$maxlen - 3); - $title = $BORDERC . $NOTEC . "\"" . $title . "...\"$_NOTEC$_BORDERC"; - } - # $title should now look as: "A sample note " - print C "$L $NUMC$num$_NUMC $R"; - if($ListType eq "LONG") - { - print C "$L$TIMEC" . $time . " $_TIMEC$R"; - } - print C "$L $NOTEC" . $title . "$_NOTEC $R\n"; - - - print C $LINE; - } - else - { - chomp $note; - $Space = " " x ($maxlen - 16); - $SP = " " x ($maxlen + 13); - #print C $LINE; - #print C "$L $NUMC#$_NUMC " . $TIMEC . "creation date$_TIMEC$SP$R\n"; - print C $LINE; - print C "$L $NUMC$num$_NUMC $R$L$TIMEC$time$_TIMEC $Space$R\n"; - print C $LINE; - print C $NOTEC . $note . $_NOTEC . "\n"; - print C $LINE; - } - -} - - - -sub C -{ - my(%Color, $default, $S, $Col, $NC, $T); - # \033[1m%30s\033[0m - %Color = ( 'black' => '0;30', - 'red' => '0;31', - 'green' => '0;32', - 'yellow' => '0;33', - 'blue' => '0;34', - 'magenta' => '0;35', - 'cyan' => '0;36', - 'white' => '0;37', - 'B' => '1;30', - 'BLACK' => '1;30', - 'RED' => '1;31', - 'GREEN' => '1;32', - 'YELLOW' => '1;33', - 'BLUE' => '1;34', - 'MAGENTA' => '1;35', - 'CYAN' => '1;36', - 'WHITE' => '1;37', - 'black_' => '4;30', - 'red_' => '4;31', - 'green_' => '4;32', - 'yellow_' => '4;33', - 'blue_' => '4;34', - 'magenta_' => '4;35', - 'cyan_' => '4;36', - 'white_' => '4;37', - 'blackI' => '7;30', - 'redI' => '7;31', - 'greenI' => '7;32', - 'yellowI' => '7;33', - 'blueI' => '7;34', - 'magentaI' => '7;35', - 'cyanI' => '7;36', - 'whiteI' => '7;37' - ); - $default = "\033[0m"; - $S = $_[0]; - foreach $Col (%Color) - { - if ($S =~ /<$Col>/g) - { - if($COLOR ne "NO") - { - $NC = "\033[" . $Color{$Col} . "m"; - $S =~ s/<$Col>/$NC/g; - $S =~ s/<\/$Col>/$default/g; - } - else - { - $S =~ s/<$Col>//g; - $S =~ s/<\/$Col>//g; - } - } - } - return $S; -} - - -sub uen -{ - my($T); - $T = pack("u", $_[0]); - chomp $T; - return $T; -} - -sub ude -{ - my($T); - $T = unpack("u", $_[0]); - return $T; -} - -sub num_bereich -{ - my($m,@LR,@Sorted_LR,$i); - # $number is the one we want to delete! - # But does it contain kommas? - $m = 0; - if($number =~ /\,/) - { - # accept -d 3,4,7 - @NumBlock = split(/\,/,$number); - } - elsif($number =~ /^\d+\-\d+$/) - { - # accept -d 3-9 - @LR = split(/\-/,$number); - @Sorted_LR = (); - - if($LR[0] > $LR[1]) - { - @Sorted_LR = ($LR[1], $LR[0]); - } - elsif($LR[0] == $LR[1]) - { - # 0 and 1 are the same - @Sorted_LR = ($LR[0], $LR[1]); - } - else - { - @Sorted_LR = ($LR[0], $LR[1]); - } - - for($i=$Sorted_LR[0]; $i<=$Sorted_LR[1]; $i++) - { - # from 3-6 create @NumBlock (3,4,5,6) - $NumBlock[$m] = $i; - $m++; - } - } - else - { - @NumBlock = ($number); - } - -} - -sub getdate -{ - my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); - $year += 1900; - $mon += 1; - $mon =~ s/^(\d)$/0$1/; - $hour =~ s/^(\d)$/0$1/; - $min =~ s/^(\d)$/0$1/; - $sec =~ s/^(\d)$/0$1/; - $mday =~ s/^(\d)$/0$1/; - return "$mday.$mon.$year $hour:$min:$sec"; -} - - -sub help -{ -print qq~ --------------------------------------------------------------- -HELP for interactive note $version - -The following commands are available: -L/l List notes. L=long, with timestamp and l=short without timestamp. - You can also just hit for short list. -N Create a new note. -D Delete a note. You can either hit "d 1" or "d 1-4" or just hit "d". - If you don't specify a number, you will be asked for. -S Search trough the notes database. Usage is similar to Delete, use - a string instead of a number to search for. -E Edit a note. Usage is similar to Delete but you can only edit note - a time.~; -if($TOPIC) -{ -print qq~ -T print a list of all existing topics. You can change the actual - topic by simply typing it's name. You can create a new topic by - creating a new note, the first line must be the topic borderd by - backslashes, i.e.: "\\newtopic\\". If you type just ".." instead - of a topic, you will go to the "default" topic, which contains - all notes without a topic.~; -} -print qq~ -?/H This help screen. -Q Exit the program. - -All commands except the List command are case insensitive. ---------------------------------------------------------------- -~; -} diff --git a/mysql-db/note.mysql b/mysql-db/note.mysql deleted file mode 100755 index 928dc32..0000000 --- a/mysql-db/note.mysql +++ /dev/null @@ -1,1246 +0,0 @@ -#!/usr/bin/perl -# $Author: tom $ $Id: note.mysql,v 1.7 2000/03/08 23:11:19 tom Exp tom $ $Revision: 1.7 $ -# -# $Log: note.mysql,v $ -# Revision 1.7 2000/03/08 23:11:19 tom -# added cd -# -# Revision 1.6 2000/03/08 22:50:41 tom -# Added the $KEEP_TIMESTAMP option and fixed a bug regarding topic names -# and invalid resolution of them in case it started with "1 name". -# -# Revision 1.5 2000/02/25 20:59:30 tom -# corrected small timestamp problem in &edit and &new -# -# Revision 1.4 2000/02/25 13:24:11 tom -# fixed a small bug, that caused to use the last line for a note title instead the 2nd. -# -# Revision 1.3 2000/02/25 11:28:53 tom -# all changes from bin version applied to sql version -# -# Revision 1.2 2000/02/25 10:30:06 tom -# *** empty log message *** -# -# -# this is the small console program "note" (MYSQL version) -# It works similar to some well known GUI note programs, -# but instead of using X11 it uses the UN*X console. -# You can edit existing notes, delete them, create new -# ones and, of course display them. -# The notes will be stored in a mysql database. Refer to -# the README of the desitribution for details about -# installation. -# It requires a configfile named .noterc in the users home. -# If it does not exist, note will create one for you, which -# you will have to edit. -# -# If you find it usefull or find a bug, please let me know: -# Thomas Linden -# -# note is GPL software. - -use Mysql; -use strict; -use Data::Dumper; - -sub usage; -sub find_editor; -sub output; -sub C; -sub uen; -sub ude; -sub num_bereich; -sub getdate; - -sub new; -sub edit; -sub del; -sub display; -sub list; -sub help; -sub import; - -my ( - $maxlen, $timelen, $TOPIC, $TYPE, $mode, $NOTEDB, - $version, $number, $CurTopic, $CurDepth, $PATH, $CONF, - $sizeof, $MAX_TIME, $PreferredEditor, %TP, $TopicSep, - $ListType, $searchstring, $dump_file, $ALWAYS_INT, $KEEP_TIMESTAMP, - $BORDERC, $BORDER_COLOR, $_BORDERC, $NOTEC, $NOTE_COLOR, - $NUMC, $NUM_COLOR, $_NUMC, $_NOTEC, $TIMEC, $TIME_COLOR, - $_TIMEC, $TOPICC, $TOPIC_COLOR, $_TOPICC, $SetTitle, $COLOR, - $typedef, $MAX_NOTE, $MAX_TIME, @NumBlock, $ALWAYS_EDIT, $HOME, - $db, $dbname, $dbhost, $DEFAULTDBNAME, $dbuser, $USER, $dbpasswd, - $table, $fnum, $fnote, $fdate, $date - ); - -################################## -# define some default values. -# don't change them, instead use the config file! - -$maxlen = 20; -$timelen = 22; - -$date = &getdate; - -$USER = getlogin || getpwuid($<); -chomp $USER; - -$HOME = `echo \$HOME`; -chomp $HOME; - -$CONF = $HOME . "/.noterc"; - -$DEFAULTDBNAME = $USER . "_note"; - -# database settings, override them within the config! -$dbname = "$DEFAULTDBNAME"; -$dbhost = "localhost"; -$dbuser = $USER; -$dbpasswd = ""; -$table = "note"; -$fnum = "number"; -$fnote = "note"; -$fdate = "date"; - - -$COLOR = "NO"; -# if $COLOR equals NO, then the following color-definitions -# will be replaced by "". -$BORDER_COLOR = "BLACK"; -$NUM_COLOR = "blue"; -$NOTE_COLOR = "magenta"; -$TIME_COLOR = "black"; -$TOPIC_COLOR = "BLACK"; - -# Turns Topic Support on -$TOPIC = 1; - -# Default topic separator: \ -$TopicSep = '/'; - -$version = "0.7 (mysql database)"; - -if($TOPIC) -{ - $CurDepth = 1; # the current depth inside the topic "directory" structure... -} -################################### - -# process command line args -if($ARGV[0] eq "") -{ - $mode = "new"; -} -else -{ - while($ARGV[0] ne "" ) - { - if($ARGV[0] =~ /^\d/) - { - # first arg is a digit! - $number = $ARGV[0]; - if($mode eq "") - { - # change mode only, if started with an option - # ($mode will be already set) - $mode = "display"; - } - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-i" || $ARGV[0] eq "--interactive") - { - $mode = "interactive"; - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-l" || $ARGV[0] eq "--list") - { - $mode = "list"; - my @ArgTopics = split /$TopicSep/,$ARGV[1]; - $CurDepth += $#ArgTopics + 1 if $ARGV[1]; - $CurTopic = $ArgTopics[$#ArgTopics]; # use the last element everytime... - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-L" || $ARGV[0] eq "--longlist") - { - $mode = "list"; - $ListType = "LONG"; - $CurTopic = $ARGV[1]; - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-s" || $ARGV[0] eq "--search") - { - # searching - $mode = "search"; - $searchstring = $ARGV[1]; - $ARGV[0] = ""; - } - elsif($ARGV[0] eq "-e" || $ARGV[0] eq "--edit") - { - if($mode eq "edit") - { - # note -e -e ! - &usage; - exit(1); - } - else - { - $mode = "edit"; - shift; - } - } - elsif($ARGV[0] eq "-d" || $ARGV[0] eq "--delete") - { - if($mode eq "delete") - { - &usage; - exit(1); - } - else - { - $mode = "delete"; - shift; - } - } - elsif($ARGV[0] eq "-D" || $ARGV[0] eq "--Dump" || $ARGV[0] eq "--dump") - { - $mode = "dump"; - $dump_file = $ARGV[1]; - $ARGV[0] = ""; - if($dump_file eq "") - { - $dump_file = "note.dump.$$"; - print "not dumpfile specified, using $dump_file.\n"; - } - } - elsif($ARGV[0] eq "-I" || $ARGV[0] eq "--Import" || $ARGV[0] eq "--import") - { - $mode = "import"; - $dump_file = $ARGV[1]; - $ARGV[0] = ""; - if($dump_file eq "") - { - print "No dumpfile specified.\n"; - exit(1); - } - } - elsif($ARGV[0] eq "-v" || $ARGV[0] eq "--version") - { - print "This is note $version by Thomas Linden .\n"; - exit(0); - } - elsif($ARGV[0] eq "-h" || $ARGV[0] eq "--help") - { - &usage; - exit(0); - } - else - { - &usage; - exit(0); - } - } -} - -# open the configfile. - - - -if(-e $CONF) -{ - eval `cat $CONF`; -} - - -# Always interactive? -if($ALWAYS_INT eq "YES" && $mode ne "dump" && $mode ne "import") -{ - $mode = "interactive"; -} - - -# calculate some constants... -$BORDERC = "<$BORDER_COLOR>"; -$_BORDERC = ""; -$NUMC = "<$NUM_COLOR>"; -$_NUMC = ""; -$NOTEC = "<$NOTE_COLOR>"; -$_NOTEC = ""; -$TIMEC = "<$TIME_COLOR>"; -$_TIMEC = ""; -$TOPICC = "<$TOPIC_COLOR>"; -$_TOPICC = ""; - - - -if($ListType ne "LONG" && $mode ne "interactive") -{ - $maxlen += $timelen; # no time will be displayed! -} - - - -# ok, if still here, we got it all, now let's connect to the database -$db = Mysql->connect($dbhost,$dbname,$dbuser,$dbpasswd) - or die "ERROR: $Mysql::dberrstr\n"; - - - -# main loop: ############### -if($mode eq "display") -{ - &display; -} -elsif($mode eq "search") -{ - &search; -} -elsif($mode eq "list") -{ - &list; -} -elsif($mode eq "new") -{ - &new; -} -elsif($mode eq "delete") -{ - del; -} -elsif($mode eq "edit") -{ - &edit; -} -elsif($mode eq "dump") -{ - &dump; -} -elsif($mode eq "import") -{ - &import; -} -elsif($mode eq "interactive") -{ - &interactive; -} -else -{ - #undefined :-( -} - - -exit(0); -################## EOP ################ - - - -############################### DISPLAY ################################## -sub display -{ - my($N,$address,$buffer,$n,$t,$match,$note,$time,$num,@row,$res); - # display a certain note - print "\n"; - &num_bereich; # get @NumBlock from $numer - foreach $N (@NumBlock) - { - $res = $db->query("SELECT $fnote,$fdate FROM $table WHERE $fnum = $N") - or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - output($N, $row[0], $row[1], "SINGLE"); - print "\n"; - $match = 1; - } - } - if(!$match) - { - print "no note with that number found!\n"; - } -} -############################### SEARCH ################################## -sub search -{ - my($n,$t,$match,$note,$time,$num,$buffer,@row,$res, $sqlstatement); - $maxlen += $timelen; - if($searchstring eq "") - { - &usage; - exit(1); - } - print "searching the database $dbname for \"$searchstring\"...\n\n"; - - $sqlstatement = "SELECT DISTINCT $fnum,$fnote,$fdate FROM $table WHERE " - . "$fnote LIKE '%$searchstring%'" - . " ORDER BY $fnum"; - - $res = $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - output($row[0], $row[1], $row[2]); - $match = 1; - } - - - if(!$match) - { - print "no matching note found!\n"; - } - print "\n"; -} - - -############################### LIST ################################## -sub list -{ - my(@topic,@RealTopic, $i,$buffer,$t,$n,$num,$note,$time,@CurItem,$top,$in, $res, @row); - if($mode ne "interactive") - { - print "List of all existing notes:\n\n"; - } - - # list all available notes (number and firstline) - $res = $db->query("SELECT $fnum,$fnote,$fdate FROM $table ORDER BY $fnum") - or die "ERROR: $Mysql::dberrstr\n"; - if($TOPIC) - { - undef %TP; - } - - while(@row = $res->fetchrow) - { - #output($row[0], $row[1], $row[2]); - $num = $row[0]; $n = $row[1]; $t = $row[2]; - if($TOPIC) - { - # this allows us to have multiple topics (subtopics!) - my ($firstline,$dummy) = split /\n/, $n, 2; - if($firstline =~ /^($TopicSep)/) - { - @topic = split(/$TopicSep/,$firstline); - } - else - { - @topic = (); - } - # looks like: "\topic\" - # collect a list of topics under the current topic - if($topic[$CurDepth-1] eq $CurTopic && $topic[$CurDepth] ne "") - { - if(exists $TP{$topic[$CurDepth]}) - { - $TP{$topic[$CurDepth]}++; - } - else - { - # only if the next item *is* a topic! - $TP{$topic[$CurDepth]} = 1 if(($CurDepth) <= $#topic); - } - } - elsif($topic[$CurDepth-1] eq $CurTopic || ($topic[$CurDepth] eq "" && $CurDepth ==1)) - { - # cut the topic off the note-text - if($n =~ /^($TopicSep)/) - { - $CurItem[$i]->{'note'} = $dummy; - } - else - { - $CurItem[$i]->{'note'} = $n; - } - # save for later output() call - $CurItem[$i]->{'num'} = $num; - $CurItem[$i]->{'time'} = $t; - $i++; - # use this note for building the $PATH! - if($RealTopic[0] eq "") - { - @RealTopic = @topic; - } - } - } - else - { - output($num, $n, $t); - } - } - if($TOPIC) - { - if($CurTopic ne "") - { - undef $PATH; - foreach (@RealTopic) - { - $PATH .= $_ . $TopicSep; - last if($_ eq $CurTopic); - } - } - else - { - $PATH = $TopicSep; - } - - # we are at top level, print a list of topics... - foreach $top (sort(keys %TP)) - { - output("-", " => ". $top . "$TopicSep ($TP{$top} notes)", - " Sub Topic "); - } - #print Dumper(@CurItem); - for($in=0;$in<$i;$in++) - { - output( $CurItem[$in]->{'num'}, - $CurItem[$in]->{'note'}, - $CurItem[$in]->{'time'} ); - } - } - - print "\n"; -} - -############################### NEW ################################## -sub new -{ - my($TEMP,$editor, $time, $note, $WARN, $c, $line, $num, $te, $me, $buff,$buffer, @topic,$n,$t,$res, @row,$sqlstatement); - $time = &getdate; - if($ALWAYS_EDIT eq "YES") - { - $TEMP = "/tmp/note.$$"; - # let the user edit it... - $editor = &find_editor; - if($editor) - { - system $editor, $TEMP; - } - else - { - print "Could not find an editor to use!\n"; - exit(0); - } - # read it in ($note) - $note = ""; - #open E, "<$TEMP" or die "Could not open $TEMP\n"; - open E, "<$TEMP" or $WARN = 1; - if($WARN) - { - print "...edit process interupted! No note has been saved.\n"; - undef $WARN; - return; - } - $c = 0; - while() - { - $_ =~ s/'/`/g; - $note = $note . $_; - } - chomp $note; - close E; - # privacy! - system "/bin/rm -f $TEMP"; - } - else - { - $note = ""; - $line = ""; - #$num = 0; - # create a new note - print "enter the text of the note, end with .\n"; - do - { - $line = ; - $_ =~ s/'/\\'/g; - $note = $note . $line; - } until $line eq ".\n"; - # remove the . ! - chop $note; - chop $note; - } - - # since we have not number, look for the next available: - $res = $db->query("SELECT max($fnum) FROM $table") or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - $number = $row[0]; - } - $number++; - if($TOPIC && $CurTopic ne "") - { - @topic = split(/$TopicSep/,$note); - if($topic[1] eq "") - { - $note = $PATH . "\n$note"; - } - } - - # mask all occuring \'s - $note =~ s/\\/\\\\/g; - - $sqlstatement = "INSERT INTO $table VALUES ($number,'$note','$date')"; - $db->query($sqlstatement) - or die "ERROR: $Mysql::dberrstr\n"; - - # everything ok until here! - print "note stored. it has been assigned the number $number.\n\n"; -} - - -############################### DELETE ################################## -sub del -{ - my($i,@count, $setnum, $buff, %Merk, $num, $note, $pos, $droped, $buffer, $sqlstatement,$res, @row, $ERR); - # delete a note - &num_bereich; # get @NumBlock from $number - - foreach $_ (@NumBlock) - { - $sqlstatement = "DELETE FROM $table WHERE $fnum = $_"; - $res = $db->query($sqlstatement) or $ERR = $Mysql::dberrstr; - # do not exit if an error occurs - good for int mode! - if($ERR) - { - print "no note with number $_ found!\n"; - } - else - { - print "note number $_ has been deleted.\n"; - } - } - # recount the notenumbers: - $i = 0; - $pos = 0; - $sqlstatement = "SELECT $fnum FROM $table ORDER BY $fnum"; - $res = $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - $count[$i] = $row[0]; - $i++; - } - #have all real id's, now recount it: - for($pos=0;$pos<$i;$pos++) - { - $setnum = $pos +1; - $sqlstatement = "UPDATE $table SET $fnum = '$setnum' WHERE $fnum = $count[$pos]"; - $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - } -} - -############################### EDIT ################################## -sub edit -{ - my($keeptime, $time, $editor, $TEMP, $address, $n, $buff, $c, $note, $t, $buffer, $num, $sqlstatement, $res, @row, $match); - # edit a note - $time = &getdate; - $sqlstatement = "SELECT $fnote, $fdate FROM $table WHERE $fnum = $number"; - $res = $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - while(@row = $res->fetchrow) - { - $note = $row[0]; - $keeptime = $row[1]; - $match = "yes"; - } - if($match eq "") - { - print "no note with that number found!\n\n"; - exit(0); - } - $TEMP = "/tmp/note.$USER.$$"; - open NOTE,">$TEMP" or die "Could not open $TEMP\n"; - select NOTE; - - print $note; - close NOTE; - select STDOUT; - $editor = &find_editor; - if($editor) - { - system $editor, $TEMP; - } - else - { - print "Could not find an editor to use!\n"; - exit(0); - } - $note = ""; - open NOTE,"<$TEMP" or die "Could not open $TEMP\n"; - $c = 0; - while() - { - $_ =~ s/'/`/g; - $note = $note . $_; - } - chomp $note; - close NOTE; - - system "/bin/rm -f $TEMP"; - - # mask all occuring \'s - $note =~ s/\\/\\\\/g; - - if($KEEP_TIMESTAMP eq "YES") - { - $t = $keeptime; - } - else - { - $t = $time; - } - - # we got it, now save to db - $sqlstatement = "UPDATE $table SET " - . "$fnote = '$note', " - . "$fdate = '$t' " - . "WHERE $fnum = $number"; - $db->query($sqlstatement) or die "ERROR: $Mysql::dberrstr\n"; - - print "note number $number has been changed.\n"; -} - - -sub dump -{ - my($buffer,$num, $note, $time,$n, $t, $res, @row); - # $dump_file - open (DUMP, ">$dump_file") or die "could not open $dump_file\n"; - select DUMP; - $res = $db->query("SELECT $fnum,$fnote,$fdate FROM $table ORDER BY $fnum") - or die "ERROR: $Mysql::dberrstr\n"; - - while(@row = $res->fetchrow) - { - print STDOUT "dumping note number $row[0] to $dump_file\n"; - print "Number: $row[0]\nTimestamp: $row[2]\n$row[1]\n"; - } - - - print "\n"; - close(DUMP); - select STDOUT; -} - -sub import -{ - my($buff, $num,$te, $me, $start, $complete, $dummi, $n, $t, $buffer, $note, $time, $date); - # open $dump_file and import it into the notedb - open (DUMP, "<$dump_file") or die "could not open $dump_file\n"; - $complete=0; - $start = 0; - while() - { - chomp $_; - if($_ =~ /^Number:\s\d+/) - { - if($start == 0) - { - # we have no previous record - ($dummi,$number) = split(/\s/,$_); - $start = 1; - } - else - { - # we got a complete record, save it! - $db->query("INSERT INTO $table VALUES (0,'$note','$date')") - or die "ERROR: $Mysql::dberrstr\n"; - print "note number $number from $dump_file inserted into notedb.\n"; - $complete = 0; # restet $complete - $note = ""; # reset $note - $date = ""; # reset $date - ($dummi,$number) = split(/\s/,$_); - } - } - elsif($_ =~ /^Timestamp:\s\d+/ && $complete == 0) - { - ($dummi,$date,$time) = split(/\s/,$_); - $date = "$date $time"; - $complete = 1; - } - else - { - $note .= $_ . "\n"; - } - } - if($note ne "" && $date ne "") - { - # the last record, if existent - $db->query("INSERT INTO $table VALUES (0,'$note','$date')") - or die "ERROR: $Mysql::dberrstr\n"; - print "note number $number from $dump_file inserted into notedb.\n"; - } -} - - - -sub interactive -{ - my($maxlen_save, $B, $BB, $menu, $char, @LastTopic); - $maxlen_save = $maxlen; - # create menu: - $B = ""; - $BB = ""; - $menu = "[" . $B . "L" . $BB . " List " - . $B . "N" . $BB . " New " - . $B . "D" . $BB . " Delete " - . $B . "S" . $BB . " Search " - . $B . "E" . $BB . " Edit " - . $B . "?" . $BB . " Help " - . $B . "Q" . $BB . " Quit] "; # $CurTopic will be empty if $TOPIC is off! - # per default let's list all the stuff: - # Initially do a list command! - $maxlen += $timelen; - print "\n"; - &list; - undef $SetTitle; - for(;;) - { - $ListType = ""; - $maxlen = $maxlen_save; - if($CurDepth > 2) - { - print C $menu . $TOPICC . "../" . $CurTopic . $_TOPICC . ">"; - } - else - { - print C $menu . $TOPICC . $CurTopic . $_TOPICC . ">"; - } - - # endless until user press "Q" or "q"! - $char = ; - chomp $char; - if($char =~ /^\d+$/) - { - # display notes - $maxlen += $timelen; - $number = $char; - &display; - undef $SetTitle; - } - elsif($char =~ /^n$/i) - { - # create a new one - &new; - } - elsif($char =~ /^l$/ || $char =~ /^$/) - { - # list - print "\n"; - $ListType = ""; - $maxlen += $timelen; - &list; - undef $SetTitle; - } - elsif($char =~ /^L$/) - { - $ListType = "LONG"; - print "\n"; - &list; - undef $SetTitle; - } - elsif($char =~ /^h$/i || $char =~ /^\?/) - { - # zu dumm der Mensch ;-) - &help; - } - elsif($char =~ /^d\s+(\d+\-*\,*\d*)/i) - { - # delete one! - $number = $1; - &del; - } - elsif($char =~ /^d$/i) - { - # we have to ask her: - print "enter number(s) of note(s) you want to delete: "; - $char = ; - chomp $char; - $number = $char; - &del; - } - elsif($char =~ /^e\s+(\d+\-*\,*\d*)/i) - { - # edit one! - $number = $1; - &edit; - } - elsif($char =~ /^e$/i) - { - # we have to ask her: - print "enter number of the note you want to edit: "; - $char = ; - chomp $char; - $number = $char; - &edit; - } - elsif($char =~ /^s\s+/i) - { - # she want's to search - $searchstring = $'; - chomp $searchstring; - &search; - } - elsif($char =~ /^s$/i) - { - # we have to ask her: - print "enter the string you want to search for: "; - $char = ; - chomp $char; - $char =~ s/^\n//; - $searchstring = $char; - &search; - } - elsif($char =~ /^q$/i) - { - # schade!!! - print "\n\ngood bye\n"; - exit(0); - } - elsif($char =~ /^\.\.$/ || $char =~ /^cd\s*\.\.$/) - { - $CurDepth-- if ($CurDepth > 1); - $CurTopic = $LastTopic[$CurDepth]; - $maxlen += $timelen; - print "\n"; - &list; - undef $SetTitle; - } - else - { - # unknown - my $unchar = $char; - $unchar =~ s/^cd //; # you may use cd now! - if(exists $TP{$char}) - { - $char = $unchar if(exists $TP{$unchar}); - $LastTopic[$CurDepth] = $CurTopic; - $CurTopic = $char; - $maxlen += $timelen; - $CurDepth++; - print "\n"; - &list; - undef $SetTitle; - } - else - { - print "\nunknown command!\n"; - } - undef $unchar; - } - } -} - - - -sub usage -{ -print qq~This is the program note $version by Thomas Linden (c) 1999-2000. -It comes with absolutely NO WARRANTY. It is distributed under the -terms of the GNU General Public License. Use it at your own risk :-) -Usage: note [-i | --interactive] | [ options ] [ number [,number...]] -Options: - -h --help displays this help screen - -v --version displays the version number - -l --list [] lists all existing notes If no topic were specified, - it will display a list of all existing topics. - -L --longlist [] the same as -l but prints also the timestamp - -s --search searches for trough the notes database - -e --edit edit note with - -d --delete delete note with - -D --Dump [] dumps the notes to the textfile - -I --Import imports a previously dumped textfile into the - note-database. Dumps from the mysql and the binary - version are in the same format. - -i --interactive interactive mode - - o if you specify only a number (i.e. "note 4"), then the note with that - number will be displayed. - o you can specify more then one number for delete and display, for example: - "note -d 3,4" deletes #3 and #4. "note 5-7" displays #5, #6 and #7. - o if you run note without any parameter and if \$ALWAYS_INT in the config is - not set, then note will create a new note and prompt you for new text. - o If it finds \~/.noterc, it will process it. Refer to the manpage for more - informations about the configuration. - o In interactive mode you can get help at any time by typing "?" or "h" at - the prompt. -~; - exit 1; -} -sub find_editor { - return $PreferredEditor || $ENV{"VISUAL"} || $ENV{"EDITOR"} || "vim" || "vi" || "pico"; -} -#/ -sub output -{ - my($SSS, $LINE, $num, $note, $time, $TYPE, $L, $LONGSPC, $R, $PathLen, $SP, $title, $CUTSPACE, - $len, $diff, $Space); - # 0 = Num, 1 = Note, 2 = Time - if($ListType ne "LONG") - { - $SSS = "-" x ($maxlen + 31 - $timelen); - } - else - { - $SSS = "-" x ($maxlen + 31); - } - $LINE = "$BORDERC $SSS $_BORDERC\n"; - $num = $_[0]; - $note = $_[1]; - $time = $_[2]; - $TYPE = $_[3]; - $L = $BORDERC . "[" . $_BORDERC; - $LONGSPC = " " x (22 + 3); - $R = $BORDERC . "]" . $_BORDERC; - $PathLen = length($PATH); # will be ZERO, if not in TOPIC mode! - if($TYPE ne "SINGLE") - { - if(!$SetTitle) - { - $SP = ""; - # print only if it is the first line! - if($ListType ne "LONG") - { - $SP = " " x ($maxlen-2 - $timelen - $PathLen); - } - else - { - $SP = " " x ($maxlen-2 - $PathLen); - } - print C $LINE; - - print C "$L $NUMC#$_NUMC "; - if($ListType eq "LONG") - { - print C " $TIMEC" . "creation date$_TIMEC "; - } - else - { - print $LONGSPC; - } - if($TOPIC) - { - print C $TOPICC . "$PATH $_TOPICC$SP$R\n"; - } - else - { - print C $NOTEC . "note$_NOTEC$SP$R\n"; - } - - print C $LINE; - $SetTitle = 1; - } - $title = ""; - $CUTSPACE = " " x $maxlen; - $note =~ s/\n/$CUTSPACE/g; - $len = length($note); - if($len < $maxlen-3) - { - $diff = $maxlen - $len; - $Space = " " x $diff; - if($num eq "-") - { - $title = $BORDERC . $TOPICC . "\"" . $note . "\"" . $_TOPICC . $Space . "$_BORDERC"; - } - else - { - $title = $BORDERC . $NOTEC . "\"" . $note . "\"" . $_NOTEC . $Space . "$_BORDERC"; - } - - } - else - { - $title = substr($note,0,$maxlen - 3); - $title = $BORDERC . $NOTEC . "\"" . $title . "...\"$_NOTEC$_BORDERC"; - } - # $title should now look as: "A sample note " - print C "$L $NUMC$num$_NUMC $R"; - if($ListType eq "LONG") - { - print C "$L$TIMEC" . $time . " $_TIMEC$R"; - } - print C "$L $NOTEC" . $title . "$_NOTEC $R\n"; - - - print C $LINE; - } - else - { - chomp $note; - $Space = " " x ($maxlen - 16); - $SP = " " x ($maxlen + 13); - #print C $LINE; - #print C "$L $NUMC#$_NUMC " . $TIMEC . "creation date$_TIMEC$SP$R\n"; - print C $LINE; - print C "$L $NUMC$num$_NUMC $R$L$TIMEC$time$_TIMEC $Space$R\n"; - print C $LINE; - print C $NOTEC . $note . $_NOTEC . "\n"; - print C $LINE; - } - -} - - - -sub C -{ - my(%Color, $default, $S, $Col, $NC, $T); - # \033[1m%30s\033[0m - %Color = ( 'black' => '0;30', - 'red' => '0;31', - 'green' => '0;32', - 'yellow' => '0;33', - 'blue' => '0;34', - 'magenta' => '0;35', - 'cyan' => '0;36', - 'white' => '0;37', - 'B' => '1;30', - 'BLACK' => '1;30', - 'RED' => '1;31', - 'GREEN' => '1;32', - 'YELLOW' => '1;33', - 'BLUE' => '1;34', - 'MAGENTA' => '1;35', - 'CYAN' => '1;36', - 'WHITE' => '1;37', - 'black_' => '4;30', - 'red_' => '4;31', - 'green_' => '4;32', - 'yellow_' => '4;33', - 'blue_' => '4;34', - 'magenta_' => '4;35', - 'cyan_' => '4;36', - 'white_' => '4;37', - 'blackI' => '7;30', - 'redI' => '7;31', - 'greenI' => '7;32', - 'yellowI' => '7;33', - 'blueI' => '7;34', - 'magentaI' => '7;35', - 'cyanI' => '7;36', - 'whiteI' => '7;37' - ); - $default = "\033[0m"; - $S = $_[0]; - foreach $Col (%Color) - { - if ($S =~ /<$Col>/g) - { - if($COLOR ne "NO") - { - $NC = "\033[" . $Color{$Col} . "m"; - $S =~ s/<$Col>/$NC/g; - $S =~ s/<\/$Col>/$default/g; - } - else - { - $S =~ s/<$Col>//g; - $S =~ s/<\/$Col>//g; - } - } - } - return $S; -} - - -sub uen -{ - my($T); - $T = pack("u", $_[0]); - chomp $T; - return $T; -} - -sub ude -{ - my($T); - $T = unpack("u", $_[0]); - return $T; -} - -sub num_bereich -{ - my($m,@LR,@Sorted_LR,$i); - # $number is the one we want to delete! - # But does it contain kommas? - $m = 0; - if($number =~ /\,/) - { - # accept -d 3,4,7 - @NumBlock = split(/\,/,$number); - } - elsif($number =~ /^\d+\-\d+$/) - { - # accept -d 3-9 - @LR = split(/\-/,$number); - @Sorted_LR = (); - - if($LR[0] > $LR[1]) - { - @Sorted_LR = ($LR[1], $LR[0]); - } - elsif($LR[0] == $LR[1]) - { - # 0 and 1 are the same - @Sorted_LR = ($LR[0], $LR[1]); - } - else - { - @Sorted_LR = ($LR[0], $LR[1]); - } - - for($i=$Sorted_LR[0]; $i<=$Sorted_LR[1]; $i++) - { - # from 3-6 create @NumBlock (3,4,5,6) - $NumBlock[$m] = $i; - $m++; - } - } - else - { - @NumBlock = ($number); - } - -} - -sub getdate -{ - my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); - $year += 1900; - $mon += 1; - $mon =~ s/^(\d)$/0$1/; - $hour =~ s/^(\d)$/0$1/; - $min =~ s/^(\d)$/0$1/; - $sec =~ s/^(\d)$/0$1/; - $mday =~ s/^(\d)$/0$1/; - return "$mday.$mon.$year $hour:$min:$sec"; -} - - -sub help -{ -print qq~ --------------------------------------------------------------- -HELP for interactive note $version - -The following commands are available: -L/l List notes. L=long, with timestamp and l=short without timestamp. - You can also just hit for short list. -N Create a new note. -D Delete a note. You can either hit "d 1" or "d 1-4" or just hit "d". - If you don't specify a number, you will be asked for. -S Search trough the notes database. Usage is similar to Delete, use - a string instead of a number to search for. -E Edit a note. Usage is similar to Delete but you can only edit note - a time.~; -if($TOPIC) -{ -print qq~ -T print a list of all existing topics. You can change the actual - topic by simply typing it's name. You can create a new topic by - creating a new note, the first line must be the topic borderd by - backslashes, i.e.: "\\newtopic\\". If you type just ".." instead - of a topic, you will go to the "default" topic, which contains - all notes without a topic.~; -} -print qq~ -?/H This help screen. -Q Exit the program. - -All commands except the List command are case insensitive. ---------------------------------------------------------------- -~; -} diff --git a/note-1.0.7/Changelog b/note-1.0.7/Changelog new file mode 100644 index 0000000..abc280d --- /dev/null +++ b/note-1.0.7/Changelog @@ -0,0 +1,277 @@ +================================================================================== + +1.0.7: +FIXED: there was a bug in the search expression, use now \Q and \E. +ADDED: --config allows one to use another config than the default. + +================================================================================== + +1.0.6: +FIXED: there were some odd bugs in commandline parsing, some options were unavailable. +FIXED: Forgot "PreferredEditor" config-option in the new config format. +FIXED: the interactive "cd .." command has ignored the presence of a + "DefaultLong" setting(and search too)... thx to Peter. +CHANGED: Optimized a little bit the output routine, now it is better to read. +ADDED: sub format and appropriate config-option for text formatting capabilities. +CHANGED: changed getconfig regexp, which allows now also to use Option = Param. +FIXED: was not possible to override config-options, which are set by default to + something. +ADDED: note chacks now, if a database os actually really encrypted and exits with + an error if it s and the user turned off encryption. This protects her from + destroying it's own database .. + +================================================================================== + +1.0.5: +FIXED: the T (and t respectively) printed nothing out since 1.0.3! It does + it now again... +ADDED: a new database backend added, NOTEDB::dbm, which uses DBM files for + storage. +FIXED: &display-tree returns now, if there is no note, otherwise it + would die because of an undefined refernce. +CHANGED: Changed the config file format completely. It is now no more a perl + file, instead it is a simple plain text file which note parses. +CHANGED: Changed the way, note loads it database backend. It uses now the + $dbdriver variable as module-name, which makes it possible easily + to write your own backend without the need to change note itself. +FIXED: Removed Getopt::Long option "bundling", causes errors with perl + 5.6.0 and is not senceful. +FIXED: Added the Getopt::Long option "no_ignore_case". In 1.0.4 options + were case insensitive causing -i to be interpreted as --import + instead of --interactive ;-((( +ADDED: a new config option $DEFAULT_LIST, which causes note, \ + if turned to "LONG", to use long-listing as default. | + But it will still be able to use short-listing if you | + explicit specify that. | submitted by +FIXED: sub search prints now an appropriate error-message in |==> Peter Palmreuther + case no searchstring was given instead of jumping to | thanks a lot! + usage. | +CHANGED: Changed the text in the interactive help to reflect | + changes of verion 1.0.3 (t and T). / + +================================================================================== + +1.0.4: +CHANGED: Moved from @ARGV-parsing to Getopt::Long, adding options is now + much easier and I do now understand my own code ;-) +ADDED: --raw, the "Raw Mode", which turns off any formatting of output. + +================================================================================== + +1.0.3: +ADDED: "-" works also for --dump, but in the other direction. It causes + note to dump to standard output instead into a file. +ADDED: you can specify - as filename for use with --import and if you want + to create a new note. "-" stands for standardinput and it allows you + tp pipe another commands output to note! +ADDED: you can now use an environment variable for the passphrase (when using + encryption). If it is presen, note will not ask for a passphrase. This + is very usefull in comination with the addition above, for use in + scripts. +CHANGED: the interactive help screen is now coloured. +ADDED: -o commandline switch, which causes note to overwrite an existing + database when importing data from a previous dump. Very handy if + you want to re-initialize your db, i.e. if you changed the format. +ADDED: the long-tree-view (-T) displays now also the note-number of each + note. + +================================================================================== + +1.0.2: +ADDED: Topic-Tree overview command (-t or -T). +ADDED: Enhanced list command in interactive mode, you can now specify + a topic which notes you want to see. +CHANGED: updated the help and usage sections to reflect the additions above. + +================================================================================== + +1.0.1: +FIXED: fixed bug in NOTEDB::mysql, which caused note t store NULL values + in db, if encryption was off. A really dump failure :-( + +================================================================================== + +1.0.0: +CHANGED: removed install.sh. use now a Makefile for installation. +ADDED: Encryption support. Note can now encrypt notes using IDEA + or DES as encryption-protocols(symetric). + +================================================================================== + +0.9: +FIXED: There were many new bugs after my last changes *grrrrr*. fixed. + Works now properly, with both backends! +FIXED: and another bug: recounting of numbers did not take care about + the existing order! If you deleted note #12, then note #13 became + not neccessarily #12! Instead it becames any other number (kind of + randomly...). +CHANGED: NOTEDB::binary set_del function changed, it does no more require + a temporary file for number recount. Instead it uses get_all and + stores all notes in RAM and then rewrites the database. +FIXED: fixed the set_new call within note. It used 0 as the first param + (number) which is not useful since we dont have support for auto- + increment from all database backends. +FIXED: fixed the function set_recountnum in NITEDB::mysql, it was also + incorrect :-((( 0.8 seemed to be a very bad early alpha........... +FIXED: there was a bug in NOTEDB::binary which caused not to recount note + numbers after deleting one :-( + + +================================================================================== + +0.8: +ADDED: NOTEDB::binary. so now 0.8 is ready for shipping ! +FIXED: regexp bug fixed. It was only possible to delete 2 items together + separated by comma ("d 1,2,3,4" deleted only 1,2!). +ADDED: Some new config options which reflects the new module structure. + So you can change your database backend without the need to + replace the note script itself. +FIXED: the previously added feature "cd " didn't really work :-( +ADDED: NOTEDB::mysql added. Perlmodule, which I will use within + note from now on instead of buildin functions for accessing the + database. From now on I only need to maintain one version of + note, since the module interface will be identical between the + bin and sql version. +CHANGED: The SQL code does not use Mysql.pm anymore. Instead it is coded + using the more portable DBI module. This allows one easily to + switch to anther database, which is supported by DBI. +CHANGED: Locking. The db-table will now be locked before note accesses it. +FIXED: width of listings is now always the same independent of the string- + length of a certain note. + + +================================================================================== + +0.7: +ADDED: one can now use the unix-like "cd" command to change to another + topic, thus use "cd topicname" instead just typing "topicname"! +FIXED: there was a smal regex bug which maked it impossible to use such + topics: "4 test", in such a case note just displayed note number 4 + instead of cd'ing to topic "4 test". +ADDED: a new config option "$KEEP_TIMESTAMP" allows a user to disable + note's default behavior of updating the timestamp of a note after + editing it. + + + +================================================================================== + + +0.6: +FIXED: oops - the new suptopic feature confused the commandline-mode of + note! quickly corrected! so subtopics also available from command- + line. +FIXED: a small bug fiyed, it was impossible to use -D or -I from command- + line, if $ALWAYS_INT was turned on, now it is. +FIXED: fixed problem with local/global variable $time, which confused + the script under certain circumstances, now $time is no more global, + it will be read in (using &getdate) locally by &new and &edit. +CHANGED: The Topic separator is no longer hardcoded, one can customize + it using the $TopicSep variable, the default is now /, the backslash + will no mor work! +CHANGED: use perl buildin localtime() function instead of + GNU date, which is possibly not installed on every target + system (i.e. win32), therefore better portability! +CHANGED: use now the strict module +ADDED: Support for subtopics added (and sub-sub-..-topics). +CHANGED: Removed the "T" command, it is now obsolete. +CHANGED: behavior of list command changed, now shows topics as well as + notes under the current topic(if there are some). +CHANGED: The ".." command takes you now one level higher in your topic- + structure. +ADDED: A new config option $PreferredEditor, which you can use to + specify your own choice of editor. +FIXED: A bug at line 769 causing single note where smaller than note- + listings + + + +================================================================================== + + + +0.5: +ADDED: Topic support(requested). You can sort the various notes under + different topics now. +FIXED: There was another bug, which caused the list command to display + the notes with a too high value of $maxlen. + + + +================================================================================== + + + +0.4.2: +ADDED: If run in interactive mode, note will at first do a list command. +FIXED: A bug caused note to save bogus timestamps after editing a note. +CHANGED: It does no more print 3 newlines before the menu in interactive mode. +FIXED: Some more vars will be resetted during each loop in interactive mode. + $ListType. + + + +================================================================================== + + + +0.4.1: +ADDED: The install.sh script for the mysql version is no able to install the + required Mysql module directly from CPAN, thanks to David A. Bandel! +FIXED: The mysql version did not display notes (i.e.: "note 3" did nothing) +CHANGED: Again, the sql-format of the mysql database has been changed. Now + there are only 3 fields, the number filed is the primary key, the id + field in previous versions was a waste of diskspace... +CHANGED: The format of the dump-output has been changed. +ADDED: It is now possible to import previously dumped notes into the notedb + (dumps from both versions are compatible with each other) +FIXED: the function num_bereich() had a bug, which caused ot to ignore under + some circumstances one number (i.e. "note -d 4-13" did nothing). + + + +================================================================================== + + + +0.4: +CHANGED: ok, mysql support is back again (upon requests). therefore there + are two different version of the script in the same time with + the same features, one for mysql and the other one for the binary + database. +ADDED: Dump to textfile capability. Later on I want to dump it into a + palm readable format, any help is welcome! +ADDED: interactive mode. +CHANGED: Better modularity, better code. +CHANGED: note can now run without the need of a config file. If does not + exist, it will try to work with default values. +ADDED: sub num_bereich(), which allows one to specify more then one + number for deletion or displaying (i.e.: "-d 1,4,7" or "-d 4-9") + + + +================================================================================== + + + +0.3: +CHANGED: it uses no more a mysql database, but a binary file instead. + This is much faster! +ADDED: note can display the notes with colors, it is turned off by default + + +================================================================================== + + +0.2: +FIXED: now any occurence of ' will be masked with \' before storage + to the mysql database. +FIXED: now numbers of notes will be recounted, if one delete one note, + so the list of notes will everytime start with 1,2,3,... +CHANGED: the look of the list output has been changed, similar to a table + + +================================================================================== + +0.1: +INITIAL RELEASE. diff --git a/note-1.0.7/Makefile.PL b/note-1.0.7/Makefile.PL new file mode 100644 index 0000000..cc0d712 --- /dev/null +++ b/note-1.0.7/Makefile.PL @@ -0,0 +1,108 @@ +# does not use ExtUtils::MakeMaker, because +# NOTEDB::mysql and NOTEDB::binary are internals +# of note. +# +# $Id: Makefile.PL,v 1.1 2000/04/17 17:38:49 thomas Exp thomas $ +# +# check for the existence of optional modules: +sub chk_mod +{ + my($mod, $msg) = @_; + print "<====\tchecking $mod \t====>\n"; + eval { + $mod .= ".pm"; + $mod =~ s/::/\//g; + require $mod; + }; + if($@) { + print $msg; + } + else { + print " ... installed.\n"; + } + print "\n"; +} + +&chk_mod( + "Getopt::Long", + "WARNING: Getopt::Long seems not to be installed on your system!\n" + ."But it is strongly required in order to run note!\n" + ); + +&chk_mod( + "DB_File", + "WARNING: DB_File seems not to be installed on your system!\n" + ."It is required, if you want to use the DBM backend.\n" + ); + + +&chk_mod( + "DBI", + " WARNING: module DBI is not installed on your system.\n" + ." It is required, if you want to use a SQL database with\n" + ."note.\n" + ); + +&chk_mod( + "Crypt::IDEA", + " WARNING: module Crypt::IDEA is not installed on your system.\n" + ." It is required, if you want to encrypt your data using IDEA.\n" + ); + +&chk_mod( + "Crypt::DES", + " WARNING: module Crypt::DES is not installed on your system.\n" + ." It is required, if you want to encrypt your data using DES.\n" + ); + +&chk_mod( + "Crypt::CBC", + " WARNING: module Crypt::CBC is not installed on your system.\n" + ." It is required, if you want to encrypt your data using CBC.\n" + ); + +&chk_mod( + "MD5", + " WARNING: module MD5 is not installed on your system.\n" + ." It is required by Crypt::CBC.\n" + ); + +foreach $dir (@INC) { + if($dir =~ /site_perl/) + { $LIBDIR = $dir; last; } +} +print "directory, where to install libs [$LIBDIR]: "; +$input = <>; +chomp $input; +$LIBDIR = $input if($input ne ""); + +$BINDIR = "/usr/local/bin"; +print "directory, where to install note [$BINDIR]: "; +$input = <>; +chomp $input; +$BINDIR = $input if($input ne ""); + +$install = `which install`; + +open M, "> Makefile" || die $!; +print M qq~BIN = bin/note +LIBS = NOTEDB/mysql.pm NOTEDB/binary.pm NOTEDB/dbm.pm +INSTBIN = $BINDIR +INSTLIB = $LIBDIR +INSTALL = $install +all: + \@echo "done. Type make install.\\n" + +install: + \$(INSTALL) -d -m 755 \$(INSTLIB)/NOTEDB + \$(INSTALL) -m 755 \$(LIBS) \$(INSTLIB)/NOTEDB + \$(INSTALL) -m 755 \$(BIN) \$(INSTBIN) +~; + +print "Type \"make install\" to install all files.\n\n"; +print "Please note: You may also copy the file \"config/noterc\" to\n" + ."your home: \"cp config/noterc ~/.noterc\". Don't forget to edit\n" + ."your config-file. Read the README for more informations on this\n" + ."topic.\n" + ."Thanks for choosing \"note\"! You are helping to keep the \n" + ."OpenSource idea alive! Enjoy and tell me, what you think!\n\n"; diff --git a/note-1.0.7/NOTEDB/README b/note-1.0.7/NOTEDB/README new file mode 100644 index 0000000..447198c --- /dev/null +++ b/note-1.0.7/NOTEDB/README @@ -0,0 +1,7 @@ +perl modules for note used as database backends. +the install.sh script will install both of them, +although you may only need one backend. Perhaps +other users on your system have oter ideas in mind... + +Therefore, please ignore these file. There is nothing +to edit or to do. Simply leave this directory :-) diff --git a/note-1.0.7/NOTEDB/binary.pm b/note-1.0.7/NOTEDB/binary.pm new file mode 100644 index 0000000..fac520b --- /dev/null +++ b/note-1.0.7/NOTEDB/binary.pm @@ -0,0 +1,388 @@ +#!/usr/bin/perl +# $Id: binary.pm,v 1.6 2000/06/25 19:48:00 scip Exp scip $ +# Perl module for note +# binary database backend. see docu: perldoc NOTEDB::binary +# +use strict; +use Data::Dumper; +use IO::Seekable; + +package NOTEDB; +use Fcntl qw(LOCK_EX LOCK_UN); +BEGIN { + # make sure, it works, although encryption + # not supported on this system! + eval { require Crypt::CBC; }; + if($@) { + $NOTEDB::crypt_supported = 0; + } + else { + $NOTEDB::crypt_supported = 1; + } +} + +# Globals: +my ($NOTEDB, $sizeof, $typedef,$version); +my ($cipher); + +$version = "(NOTEDB::binary, 1.6)"; + + +sub new +{ + my($this, $dbdriver, $dbname, $MAX_NOTE, $MAX_TIME) = @_; + + my $class = ref($this) || $this; + my $self = {}; + bless($self,$class); + $NOTEDB = $dbname; + + if(! -e $NOTEDB) + { + open(TT,">$NOTEDB") or die "Could not create $NOTEDB: $!\n"; + close (TT); + } + elsif(! -w $NOTEDB) + { + print "$NOTEDB is not writable!\n"; + exit(1); + } + + + my $TYPEDEF = "i a$MAX_NOTE a$MAX_TIME"; + my $SIZEOF = length pack($TYPEDEF, () ); + + $sizeof = $SIZEOF; + $typedef = $TYPEDEF; + return $self; +} + + +sub DESTROY +{ + # clean the desk! +} + +sub version { + return $version; +} + +sub no_crypt { + $NOTEDB::crypt_supported = 0; +} + +sub use_crypt { + my($this,$key,$method) = @_; + if($NOTEDB::crypt_supported == 1) { + eval { + $cipher = new Crypt::CBC($key, $method); + }; + if($@) { + $NOTEDB::crypt_supported == 0; + } + } + else{ + print "warning: Crypt::CBC not supported by system!\n"; + } +} + +sub set_del_all +{ + unlink $NOTEDB; + open(TT,">$NOTEDB") or die "Could not create $NOTEDB: $!\n"; + close (TT); +} + + +sub get_single +{ + my($this, $num) = @_; + my($address, $note, $date, $buffer, $n, $t, $buffer, ); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + $address = ($num-1) * $sizeof; + seek(NOTE, $address, IO::Seekable::SEEK_SET); + read(NOTE, $buffer, $sizeof); + ($num, $n, $t) = unpack($typedef, $buffer); + + $note = ude($n); + $date = ude($t); + + flock NOTE, LOCK_UN; + close NOTE; + + return $note, $date; +} + + +sub get_all +{ + my($this, $num, $note, $date, %res); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + my($buffer, $t, $n); + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) { + ($num, $note, $date) = unpack($typedef, $buffer); + $t = ude($date); + $n = ude($note); + $res{$num}->{'note'} = $n; + $res{$num}->{'date'} = $t; + } + flock NOTE, LOCK_UN; + close NOTE; + + return %res; +} + + +sub get_nextnum +{ + my($this, $num, $te, $me, $buffer); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) { + ($num, $te, $me) = unpack($typedef, $buffer); + } + $num += 1; + flock NOTE, LOCK_UN; + close NOTE; + + return $num; +} + +sub get_search +{ + my($this, $searchstring) = @_; + my($buffer, $num, $note, $date, %res, $t, $n); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) + { + ($num, $note, $date) = unpack($typedef, $buffer); + $n = ude($note); + $t = ude($date); + if($n =~ /\Q$searchstring\E/i) + { + $res{$num}->{'note'} = $n; + $res{$num}->{'date'} = $t; + } + } + flock NOTE, LOCK_UN; + close NOTE; + + return %res; +} + + + + +sub set_edit +{ + my($this, $num, $note, $date) = @_; + my $address = ($num -1 ) * $sizeof; + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + seek(NOTE, $address, IO::Seekable::SEEK_SET); + my $n = uen($note); + my $t = uen($date); + + my $buffer = pack($typedef, $num, $n, $t); + print NOTE $buffer; + + flock NOTE, LOCK_UN; + close NOTE; +} + + +sub set_new +{ + my($this, $num, $note, $date) = @_; + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + seek(NOTE, 0, IO::Seekable::SEEK_END); # APPEND + my $n = uen($note); + my $t = uen($date); + my $buffer = pack($typedef, $num, $n, $t); + print NOTE $buffer; + + flock NOTE, LOCK_UN; + close NOTE; +} + + +sub set_del +{ + my($this, $num) = @_; + my(%orig, $note, $date, $T, $setnum, $buffer, $n, $N, $t); + + $setnum = 1; + + %orig = $this->get_all(); + return "ERROR" if (! exists $orig{$num}); + + delete $orig{$num}; + + # overwrite, but keep number! + open NOTE, ">$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + seek(NOTE, 0, 0); # START FROM BEGINNING + foreach $N (keys %orig) { + $n = uen($orig{$N}->{'note'}); + $t = uen($orig{$N}->{'date'}); + $buffer = pack( $typedef, $N, $n, $t); # keep orig number, note have to call recount! + print NOTE $buffer; + seek(NOTE, 0, IO::Seekable::SEEK_END); + $setnum++; + } + flock NOTE, LOCK_UN; + close NOTE; + return; +} + +sub set_recountnums +{ + my($this) = @_; + my(%orig, $note, $date, $T, $setnum, $buffer, $n, $N, $t); + + $setnum = 1; + %orig = $this->get_all(); + + open NOTE, ">$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + seek(NOTE, 0, 0); # START FROM BEGINNING + + foreach $N (sort {$a <=> $b} keys %orig) { + $n = uen($orig{$N}->{'note'}); + $t = uen($orig{$N}->{'date'}); + $buffer = pack( $typedef, $setnum, $n, $t); + print NOTE $buffer; + seek(NOTE, 0, IO::Seekable::SEEK_END); + $setnum++; + } + flock NOTE, LOCK_UN; + close NOTE; + return; +} + +sub uen +{ + my($T); + if($NOTEDB::crypt_supported == 1) { + eval { + $T = pack("u", $cipher->encrypt($_[0])); + }; + } + else { + $T = pack("u", $_[0]); + } + chomp $T; + return $T; +} + +sub ude +{ + my($T); + if($NOTEDB::crypt_supported == 1) { + eval { + $T = $cipher->decrypt(unpack("u",$_[0])); + }; + } + else { + $T = unpack("u", $_[0]); + } + return $T; +} + +1; # keep this! + +__END__ + +=head1 NAME + +NOTEDB::binary - module lib for accessing a notedb from perl + +=head1 SYNOPSIS + + # include the module + use NOTEDB; + + # create a new NOTEDB object + $db = new NOTEDB("binary", "/home/tom/.notedb", 4096, 24); + + # decide to use encryption + # $key is the cipher to use for encryption + # $method must be either Crypt::IDEA or Crypt::DES + # you need Crypt::CBC, Crypt::IDEA and Crypt::DES to have installed. + $db->use_crypt($key,$method); + + # do not use encryption + # this is the default + $db->no_crypt; + + # get a single note + ($note, $date) = $db->get_single(1); + + # search for a certain note + %matching_notes = $db->get_search("somewhat"); + # format of returned hash: + #$matching_notes{$numberofnote}->{'note' => 'something', 'date' => '23.12.2000 10:33:02'} + + # get all existing notes + %all_notes = $db->get_all(); + # format of returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + + # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH + $db->use_crypt("passphrase", "CryptMethod"); + + # turn off encryption. This is the default. + $db->no_crypt(); + + +=head1 DESCRIPTION + +You can use this module for accessing a note database. There are currently +two versions of this module, one version for a SQL database and one for a +binary file (note's own database-format). +However, both versions provides identical interfaces, which means, you do +not need to change your code, if you want to switch to another database format. + +Currently, NOTEDB module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + + +=cut diff --git a/note-1.0.7/NOTEDB/dbm.pm b/note-1.0.7/NOTEDB/dbm.pm new file mode 100644 index 0000000..cfdc0ba --- /dev/null +++ b/note-1.0.7/NOTEDB/dbm.pm @@ -0,0 +1,261 @@ +#!/usr/bin/perl +# $Id: dbm.pm,v 1.2 2000/06/25 19:51:11 scip Exp scip $ +# Perl module for note +# DBM database backend. see docu: perldoc NOTEDB::dbm +# + +use DB_File; +#use Data::Dumper; +use strict; +package NOTEDB; + +BEGIN { + # make sure, it works, although encryption + # not supported on this system! + eval { require Crypt::CBC; }; + if($@) { + $NOTEDB::crypt_supported = 0; + } + else { + $NOTEDB::crypt_supported = 1; + } +} + +# Globals: +my ($dbm_dir, $notefile, $timefile, $version, $cipher, %note, %date); +$notefile = "note.dbm"; +$timefile = "date.dbm"; + +$version = "(NOTEDB::dbm, 1.1)"; + +sub new +{ + my($this, $dbdriver, $dbm_dir) = @_; + my $class = ref($this) || $this; + my $self = {}; + bless($self,$class); + + tie %note, "DB_File", "$dbm_dir/$notefile" || die $!; + tie %date, "DB_File", "$dbm_dir/$timefile" || die $!; + + return $self; +} + + +sub DESTROY +{ + # clean the desk! + untie %note, %date; +} + +sub version { + return $version; +} + +sub no_crypt { + $NOTEDB::crypt_supported = 0; +} + +sub use_crypt { + my($this, $key, $method) = @_; + if($NOTEDB::crypt_supported == 1) { + eval { + $cipher = new Crypt::CBC($key, $method); + }; + if($@) { + $NOTEDB::crypt_supported == 0; + } + } + else{ + print "warning: Crypt::CBC not supported by system!\n"; + } +} + + +sub get_single +{ + my($this, $num) = @_; + my($note, $date); + return ude ($note{$num}), ude($date{$num}); +} + + +sub get_all +{ + my($this, $num, $note, $date, %res, $real); + foreach $num (sort {$a <=> $b} keys %date) { + $res{$num}->{'note'} = ude($note{$num}); + $res{$num}->{'date'} = ude($date{$num}); + } + return %res; +} + + +sub get_nextnum +{ + my($this, $num); + foreach (sort {$a <=> $b} keys %date) { + $num = $_; + } + $num++; + return $num; +} + +sub get_search +{ + my($this, $searchstring) = @_; + my($num, $note, $date, %res); + + foreach $num (sort {$a <=> $b} keys %date) { + if (ude($note{$num}) =~ /\Q$searchstring\E/i) { + $res{$num}->{'note'} = ude($note{$num}); + $res{$num}->{'date'} = ude($date{$num}); + } + } + + return %res; +} + + + +sub set_recountnums +{ + my $this = shift; + my(%Note, %Date, $num, $setnum); + $setnum = 1; + foreach $num (sort {$a <=> $b} keys %note) { + $Note{$setnum} = $note{$num}; + $Date{$setnum} = $date{$num}; + $setnum++; + } + %note = %Note; + %date = %Date; +} + + + +sub set_edit +{ + my($this, $num, $note, $date) = @_; + $note{$num} = uen($note); + $date{$num} = uen($date); +} + + +sub set_new +{ + my($this, $num, $note, $date) = @_; + $this->set_edit($num, $note, $date); # just the same thing +} + + +sub set_del +{ + my($this, $num) = @_; + my($note, $date, $T); + ($note, $date) = $this->get_single($num); + return "ERROR" if ($date !~ /^\d/); + delete $note{$num}; + delete $date{$num}; +} + +sub set_del_all +{ + my($this) = @_; + %note = (); + %date = (); + return; +} + +sub uen +{ + my($T); + if($NOTEDB::crypt_supported == 1) { + eval { + $T = pack("u", $cipher->encrypt($_[0])); + }; + } + else { + $T = $_[0]; + } + chomp $T; + return $T; +} + +sub ude +{ + my($T); + if($NOTEDB::crypt_supported == 1) { + eval { + $T = $cipher->decrypt(unpack("u",$_[0])) + }; + return $T; + } + else { + return $_[0]; + } +} + +1; # keep this! + +__END__ + +=head1 NAME + +NOTEDB::dbm - module lib for accessing a notedb from perl + +=head1 SYNOPSIS + + # include the module + use NOTEDB; + + # create a new NOTEDB object (the last 4 params are db table/field names) + $db = new NOTEDB("mysql","note","/home/user/.notedb/"); + + # get a single note + ($note, $date) = $db->get_single(1); + + # search for a certain note + %matching_notes = $db->get_search("somewhat"); + # format of returned hash: + #$matching_notes{$numberofnote}->{'note' => 'something', 'date' => '23.12.2000 10:33:02'} + + # get all existing notes + %all_notes = $db->get_all(); + # format of returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # recount all noteids starting by 1 (usefull after deleting one!) + $db->set_recountnums(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + +=head1 DESCRIPTION + +You can use this module for accessing a note database. This is the dbm module. +It uses the DB_FILE module to store it's data and it uses DBM files for tis purpose. + +Currently, NOTEDB module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + + +=cut diff --git a/note-1.0.7/NOTEDB/mysql.pm b/note-1.0.7/NOTEDB/mysql.pm new file mode 100644 index 0000000..9c47509 --- /dev/null +++ b/note-1.0.7/NOTEDB/mysql.pm @@ -0,0 +1,349 @@ +#!/usr/bin/perl +# $Id: mysql.pm,v 1.5 2000/06/25 19:50:43 scip Exp scip $ +# Perl module for note +# mysql database backend. see docu: perldoc NOTEDB::binary +# + +use DBI; +use strict; +use Data::Dumper; + +package NOTEDB; + +BEGIN { + # make sure, it works, although encryption + # not supported on this system! + eval { require Crypt::CBC; }; + if($@) { + $NOTEDB::crypt_supported = 0; + } + else { + $NOTEDB::crypt_supported = 1; + } +} + +# Globals: +my ($DB, $table, $fnum, $fnote, $fdate, $version, $cipher); +$table = "note"; +$fnum = "number"; +$fnote = "note"; +$fdate = "date"; +$version = "(NOTEDB::mysql, 1.4)"; + +# prepare some std statements... ##################################################################### +my $sql_getsingle = "SELECT $fnote,$fdate FROM $table WHERE $fnum = ?"; +my $sql_all = "SELECT $fnum,$fnote,$fdate FROM $table"; +my $sql_nextnum = "SELECT max($fnum) FROM $table"; +my $sql_incrnum = "SELECT $fnum FROM $table ORDER BY $fnum"; +my $sql_search = "SELECT DISTINCT $fnum,$fnote,$fdate FROM $table WHERE $fnote LIKE ?"; + +my $sql_setnum = "UPDATE $table SET $fnum = ? WHERE $fnum = ?"; +my $sql_edit = "UPDATE $table SET $fnote = ?, $fdate = ? WHERE $fnum = ?"; + +my $sql_insertnew = "INSERT INTO $table VALUES (?, ?, ?)"; + +my $sql_del = "DELETE FROM $table WHERE $fnum = ?"; +my $sql_del_all = "DELETE FROM $table"; +###################################################################################################### + +sub new +{ + # no prototype, because of the bin-version, which takes only a filename! + my($this, $dbdriver, $dbname, $dbhost, $dbuser, $dbpasswd) = @_; + + my $class = ref($this) || $this; + my $self = {}; + bless($self,$class); + my $database = "DBI:$dbdriver:$dbname;host=$dbhost"; + + $DB = DBI->connect($database, $dbuser, $dbpasswd) || die DBI->errstr(); + + # LOCK the database! + my $lock = $DB->prepare("LOCK TABLES $table WRITE") || die $DB->errstr(); + $lock->execute() || die $DB->errstr(); + + return $self; +} + + +sub DESTROY +{ + # clean the desk! + my $unlock = $DB->prepare("UNLOCK TABLES") || die $DB->errstr; + $unlock->execute() || die $DB->errstr(); + $DB->disconnect || die $DB->errstr; +} + +sub version { + return $version; +} + +sub no_crypt { + $NOTEDB::crypt_supported = 0; +} + +sub use_crypt { + my($this, $key, $method) = @_; + if($NOTEDB::crypt_supported == 1) { + eval { + $cipher = new Crypt::CBC($key, $method); + }; + if($@) { + $NOTEDB::crypt_supported == 0; + } + } + else{ + print "warning: Crypt::CBC not supported by system!\n"; + } +} + +sub get_single +{ + my($this, $num) = @_; + my($note, $date); + my $statement = $DB->prepare($sql_getsingle) || die $DB->errstr(); + + $statement->execute($num) || die $DB->errstr(); + $statement->bind_columns(undef, \($note, $date)) || die $DB->errstr(); + + while($statement->fetch) { + return ude($note), ude($date); + } +} + + +sub get_all +{ + my($this, $num, $note, $date, %res); + my $statement = $DB->prepare($sql_all) || die $DB->errstr(); + + $statement->execute || die $DB->errstr(); + $statement->bind_columns(undef, \($num, $note, $date)) || die $DB->errstr(); + + while($statement->fetch) { + $res{$num}->{'note'} = ude($note); + $res{$num}->{'date'} = ude($date); + } + return %res; +} + + +sub get_nextnum +{ + my($this, $num); + my $statement = $DB->prepare($sql_nextnum) || die $DB->errstr(); + + $statement->execute || die $DB->errstr(); + $statement->bind_columns(undef, \($num)) || die $DB->errstr(); + + while($statement->fetch) { + return $num+1; + } +} + +sub get_search +{ + my($this, $searchstring) = @_; + my($num, $note, $date, %res); + if($NOTEDB::crypt_supported != 1) { + $searchstring = "\%$searchstring\%"; + my $statement = $DB->prepare($sql_search) || die $DB->errstr(); + $statement->execute($searchstring) || die $DB->errstr(); + $statement->bind_columns(undef, \($num, $note, $date)) + || die $DB->errstr(); + while($statement->fetch) { + $res{$num}->{'note'} = $note; + $res{$num}->{'date'} = $date; + } + } + else { + my %res = $this->get_all(); + foreach $num (sort { $a <=> $b } keys %res) { + $note = ude($res{$num}->{'note'}); + $date = ude($res{$num}->{'date'}); + if($note =~ /\Q$searchstring\E/i) + { + $res{$num}->{'note'} = $note; + $res{$num}->{'date'} = $date; + } + } + } + return %res; +} + + + + +sub set_edit +{ + my($this, $num, $note, $date) = @_; + + my $statement = $DB->prepare($sql_edit) || die $DB->errstr(); + + $note =~ s/'/\'/g; + $note =~ s/\\/\\\\/g; + $statement->execute(uen($note), uen($date), $num) || die $DB->errstr(); +} + + +sub set_new +{ + my($this, $num, $note, $date) = @_; + + my $statement = $DB->prepare($sql_insertnew) || die $DB->errstr(); + + $note =~ s/'/\'/g; + $note =~ s/\\/\\\\/g; + $statement->execute($num, uen($note), uen($date)) || die $DB->errstr(); +} + + +sub set_del +{ + my($this, $num) = @_; + my($note, $date, $T); + + ($note, $date) = $this->get_single($num); + + return "ERROR" if ($date !~ /^\d/); + + # delete record! + my $statement = $DB->prepare($sql_del) || die $DB->errstr(); + $statement->execute($num) || die $DB->errstr(); + return; +} + + +sub set_del_all +{ + my($this) = @_; + my $statement = $DB->prepare($sql_del_all) || die $DB->errstr(); + $statement->execute() || die $DB->errstr(); + return; +} + +sub set_recountnums +{ + my $this = shift; + my(@count, $i, $num, $setnum, $pos); + $setnum = 1; + $pos=0; $i=0; @count = (); + + my $statement = $DB->prepare($sql_incrnum) || die $DB->errstr(); + $statement->execute || die $DB->errstr(); + $statement->bind_columns(undef, \($num)) || die $DB->errstr(); + # store real id's in an array! + while($statement->fetch) { + $count[$i] = $num; + $i++; + } + + # now recount them! + my $sub_statement = $DB->prepare($sql_setnum) || die $DB->errstr(); + for($pos=0;$pos<$i;$pos++) { + $setnum = $pos +1; + $sub_statement->execute($setnum,$count[$pos]) || die $DB->errstr(); + } +} + +sub uen +{ + my($T); + if($NOTEDB::crypt_supported == 1) { + eval { + $T = pack("u", $cipher->encrypt($_[0])); + }; + } + else { + $T = $_[0]; + } + chomp $T; + return $T; +} + +sub ude +{ + my($T); + if($NOTEDB::crypt_supported == 1) { + eval { + $T = $cipher->decrypt(unpack("u",$_[0])) + }; + return $T; + } + else { + return $_[0]; + } +} + +1; # keep this! + +__END__ + +=head1 NAME + +NOTEDB::mysql - module lib for accessing a notedb from perl + +=head1 SYNOPSIS + + # include the module + use NOTEDB; + + # create a new NOTEDB object (the last 4 params are db table/field names) + $db = new NOTEDB("mysql","note","localhost","username","password","note","number","note","date"); + + # get a single note + ($note, $date) = $db->get_single(1); + + # search for a certain note + %matching_notes = $db->get_search("somewhat"); + # format of returned hash: + #$matching_notes{$numberofnote}->{'note' => 'something', 'date' => '23.12.2000 10:33:02'} + + # get all existing notes + %all_notes = $db->get_all(); + # format of returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # recount all noteids starting by 1 (usefull after deleting one!) + $db->set_recountnums(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + + # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH + $db->use_crypt("passphrase", "CryptMethod"); + + # turn off encryption. This is the default. + $db->no_crypt(); + +=head1 DESCRIPTION + +You can use this module for accessing a note database. There are currently +two versions of this module, one version for a SQL database and one for a +binary file (note's own database-format). +However, both versions provides identical interfaces, which means, you do +not need to change your code, if you want to switch to another database format. + +Currently, NOTEDB module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + + +=cut diff --git a/note-1.0.7/README b/note-1.0.7/README new file mode 100644 index 0000000..06a62fb --- /dev/null +++ b/note-1.0.7/README @@ -0,0 +1,517 @@ +note 1.0.7 by Thomas Linden, 27/06/2000 +======================================= + +Introduction +============ + + This is a small console program written in + perl, which allows you to manage notes similar + to programs like "knotes" from commandline. + + There are currently three different database backends, + which you can use with note: + o NOTEDB::binary - this is the default backend + and uses a binary file to store your notes. + o NOTEDB::mysql - this backend uses a mysql + database to store your notes. You can switch + easily to another DBMS since this module uses + the Perl standard module "DBI" for database- + access. See below for more info on this topic! + o NOTEDB::dbm - this module uses two DBM files + for data storage and requires the module DB_FILE, + which is part of the perl standard distribution. + See below for more details about the DBM module. + + + +Where to get? +============= + + By now at + http://www.daemon.de/software.html + or + ftp://www.0c49.org/pub/scip/note/ + + You may also try your nearest tucows mirror. + + + + +Features +======== + + o Three different database backends, mysql(DBI), dbm, binary(bin file). + o Commandline interface using the standard perl module + Getopt::Long, which allows you to use short or long + command-line options. + o Interactive interface(pure ascii), the following functions + are available in interactive mode: list, display, topic, + delete, edit, help. + o Highly confiurable using a perlish configfile ~/.noterc. + although it is configurable it is not required, note can + run without a configfile using useful default presets. + o Colourized output is supported using ASCII Escape-Sequences. + o The user can customize the color for each item. + o Data can be stored in various different database backends, + since all database access is excluded from the program itself + in perl modules. + o Notes can be deleted, edited and you can search trough your notes. + o Notes can be categorized. Each category(topic) can contain multiple + notes and even more sup-topics. There is no limitation about + sub topics. + o You can view all notes in a list and it is possible only to view + notes under a certain topic. + o There is a tree-view, which allows you to get an overview of your + topic-hierarchy. + o Notes can be encrypted using DES or IDEA algorythms and Crypt::CBC. + o You can dump the contents of your note database into a plain text + file, which can later be imported. Imports can be appended or it can + overwrite an existing database (-o). + o Note has scripting capabilities, you can create a new note by piping + another commands output to note, you can also import a notedump from + stdin as well es duming to stdout instead a file. Additional, there + is an option --raw available, which prints everything out completely + without formatting. + o It can be installed without root-privileges. + o Last, a while ago a user stated: "... it simply does, what it says ..." + + + + + +Requirements +============ + + You need the following things: + o perl installed (5.004x) + o The module IO::Seekable and Fcntl, which should be + already installed with your perl distributuion if + you want to use the binary database backend. + o DBI module and DBI::mysql if you want to use the + mysql database backend. + o The module DB_FILE if you want to use the DBM module. + o Getopt::Long (part of perl std ditribution) + + + +Installation +============ + + Unpack the tar-ball and issue the command: + $ perl Makefile.PL + It will ask you a few questions about file destinations. + The script will find itself the proper destinations for + the files. So, if you agree with it, simply press ENTER. + However, you may decide to use other destinations. In this + case, enter it, when asked. This maybe usefull, if you are + installing it in your ome-directory and if you are not root! + + For installation instructions for the mysql database installation + see mysql/README. + + If want to use another SQL database, i.e. postgresql then set + the option "DbDriver" to the name of the responding DBI-driver + and create a symlink of this name like this: + /usr/lib/perl5/siteperl/NOTEDB $ ln -s mysql.pm oracle.pm + The functionality is the same, but not the name! + + The default binary file backend does not need any special installation + procedure, you need only to spceify a filename in your config file. + + The DBM backend(NOTEDB::dbm) requires the existence of a directory, + which you must specify in your config using the option "DbName". + + + +Configuration +============= + + This version of note doesn't neccessarily need + a configuration file. But you can have one and change + some default values. Take a look to the file config/noterc + provided with this tarball. There are detailed instructions + about every available parameter. + Simply copy this file into your home-directory and name it + .noterc + If you decide not to use the default database backend (a binary + file), you will *need* a configuration! + + + +Usage +===== + + If you don't know, how to run note, try "note -h" first. + It will tell you all available commandline options. + + To create a new note, simply run "note". You can enter + the note (the length is by default limited to 4096 bytes, + which you can change from your config file if you are using + the binary backend, therwise there is no limitation). + End by typing a . on a line itself. note will tell you the + number of the note. + + If you want to view the note, type "note 1", if the notenumber + was 1. + + If you want to get an overview of all notes, type "note -l". + You will get a list of all notes, containing the number, + the first line and the creation date. If topic-support is + turned on (which is by default), then all subtopics under the + current topic will be displayed first. + If you want to get a listing of all + If you want to see the timestamps, use "-L" instead of "-l". + Read more about topics below in the section "Topics". + You can also specify the topic which notes you want to see: + "-l mytopic" does the trick. + Additional, you might want to get an overview of your topic- + strcture. You can use the command "-t" in this case, which + will display a tree-view of your tpic-structure. You can + use the command "-T" if you want to see the notes under each + topic too. "-T" will also show the number of each note. + + To edit a certain note, type "note -e 1". It will invoke your + editor (vi or pico). You can edit it, after saving, note + will store the changed note to the database. + + Of course you can drop a certain note: "note -d 1" deletes + note number 1. If a note in the middle or the beginning of + the database will be deleted, note will recount the other + existent notes. For example there are 3 notes, number 1, 2 + and 3. If you delete number 2, then number 3 will become + number 2. + You can also make use of the extended delete-syntax: + To delete note 1 and 2, use "-d 1,2" + To delete note 1,2 and 3, use "-d 1-3". + + If you cannot remember, which note you are looking for, you + can use the search capability of note: "note -s ". + note will search the whole note database case insensitive for + an occurence of this string and tell you the number and first- + line it have. + + Instead of using note from the commandline you can use the + interactive mode. Run note with "note -i". If you need assistance + type "?" or "h" at the ">" prompt. The interactive mode + provides you the most functions of note. + + You can also dump the contents of your note-database into a + ASCII-textfile(-D). You can use this file later to import it into + your note-database(-I). This is usefull, if you want quickly trans- + fer your notes from one host to another (i.e. you could mail + your note-dump form your office to home and import it there + for further use). + The dumps from the two versions of note are in the same format. + Using dumps it is also possible to reinitialize your database. You + can use the "-o" switch whcih causes note to overwrite your existing + database. This is very handy if you changed heavily your config. And + it is required, if you changed: encryption, db-driver, (binary-format) + and the password. You can use the following command for reinitializing: + $ note -D - | note -o -I - + What the hell, does it?! Step by step: + o "note -D -" creates a note-database dump and prints it out + to stantdard output. + o "|" this is the shell's pipe command. It takes the output + of the left program and gives it to the right program as standard + input. + o "note -o -I -" imports a note-database dump from standard input + and overwrites an existing database. + Before you use the "-o" switch, I consider yuo to make a backup! + + + + +Topics +====== + + If topic-support is turned on (which is by default), the various + notes are sorted under various topics. There is no special database + field for the topic. Instead the topic will be stored right in the + note. + If the first line of your note contains some text bordered by slashes + (or whatever you prefer, set "TopicSeparator" in your config! default is slash), + then note will consider it as the topic of this certain note. For examle: + /TodoList/ + If you are using topics, no data after the topic is allowed, if there + is any text, note will consider it as a subtopic! Therefore, don't for- + get to put a newline after the topic-line. + + If you are in interactive mode, you can "cd" to a different note simply + by typing it's name at the command-prompt, or you can use the well-known + syntax "cd topic". + The list-command will only show you notes under this topic. If you create + a new note, it will automagically inserted under the current topic (note + will prepend the string "/topicname/" to the text of your note). + + You can create at any time from any point a new topic. Just create a new + note and type the name of the new topic bordered by slashes (or TopicSeparator) + at the first line of this note. After saving, there will be available a + new topic with one note in it. + + You can create as many subtopics as you like, the format is similar to a + filesystem-path. An example, say, you want to create such a structure: + + (root - top level) + | + |----test + | |----subtopic + | | |--note 1 + | | |--note 2 + | | + | |--note 4 + | + |--note 3 + + Then you may create those 4 new notes: + --- snip --- + /test/subtopic/ + note 1 + --- snip --- + /test/subtopic/ + note 2 + --- snip --- + note 3 + --- snip --- + /test/ + note 4 + --- snip --- + + I hope, you got the point ;-) + + + + If a note does not contain the "magic" /topic/ construction on the first + line, it will be listed under the "root" of note, that is the point you are + at the startup of note. + + You can subsequently move a note without a topic to a certain topic. Simply + edit it and insert at the first line the above mentioned construction. + + Note: Please don't forget the prepending and appending a slash of a topic. + You will get strange results without it! + + + + +Formatting of notes +=================== + + Another very nice feature is the possibility to format the note-text (as much as + shell allows it). First, you can use the note-internal "magic-strings" for color- + izing. Those strings looks much like HTML: + "here is a green line of text no more green." + As you see, the beginning of another color starts with a tag(kinda) of the color + and ens with an end tag . + + The following colors are available: + black, red, green, yellow, blue, magenta, cyan and white. + + Beside colorizing text, you can also create bold or underlined text! If you decide + to use this (additional) feature, you need to set the Config-Option "FormatNotes" + to 1 which turns it on. + Usage is very straightforward, if a word (a word is defined as some text with at least + one space surrounded) is between a magic mark-character. Here are the available + things, you can do: + + bold: **word** + underlined: __word__ + inverse: {{word}} + + The text will be formatted using the actually note-color. + + + + +Scripting +========= + + Since version 1.0.3 there are some additions which allows you to use note in + scripts, without user-interaction. You might run a special script as cronjob, + which adds a note under a certain topic every week. Or the like. + + Here are the possibilies you have: + + You can add a new note through a pipe, another commands output becomes + note's input: + $ cat /var/spool/news/daily | note - + This command adds the content of a file "daily" as a new note. Note the dash. + it stands for "Standard Input". Note will be completely silent and it will not + ask for something. + + Suppose you are using encryption. You might wonder, how note will get your + passphrase? The solution: You need to set up an environment variable which + contains the password: + $ export NOTE_PASSWD=secret + If the variable is present, note will not ask you for a passphrase! + + Another thingy you might find useful is the -r (--raw) command-line flag. This + turns note into raw mode , which means it will only print the + data without any formatting. Raw mode is available for list and display, + since it makes no sense, interactive mode doe not support raw mode. + + + + + +Format of the notedb (binary backend) +===================================== + + The database where the notes are stored is a binary fixed record length file + of the following format: + It consists of three fixed length fields per entry. The fields + have the following types: + o Number: Integer (1 byte) + o Note: String (default 1024 bytes) + o Time: String (default 64 bytes) + You can change the sizes of the fields "Note" and "Time" in + the configfile "~/.noterc". If it does not exist, the above + defaults will be used. + If the data to be stored is smaller then the size of the field, + it will be filled with ZERO's ("\0"). The Note and the Time + fields will be uuencoded before storage. Of course, this is + no security, never mind... + + + +The note-database (mysql backend) +================================= + + The sql-database for the mysql version has the following design: + +--------+---------+------+-----+---------+----------------+ + | Field | Type | Null | Key | Default | Extra | + +--------+---------+------+-----+---------+----------------+ + | number | int(10) | | PRI | 0 | auto_increment | + | note | text | YES | | NULL | | + | date | text | YES | | NULL | | + +--------+---------+------+-----+---------+----------------+ + + + +Format of the ASCII-dump file (note -D) +======================================= + + The dump of a note-database (if you use note -D) has the following + format: + + --- snip --- + Number: 1 + Timestamp: 14.01.2000 00:25:01 + This is a sample text + in a sample note. + + Number: 2 + Timestamp: 14.01.2000 02:37:40 + And this is another sample + of a note. + --- snip --- + + You can reimport a dump into your note-database with "note -I " + Existing notes will not overwritten, note will append the imported + data to your note-database. + + + + +Security +======== + + If you are using the MySQL driver, refer to the mysql + manual for more informations about security of mysql databases: + http://www.mysql.org/Manual_chapter/manual_Privilege_system.html + + If you are using notes proprietary binary driver, then + the permission 0600 of the file "~/.notedb" is strongly required! + + Additional, you can turn on encryption from the config file. + Simply set UseEncryption to 1. Please note, that you need + to decide, if you want to use encryption before the first use + of note! If have already a note database and want to "migrate" + to encryption, I suggest you to follow the directions in the + file UPGRADE! + + You can choose from different encryption algorythms. The default + is IDEA, but DES or BLOWFISH is also possible. You need to have + installed the following additional perl-modules on your system: + MD5 + Crypt::IDEA + Crypt::DES + Crypt::CBC + + After turning on encryption, note will ask you for a passphrase + everytime it runs! It will *not* store this passphrase! + So, don't forget it! Be careful! + + Once note have encrypted some data using this passphrase, you + cannot simply switch to another passphrase, because all data + within the database needs to be encrypted using the same passphrase! + If you want to change the passphrase for any reason, please read + the file UPGRADE and follow it's directions! + Someday I will add a "change passwd" function, which will do all + these things for you. Someday, I said... + For now you can use the "re-initialze database" functionality, mentioned + earlier in the "Usage" section (at the end of the section). + + Note: To make sure, the encrypted data can be stored properly, + it will be uuencoded after encryption. + + Note: *If* you forgot your passphrase and *if* you don't have + a backup of your database without encryption, PLEASE + don't bother me with "helpme" emails! If you don't know + the phrase, then the data can't be decrypted. Even if it + is possible - I am not responsible for that! + + Note: How does note know, if the passphrase was incorrect? It uses the + specified phrase and encodes at least one note (the first one) + and checks if the decrypted timestamp field matches the following + expression: "^\d+\.\d+". Translated from perl to human: + the timestamp must begin with minimum one digit (possibly more), + followed by one dot, followed by minimum one digit (possibly more). + Chances are bad, that a wrong passphrase will cause a timestamp + matching the rule above. If you have other experiences, please + drop me a mail! + + +Comments +======== + + You can send any comments to Thomas Linden . + If you find a bug or if you have a suggestion for improvement of the script + feel free to send me a patch ;-) + + + +License +======= + + This script comes with absolutely NO WARRANTY. It is distributed under the + terms of the GNU General Public License. Use it at your own risk :-) + You can read the complete GPL at: http://www.gnu.org/copyleft/gpl.html + + + +Author and Copyright +==================== + + The author is Thomas Linden. + note is Copyright of Thomas Linden. + + + + +Contributors / Credits +====================== + + Shouts to those guys who helped me to enhance note: THANKS A LOT! + + Jens Heunemann - sub tree. + Peter Palmreuther - various additions. + + And many other people who sended bug reports, feature requests. If you feel that + I forgot your name in this list, then please send me an email and I'll add you. + + + +Last changed +============ + + 27/06/2000 diff --git a/note-1.0.7/UPGRADE b/note-1.0.7/UPGRADE new file mode 100644 index 0000000..32611ee --- /dev/null +++ b/note-1.0.7/UPGRADE @@ -0,0 +1,73 @@ +1.0.5 important note upgrade information +======================================== + +If you are upgrading from previous versions of note, you +will need to create a new config file, since the format of +that file has completely changed! + +Take a look at the sample in config/noterc for details. + +note will NOT work with an existing database and an old config. +You have to create a new config based on your old settings. + + +Please don't forget to make a backup of your database before +upgrading! I am not responsible for data loss! + +I told ya... + + + + + +Thomas Linden +READ THIS FILE, IF YOU ARE UPGRADING FROM 0.9 TO 1.0.x +====================================================== + + +In any case: BACKUP your existing note database!!!!!!! +The format has not changed, but some default values +(see the new config file-sample). Use this command +to save your note database with your *old* version +of note: + "note -D" +This works with both the mysql and the binary version. + +You need to reedit your configfile. Please refer to the +sample config in config/noterc. + +====================================================== + +This version of note has now encryption support build in. +If you decide to use it, you need to re-initialize your +note database. That's why, because your current database +is unencrypted and *if* you want to secure your data, you +need to secure everything. That means, your existing data +must be encrypted before you can use this new capability! + +Follow this steps: + o backup existing db: + $ note -D + o backup the db: + $ cp .notedb .notedb.save + or (for mysql users!): + $ cp -r /usr/local/mysql/data/notedb ~/notedb.mysql.save + o go into note and delete all existing notes: + $ note -d 1-20 (or however) + o now upgrade your note installation: + $ perl Makefile.PL; make install + o re-configure note. Turn $USE_CRYPT on by setting it + to "YES". + o re-initialize your database: + $ note -I note.dump.2323 (or whatever) + note will prompt you for a passphrase. It will be used + by Crypt::CBC for encrypting your data. +From now on, your data is encrypted. You will need the passphrase +you set above for decrypting it! So - don't forget it! + +====================================================== + +AGAIN: YOU HAVE BEEN WARNED! DO NOT UPGRADE WITHOUT MADE A + BACKUP OF YOUR DATABASE! I AM NOT RESPONSIBLE IF YOU + LOOSE DATA! + diff --git a/note-1.0.7/VERSION b/note-1.0.7/VERSION new file mode 100644 index 0000000..af0b7dd --- /dev/null +++ b/note-1.0.7/VERSION @@ -0,0 +1 @@ +1.0.6 diff --git a/note-1.0.7/bin/note b/note-1.0.7/bin/note new file mode 100755 index 0000000..1c2e56a --- /dev/null +++ b/note-1.0.7/bin/note @@ -0,0 +1,1662 @@ +#!/usr/bin/perl +# $Id: note,v 1.29 2000/06/25 20:13:23 scip Exp scip $ +# +# +# note - console notes management with database and encryption support. +# Copyright (C) 1999-2000 Thomas Linden (see README for details!) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# - Thomas Linden +# +# latest version on: +# http://www.daemon.de/software.html +# ftp://www.0x49.org/pub/scip/note/ +# + +use strict; +#use Data::Dumper; +use Getopt::Long; + +# +# prototypes +# +sub usage; # print usage message for us thumb userz :-) +sub find_editor; # returns an external editor for use +sub output; # used by &list and &display +sub C; # print colourized +sub num_bereich; # returns array from "1-4" (1,2,3,4) +sub getdate; # return pretty formatted day +sub new; # crate new note +sub edit; # edit a note +sub del; # delete a note +sub display; # display one or more notes +sub list; # note-listing +sub help; # interactive help screen +sub import; # import from notedb-dump +sub display_tree; # show nice tree-view +sub tree; # build the tree +sub print_tree; # print the tree, contributed by Jens Heunemann . THX! + + +# +# globals +# +my ( + # + # commandline options + # + $opt_, $opt_i, $opt_r, $opt_e, $opt_d, + $opt_s, $opt_t, $opt_T, $opt_l, $opt_L, $opt_c, + $opt_D, $opt_I, $opt_o, $opt_h, $opt_n, $opt_v, + + # + # set from commandline (or interactive) + # + $number, $searchstring, $dump_file, $ImportType, $NewType, $Raw, + + # + # options from config file .noterc + # + $maxlen, $timelen, $TOPIC, $NOTEDB, $MAX_TIME, $PreferredEditor, + $ALWAYS_INT, $KEEP_TIMESTAMP, $COLOR, $ALWAYS_EDIT, $HOME, $FormatText, + $BORDER_COLOR, $NOTE_COLOR, $NUM_COLOR, $TOPIC_COLOR, $MAX_NOTE, + $USE_CRYPT, $CRYPT_METHOD, $TopicSep, $DEFAULT_LIST, $TIME_COLOR, + + # + # db specifics from .noterc + # + $db, $dbname, $dbhost, $dbuser, $dbpasswd, + $table, $fnum, $fnote, $fdate, $date, $dbdriver, $libpath, + + # + # processed colors + # + $BORDERC, $_BORDERC, $NOTEC, $NUMC, $_NUMC, $_NOTEC, $TIMEC, + $_TIMEC, $TOPICC, $_TOPICC, + + # + # config presets + # + $DEFAULTDBNAME, $USER, $PATH, $CONF, + + # + # internals + # + $TYPE, $mode, $NoteKey, + $version, $number, $CurTopic, $CurDepth, $WantTopic, + $sizeof, %TP, $TreeType, $ListType, $SetTitle, + @ArgTopics, $key, $typedef, @NumBlock, $has_nothing, + ); + + +# +# DEFAULTS, allows one to use note without a config +# don't change them, instead use the config file! +# +$maxlen = 30; +$timelen = 22; +$date = &getdate; +$USER = getlogin || getpwuid($<); +chomp $USER; +$HOME = $ENV{'HOME'}; +$CONF = $HOME . "/.noterc"; +$dbdriver = "binary"; +$libpath = "/usr/local/lib"; +$NOTEDB = $HOME . "/.notedb"; +$MAX_NOTE = 4096; +$MAX_TIME = 64; +$COLOR = "YES"; +$BORDER_COLOR = "BLACK"; +$NUM_COLOR = "blue"; +$NOTE_COLOR = "green"; +$TIME_COLOR = "black"; +$TOPIC_COLOR = "BLACK"; +$TOPIC = 1; +$TopicSep = '/'; +$version = "1.0.7"; +if($TOPIC) +{ + $CurDepth = 1; # the current depth inside the topic "directory" structure... +} +$USE_CRYPT = "NO"; + + + + +# +# process command line args +# +if($ARGV[0] eq "") +{ + $mode = "new"; +} +elsif($#ARGV == 0 && $ARGV[0] eq "-") { + $mode = "new"; + $NewType = 1; # read from STDIN until EOF + shift; + undef $has_nothing; +} +else +{ + Getopt::Long::Configure( qw(no_ignore_case)); + GetOptions ( + "interactive|i!" => \$opt_i, # no arg + "config|c=s" => \$opt_c, # string, required + "raw|r!" => \$opt_r, # no arg + "edit|e=i" => \$opt_e, # integer, required + "delete|d=s" => \$opt_d, # integer, required + "search|s=s" => \$opt_s, # string, required + "tree|topic|t!" => \$opt_t, # no arg + "longtopic|T!" => \$opt_T, # no arg + "list|l:s" => \$opt_l, # string, optional + "longlist|L:s" => \$opt_L, # string, optional + "dump||Dump|D:s" => \$opt_D, # string, optional + "import|Import|I:s" => \$opt_I, # string, optional + "overwrite|o!" => \$opt_o, # no arg + "help|h|?!" => \$opt_h, # no arg + "version|v!" => \$opt_v # no arg + ); + $opt_n = shift; # after that @ARGV contains eventually + # a note-number + # $opt_ is a single dash, in case of existence! + # + # determine mode + # + if($opt_i) { + $mode = "interactive"; + } + elsif(defined $opt_l || defined $opt_L) { + $mode = "list"; + if(defined $opt_l) { + @ArgTopics = split /$TopicSep/, $opt_l; + } + else { + $ListType = "LONG"; + @ArgTopics = split /$TopicSep/, $opt_L; + } + $CurDepth += $#ArgTopics + 1 if($opt_l || $opt_L); + $CurTopic = $ArgTopics[$#ArgTopics]; # use the last element everytime... + } + elsif($opt_t || $opt_T) { + $mode = "tree"; + $TreeType = "LONG" if($opt_T); + } + elsif(defined $opt_s) { + $mode = "search"; + $searchstring = $opt_s; + } + elsif($opt_e) { + $mode = "edit"; + $number = $opt_e; + } + elsif($opt_d) { + $mode = "delete"; + $number = $opt_d; + } + elsif(defined $opt_D) { + $mode = "dump"; + if(!$opt_) { + if($opt_D ne "") { + $dump_file = $opt_D; + } + else { + $dump_file = "note.dump.$$"; + print "no dumpfile specified, using $dump_file.\n"; + } + } + else { + $dump_file = "-"; # use STDIN + } + } + elsif(defined $opt_I) { + $mode = "import"; + if(!$opt_) { + if($opt_I ne "") { + $dump_file = $opt_I; + } + else { + print "Import-error! No dump_file specified!\n"; + exit(1); + } + } + else { + $dump_file = "-"; + } + } + elsif($opt_v) { + print "This is note $version by Thomas Linden .\n"; + exit(0); + } + elsif($opt_h) { + &usage; + } + else { + if($opt_c && $mode eq "" && !$opt_n) { + $mode = "new"; + } + elsif($opt_c && $mode eq "") { + $mode = ""; # huh?! + } + else { + $has_nothing = 1; + } + } + ### determine generic options + if($opt_n =~ /^[\d+\-?\,*]+$/) { + # first arg is a digit! + if($mode eq "") { + $number = $opt_n; + $mode = "display"; + undef $has_nothing; + } + else { + print "mode <$mode> does not take a numerical argument!\n"; + exit(1); + } + } + elsif($opt_n ne "") { + print "Unknown option: $opt_n\n"; + &usage; + } + if($opt_r) { + $Raw = 1; + } + if($opt_o) { + $ImportType = "overwrite"; + if(!$opt_I) { + print "--overwrite is only suitable for use with --import!\n"; + exit(1); + } + } + ##### +} +if($has_nothing && $mode eq "") +{ + &usage; +} + + +# read the configfile. +$CONF = $opt_c if($opt_c); # if given by commandline, use this. +if(-e $CONF) +{ + &getconfig($CONF); +} +elsif($opt_c) { + # only wrong, if specified by commandline! else use default values! + print STDERR "Could not open \"$CONF\": file does not exist or permission denied!\n"; + exit(1); +} + + +# Always interactive? +if($ALWAYS_INT eq "YES" && $mode ne "dump" && $mode ne "import") +{ + $mode = "interactive"; +} + +# OK ... Long-Listing shall be default ... You wanted it!!! +if($DEFAULT_LIST eq "LONG") +{ + # takes only precedence in commandline mode + $ListType="LONG"; +} + + + +# *if* loading of the config was successful, try to load the +# configured database backend. Currently supported: mysql and binary. +push @INC, $libpath; +#if($dbdriver eq "mysql") { +# eval { +# require NOTEDB::mysql; +# $db = new NOTEDB($dbdriver, $dbname, $dbhost, $dbuser, $dbpasswd, $table, $fnum, $fnote, $fdate); +# } +#} +if($dbdriver eq "binary") { + eval { + require NOTEDB::binary; + $db = new NOTEDB($dbdriver, $NOTEDB, $MAX_NOTE, $MAX_TIME, $dbdriver); + } +} +else { + eval { + require "NOTEDB/$dbdriver.pm"; + $db = new NOTEDB($dbdriver, $dbname, $dbhost, $dbuser, $dbpasswd, $table, $fnum, $fnote, $fdate); + }; +} +if($@) { + print "Unsupported database backend: NOTEDB::$dbdriver!\n"; + print "The following error has occured:\n------------------------\n" . $@ . "\n------------------------\n"; + exit 1; +} + +# add the backend version to the note version: +$version .= " " . $db->version(); + +# calculate some constants... +$BORDERC = "<$BORDER_COLOR>"; +$_BORDERC = ""; +$NUMC = "<$NUM_COLOR>"; +$_NUMC = ""; +$NOTEC = "<$NOTE_COLOR>"; +$_NOTEC = ""; +$TIMEC = "<$TIME_COLOR>"; +$_TIMEC = ""; +$TOPICC = "<$TOPIC_COLOR>"; +$_TOPICC = ""; + +$NoteKey = $TopicSep . "notes" . $TopicSep; + + +if($ListType ne "LONG" && $mode ne "interactive") +{ + #$maxlen += $timelen; # no time will be displayed! +} + + +# check if the user wants to use encryption: +if($USE_CRYPT eq "YES" && $NOTEDB::crypt_supported == 1) { + if($CRYPT_METHOD eq "") { + $CRYPT_METHOD = "Crypt::IDEA"; + } + if(!exists $ENV{'NOTE_PASSWD'}) { + print "password: "; + eval { + local($|) = 1; + local(*TTY); + open(TTY,"/dev/tty"); + system ("stty -echo ); + print STDERR "\r\n"; + system ("stty echo ; + } + } + else { + $key = $ENV{'NOTE_PASSWD'}; + } + chomp $key; + $db->use_crypt($key,$CRYPT_METHOD); + undef $key; + # verify correctness of passwd + my ($cnote, $cdate) = $db->get_single(1); + if($cdate ne "") { + if($cdate !~ /^\d+\.\d+?/) { + print "access denied.\n"; # decrypted $date is not a number! + exit(1); + } + } #else empty! +} +else { + $db->no_crypt; + # does: NOTEDB::crypt_supported = 0; + my ($cnote, $cdate) = $db->get_single(1); + if($cdate ne "") { + if($cdate !~ /^\d+\.\d+?/) { + print "$NOTEDB seems to be encrypted!\n"; + exit(1); + } + } +} + +# main loop: ############### +if($mode eq "display") +{ + &display; +} +elsif($mode eq "search") +{ + &search; +} +elsif($mode eq "list") +{ + &list; +} +elsif($mode eq "tree") +{ + &display_tree; +} +elsif($mode eq "new") +{ + &new; +} +elsif($mode eq "delete") +{ + del; +} +elsif($mode eq "edit") +{ + &edit; +} +elsif($mode eq "dump") +{ + &dump; +} +elsif($mode eq "import") +{ + &import; +} +elsif($mode eq "interactive") +{ + &interactive; +} +else +{ + #undefined :-( +} + + +exit(0); +################## EOP ################ + + + +############################### DISPLAY ################################## +sub display +{ + my($N,$match,$note,$date,$num); + # display a certain note + print "\n"; + &num_bereich; # get @NumBlock from $numer + foreach $N (@NumBlock) + { + ($note, $date) = $db->get_single($N); + if($note) + { + if($Raw) { + print "$N\n$date\n$note\n\n"; + } + else { + output($N, $note, $date, "SINGLE"); + print "\n"; + } + $match = 1; + } + } + if(!$match) + { + print "no note with that number found!\n"; + } +} +############################### SEARCH ################################## +sub search +{ + my($n,$match,$note,$date,$num,%res); + if($searchstring eq "") + { + print "No searchstring specified!\n"; + } + else { + print "searching the database $dbname for \"$searchstring\"...\n\n"; + + %res = $db->get_search($searchstring); + + foreach $num (sort { $a <=> $b } keys %res) + { + output($num, $res{$num}->{'note'}, $res{$num}->{'date'}); + $match = 1; + } + if(!$match) + { + print "no matching note found!\n"; + } + print "\n"; + } +} + + +############################### LIST ################################## +sub list +{ + my(@topic,@RealTopic, $i,$t,$n,$num,@CurItem,$top,$in,%res); + if($mode ne "interactive" && !$Raw) + { + print "\nList of all existing notes:\n\n"; + } + else { + print "\n"; + } + + # list all available notes (number and firstline) + %res = $db->get_all(); + + if($TOPIC) + { + undef %TP; + } + + foreach $num (sort { $a <=> $b } keys %res) + { + $n = $res{$num}->{'note'}; + $t = $res{$num}->{'date'}; + if($TOPIC) + { + # this allows us to have multiple topics (subtopics!) + my ($firstline,$dummy) = split /\n/, $n, 2; + if($firstline =~ /^($TopicSep)/) + { + @topic = split(/$TopicSep/,$firstline); + } + else + { + @topic = (); + } + # looks like: "\topic\" + # collect a list of topics under the current topic + if($topic[$CurDepth-1] eq $CurTopic && $topic[$CurDepth] ne "") + { + if(exists $TP{$topic[$CurDepth]}) + { + $TP{$topic[$CurDepth]}++; + } + else + { + # only if the next item *is* a topic! + $TP{$topic[$CurDepth]} = 1 if(($CurDepth) <= $#topic); + } + } + elsif($topic[$CurDepth-1] eq $CurTopic || ($topic[$CurDepth] eq "" && $CurDepth ==1)) + { + # cut the topic off the note-text + if($n =~ /^($TopicSep)/) + { + $CurItem[$i]->{'note'} = $dummy; + } + else + { + $CurItem[$i]->{'note'} = $n; + } + # save for later output() call + $CurItem[$i]->{'num'} = $num; + $CurItem[$i]->{'time'} = $t; + $i++; + # use this note for building the $PATH! + if($RealTopic[0] eq "") + { + @RealTopic = @topic; + } + } + } + else + { + output($num, $n, $t); + } + } + if($TOPIC) + { + if($CurTopic ne "") + { + undef $PATH; + foreach (@RealTopic) + { + $PATH .= $_ . $TopicSep; + last if($_ eq $CurTopic); + } + } + else + { + $PATH = $TopicSep; + } + + # we are at top level, print a list of topics... + foreach $top (sort(keys %TP)) + { + output("-", " => ". $top . "$TopicSep ($TP{$top} notes)", + " Sub Topic "); + } + #print Dumper(@CurItem); + for($in=0;$in<$i;$in++) + { + output( $CurItem[$in]->{'num'}, + $CurItem[$in]->{'note'}, + $CurItem[$in]->{'time'} ); + } + } + + print "\n"; +} + +############################### NEW ################################## +sub new +{ + my($TEMP,$editor, $date, $note, $WARN, $c, $line, $num, @topic); + $date = &getdate; + if($ALWAYS_EDIT eq "YES") + { + $TEMP = "/tmp/note.$$"; + # let the user edit it... + $editor = &find_editor; + if($editor) + { + system $editor, $TEMP; + } + else + { + print "Could not find an editor to use!\n"; + exit(0); + } + # read it in ($note) + $note = ""; + open E, "<$TEMP" or $WARN = 1; + if($WARN) + { + print "...edit process interupted! No note has been saved.\n"; + undef $WARN; + return; + } + $c = 0; + while() + { + $note = $note . $_; + } + chomp $note; + close E; + # privacy! + unlink $TEMP; + } + else + { + $note = ""; + $line = ""; + # create a new note + if($NewType) + { + # be silent! read from STDIN until EOF. + while () { $note .= $_; } + } + else + { + print "enter the text of the note, end with .\n"; + do + { + $line = ; + $note = $note . $line; + } until $line eq ".\n"; + # remove the . ! + chop $note; + chop $note; + } + } + + # since we have not number, look for the next available: + $number = $db->get_nextnum(); + if($TOPIC && $CurTopic ne "") + { + @topic = split(/$TopicSep/,$note); + if($topic[1] eq "") + { + $note = $PATH . "\n$note"; + } + } + + + $db->set_new($number,$note,$date); + + # everything ok until here! + print "note stored. it has been assigned the number $number.\n\n"; +} + + +############################### DELETE ################################## +sub del +{ + my($i,@count, $setnum, $pos, $ERR); + # delete a note + &num_bereich; # get @NumBlock from $number + foreach $_ (@NumBlock) + { + $ERR = $db->set_del($_); + if($ERR) + { + print "no note with number $_ found!\n"; + } + else + { + print "note number $_ has been deleted.\n"; + } + } + # recount the notenumbers: + $db->set_recountnums(); + + @NumBlock = (); +} + +############################### EDIT ################################## +sub edit +{ + my($keeptime, $date, $editor, $TEMP, $note, $t, $num, $match); + # edit a note + $date = &getdate; + ($note, $keeptime) = $db->get_single($number); + if($keeptime eq "") + { + print "no note with that number found!\n\n"; + exit(0) if($mode ne "interactive"); + } + $TEMP = "/tmp/note.$USER.$$"; + open NOTE,">$TEMP" or die "Could not open $TEMP\n"; + select NOTE; + + print $note; + close NOTE; + select STDOUT; + $editor = &find_editor; + if($editor) + { + system $editor, $TEMP; + } + else + { + print "Could not find an editor to use!\n"; + exit(0); + } + $note = ""; + open NOTE,"<$TEMP" or die "Could not open $TEMP\n"; + + while() + { + $note = $note . $_; + } + chomp $note; + close NOTE; + + unlink $TEMP; + + if($KEEP_TIMESTAMP eq "YES") + { + $t = $keeptime; + } + else + { + $t = $date; + } + + # we got it, now save to db + $db->set_edit($number, $note, $t); + + print "note number $number has been changed.\n"; +} + + +sub dump +{ + my(%res, $num, $DUMP); + # $dump_file + if($dump_file eq "-") { + $DUMP = *STDOUT; + } + else { + open (DUMPFILE, ">$dump_file") or die "could not open $dump_file\n"; + $DUMP = *DUMPFILE; + } + select $DUMP; + %res = $db->get_all(); + foreach $num (sort { $a <=> $b } keys %res) + { + print STDOUT "dumping note number $num to $dump_file\n" if($dump_file ne "-"); + print "Number: $num\n" + ."Timestamp: $res{$num}->{'date'}\n" + ."$res{$num}->{'note'}\n"; + } + print "\n"; + close(DUMP); + select STDOUT; +} + +sub import +{ + my($num, $start, $complete, $dummi, $note, $date, $time, $number, $stdin, $DUMP); + # open $dump_file and import it into the notedb + $stdin = 1 if($dump_file eq "-"); + if($stdin) { + $DUMP = *STDIN; + } + else { + open (DUMPFILE, "<$dump_file") or die "could not open $dump_file\n"; + $DUMP = *DUMPFILE; + } + $db->set_del_all() if($ImportType ne ""); + $complete=0; + $start = 0; + while(<$DUMP>) + { + chomp $_; + if($_ =~ /^Number:\s\d+/) + { + if($start == 0) + { + # we have no previous record + ($dummi,$number) = split(/\s/,$_); + $start = 1; + } + else + { + # we got a complete record, save it! + $number = $db->get_nextnum(); + $db->set_new($number,$note, $date); + print "note number $number from $dump_file inserted into notedb.\n" if(!$stdin); + $complete = 0; + $note = ""; + $date = ""; + ($dummi,$number) = split(/\s/,$_); + } + } + elsif($_ =~ /^Timestamp:\s\d+/ && $complete == 0) + { + ($dummi,$date,$time) = split(/\s/,$_); + $date = "$date $time"; + $complete = 1; + } + else + { + $note .= $_ . "\n"; + } + } + if($note ne "" && $date ne "") + { + # the last record, if existent + $number = $db->get_nextnum(); + $db->set_new($number,$note, $date); + print "note number $number from $dump_file inserted into notedb.\n" if(!$stdin); + } +} + + + +sub interactive +{ + my($B, $BB, $menu, $char, @LastTopic, $Channel); + $Channel = $|; + # create menu: + $B = ""; + $BB = ""; + $menu = "[" . $B . "L" . $BB . "-List "; + if($TOPIC) { + $menu .= $B . "T" . $BB . "-Topics "; + } + $menu .= $B . "N" . $BB . "-New " + . $B . "D" . $BB . "-Delete " + . $B . "S" . $BB . "-Search " + . $B . "E" . $BB . "-Edit " + . $B . "?" . $BB . "-Help " + . $B . "Q" . $BB . "-Quit] "; # $CurTopic will be empty if $TOPIC is off! + # per default let's list all the stuff: + # Initially do a list command! + $ListType = ($DEFAULT_LIST eq "LONG") ? "LONG" : ""; + &list; + + for(;;) + { + $ListType = ($DEFAULT_LIST eq "LONG") ? "LONG" : ""; + undef $SetTitle; + if($CurDepth > 2) + { + print C $menu . $TOPICC . "../" . $CurTopic . $_TOPICC . ">"; + } + else + { + print C $menu . $TOPICC . $CurTopic . $_TOPICC . ">"; + } + + # endless until user press "Q" or "q"! + $char = ; + #$char = $term->readline(''); + chomp $char; + if($char =~ /^\d+\s*[\di*?,*?\-*?]*$/) + { + $ListType = ""; #overrun + # display notes + $number = $char; + &display; + } + elsif($char =~ /^n$/i) + { + # create a new one + &new; + } + elsif($char =~ /^$/) + { + &list; + } + elsif($char =~ /^l$/) + { + $ListType = ""; + &list; + } + elsif($char =~ /^L$/) + { + $ListType = "LONG"; + &list; + undef $SetTitle; + } + elsif($char =~ /^h$/i || $char =~ /^\?/) + { + # zu dumm der Mensch ;-) + &help; + } + elsif($char =~ /^d\s+([\d*?,*?\-*?]*)$/i) + { + # delete one! + $number = $1; + &del; + } + elsif($char =~ /^d$/i) + { + # we have to ask her: + print "enter number(s) of note(s) you want to delete: "; + $char = ; + chomp $char; + $number = $char; + &del; + } + elsif($char =~ /^e\s+(\d+\-*\,*\d*)/i) + { + # edit one! + $number = $1; + &edit; + } + elsif($char =~ /^e$/i) + { + # we have to ask her: + print "enter number of the note you want to edit: "; + $char = ; + chomp $char; + $number = $char; + &edit; + } + elsif($char =~ /^s\s+/i) + { + # she want's to search + $searchstring = $'; + chomp $searchstring; + &search; + } + elsif($char =~ /^s$/i) + { + # we have to ask her: + print "enter the string you want to search for: "; + $char = ; + chomp $char; + $char =~ s/^\n//; + $searchstring = $char; + &search; + } + elsif($char =~ /^q$/i) + { + # schade!!! + $| = $Channel; + print "\n\ngood bye!\n"; + exit(0); + } + elsif($char =~ /^t$/) + { + $TreeType = ""; + &display_tree; + } + elsif($char =~ /^T$/) + { + $TreeType = "LONG"; + &display_tree; + $TreeType = ""; + } + elsif($char =~ /^\.\.$/ || $char =~ /^cd\s*\.\.$/) + { + $CurDepth-- if ($CurDepth > 1); + $CurTopic = $LastTopic[$CurDepth]; + &list; + } + elsif($char =~ /^l\s+(\w+)$/) + { + # list + $WantTopic = $1; + if(exists $TP{$WantTopic}) + { + my %SaveTP = %TP; + $LastTopic[$CurDepth] = $CurTopic; + $CurTopic = $1; + $CurDepth++; + + &list; + + $CurTopic = $LastTopic[$CurDepth]; + $CurDepth--; + %TP = %SaveTP; + } + else + { + print "\nunknown command!\n"; + } + } + else + { + # unknown + my $unchar = $char; + $unchar =~ s/^cd //; # you may use cd now! + if(exists $TP{$char} || exists $TP{$unchar}) + { + $char = $unchar if(exists $TP{$unchar}); + $LastTopic[$CurDepth] = $CurTopic; + $CurTopic = $char; + $CurDepth++; + &list; + } + else + { + print "\nunknown command!\n"; + } + undef $unchar; + } + } +} + + + +sub usage +{ +print qq~This is the program note $version by Thomas Linden (c) 1999-2000. +It comes with absolutely NO WARRANTY. It is distributed under the +terms of the GNU General Public License. Use it at your own risk :-) +Usage: note [ options ] [ number [,number...]] +Options: +-h --help displays this help screen +-v --version displays the version number +-c --config use another config file than the default \~/.noterc +-l --list [] lists all existing notes If no topic were specified, + it will display a list of all existing topics. +-L --longlist [] the same as -l but prints also the timestamp +-t --topic prints a list of all topics as a tree. +-T --longtopc prints the topic-tree with the notes under each topic +-s --search searches for trough the notes database +-e --edit edit note with +-d --delete delete note with +-D --Dump [ | -] dumps the notes to the textfile . if is simply + a "-" it will printed out to standard output. +-I --Import | - imports a previously dumped textfile into the + note-database. Data will be appended by default. + You can also specify a dash "note -I -" instead of a , + which causes note, silently to read in a dump from STDIN. +-o --overwrite only suitable for use with --Import. Overwrites an + existing notedb. +-r --raw raw mode, output will not be formatted. Works not in interactive + mode, only on cmd-line for list and display. +-i --interactive interactive mode +- if you run note only with one dash: "note -", then it will + read in a new note from STDIN until EOF, this makes it + possible to pipe text into a new note. + + o if you specify only a number (i.e. "note 4"), then the note with that + number will be displayed. + o you can specify more then one number for delete and display, for example: + "note -d 3,4" deletes #3 and #4. "note 5-7" displays #5, #6 and #7. + o if you run note without any parameter and if "AlwaysInteractive" in the config + set off, then note will create a new note and prompt you for new text. + o If it finds \~/.noterc, it will process it. Refer to the manpage for more + informations about the configuration. + o In interactive mode you can get help at any time by typing "?" or "h" at + the prompt. + o If encryption support is turned on, note will ask you for a passphrase every + time it runs. You can avoid this behavior by setting the environment-variable + \$NOTE_PASSWD. You will need this for example, if you call note from a script. +~; + #my ($package, $filename, $line) = caller; + #print "called from line $line\n"; + exit 1; +} + +sub find_editor { + return $PreferredEditor || $ENV{"VISUAL"} || $ENV{"EDITOR"} || "vim" || "vi" || "pico"; +} + +#/ + +sub format { + # make text bold/underlined/inverse using current $NOTEC + # s/\[([^]]*)\]/$param{$1}/g; + my($note) = @_; + if($FormatText) { + my $BN = uc($NOTEC); + my $_BN = uc($_NOTEC); + my $UN = $NOTEC; + $UN =~ s/<(.*)>/<$1_>/; + my $_UN = $UN; + $_UN =~ s/<(.*)>/<\/$1>/; + my $IN = $NOTEC; my $_IN = $_NOTEC; + $IN =~ s/<(.*)>/<$1I>/; + $_IN =~ s/<(.*)>/<$1I>/; + #$note =~ s/ (\*)(.+)(\*) / $BN$2$_BN /g; + #$note =~ s/ (_)(.+)(_) / $UN$2$_UN /g; + #$note =~ s/ (\/)(.+)(\/) / $IN$2$_IN /g; + $note =~ s/\*\*([^\*^\*]*)\*\*/$BN$1$_BN/g; + $note =~ s/__([^_^_]*)__/$UN$1$_UN/g; + $note =~ s/{{([^}^}]*)}}/$IN$1$_IN/g; + } + $note =~ s/(<\/.*>)/$1$NOTEC/g; + $note; +} + +sub output +{ + my($SSS, $LINE, $num, $note, $time, $TYPE, $L, $LONGSPC, $R, $PathLen, $SP, $title, $CUTSPACE, + $len, $diff, $Space, $nlen, $txtlen); + ($num, $note, $time, $TYPE) = @_; + $txtlen = ($ListType eq "LONG") ? $maxlen : $timelen + $maxlen; + + $note = &format($note); + + $SSS = "-" x ($maxlen + 31); + + $nlen = length("$num"); + $LINE = "$BORDERC $SSS $_BORDERC\n"; + $L = $BORDERC . "[" . $_BORDERC; + $LONGSPC = " " x (26 - $nlen); + $R = $BORDERC . "]" . $_BORDERC; + $PathLen = length($PATH); # will be ZERO, if not in TOPIC mode! + if($TYPE ne "SINGLE") + { + if(!$SetTitle) + { + $SP = ""; + # print only if it is the first line! + $SP = " " x ($maxlen - 2 - $PathLen); + if(!$Raw) { + # no title in raw-mode! + print C $LINE; + + print C "$L $NUMC#$_NUMC "; + if($ListType eq "LONG") + { + print C " $TIMEC" . "creation date$_TIMEC "; + } + else + { + print $LONGSPC; + } + if($TOPIC) + { + print C $TOPICC . "$PATH $_TOPICC$SP$R\n"; + } + else + { + print C $NOTEC . "note$_NOTEC$SP$R\n"; + } + + print C $LINE; + } + $SetTitle = 1; + } + $title = ""; + $CUTSPACE = " " x $txtlen; + $note =~ s/\n/$CUTSPACE/g; + $len = length($note); + if($len < ($txtlen - 2 - $nlen)) + { + $diff = $txtlen - $len; + $Space = " " x $diff; + if(!$Raw) { + if($num eq "-") + { + $title = $BORDERC . $TOPICC . "\"" . $note . "\"" . $_TOPICC . $Space . "$_BORDERC"; + } + else + { + $title = $BORDERC . $NOTEC . "\"" . $note . "\"" . $_NOTEC . $Space . "$_BORDERC"; + } + } + else { + $title = $note; + } + } + else + { + $title = substr($note,0,($txtlen - 2 - $nlen)); + if(!$Raw) { + $title = $BORDERC . $NOTEC . "\"" . $title . "...\"$_NOTEC$_BORDERC"; + } + } + if($Raw) { + print "$num "; + print "$time " if($ListType eq "LONG"); + if($title =~ /^ => (.*)$TopicSep (.*)$/) { + $title = "$1$TopicSep $2"; # seems to be a topic! + } + print "$title\n"; + } + else { + # $title should now look as: "A sample note " + print C "$L $NUMC$num$_NUMC $R"; + if($ListType eq "LONG") + { + print C "$L$TIMEC" . $time . " $_TIMEC$R"; + } + print C "$L $NOTEC" . $title . "$_NOTEC $R\n"; + print C $LINE; + } + } + else + { + # we will not reach this in raw-mode, therefore no decision here! + chomp $note; + $Space = " " x (($maxlen + $timelen) - 16); + print C $LINE; + print C "$L $NUMC$num$_NUMC $R$L$TIMEC$time$_TIMEC $Space$R\n"; + print C $LINE; + print C $NOTEC . $note . $_NOTEC . "\n"; + print C $LINE; + } + +} + + + +sub C +{ + my(%Color, $default, $S, $Col, $NC, $T); + # \033[1m%30s\033[0m + %Color = ( 'black' => '0;30', + 'red' => '0;31', + 'green' => '0;32', + 'yellow' => '0;33', + 'blue' => '0;34', + 'magenta' => '0;35', + 'cyan' => '0;36', + 'white' => '0;37', + 'B' => '1;30', + 'BLACK' => '1;30', + 'RED' => '1;31', + 'GREEN' => '1;32', + 'YELLOW' => '1;33', + 'BLUE' => '1;34', + 'MAGENTA' => '1;35', + 'CYAN' => '1;36', + 'WHITE' => '1;37', + 'black_' => '4;30', + 'red_' => '4;31', + 'green_' => '4;32', + 'yellow_' => '4;33', + 'blue_' => '4;34', + 'magenta_' => '4;35', + 'cyan_' => '4;36', + 'white_' => '4;37', + 'blackI' => '7;30', + 'redI' => '7;31', + 'greenI' => '7;32', + 'yellowI' => '7;33', + 'blueI' => '7;34', + 'magentaI' => '7;35', + 'cyanI' => '7;36', + 'whiteI' => '7;37' + ); + $default = "\033[0m"; + $S = $_[0]; + foreach $Col (%Color) + { + if ($S =~ /<$Col>/g) + { + if($COLOR ne "NO") + { + $NC = "\033[" . $Color{$Col} . "m"; + $S =~ s/<$Col>/$NC/g; + $S =~ s/<\/$Col>/$default/g; + } + else + { + $S =~ s/<$Col>//g; + $S =~ s/<\/$Col>//g; + } + } + } + return $S; +} + + + +sub num_bereich +{ + my($m,@LR,@Sorted_LR,$i); + # $number is the one we want to delete! + # But does it contain kommas? + @NumBlock = (); #reset + $m = 0; + if($number =~ /\,/) + { + # accept -d 3,4,7 + @NumBlock = split(/\,/,$number); + } + elsif($number =~ /^\d+\-\d+$/) + { + # accept -d 3-9 + @LR = split(/\-/,$number); + @Sorted_LR = (); + + if($LR[0] > $LR[1]) + { + @Sorted_LR = ($LR[1], $LR[0]); + } + elsif($LR[0] == $LR[1]) + { + # 0 and 1 are the same + @Sorted_LR = ($LR[0], $LR[1]); + } + else + { + @Sorted_LR = ($LR[0], $LR[1]); + } + + for($i=$Sorted_LR[0]; $i<=$Sorted_LR[1]; $i++) + { + # from 3-6 create @NumBlock (3,4,5,6) + $NumBlock[$m] = $i; + $m++; + } + } + else + { + @NumBlock = ($number); + } + +} + +sub getdate +{ + my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + $year += 1900; + $mon += 1; + $mon =~ s/^(\d)$/0$1/; + $hour =~ s/^(\d)$/0$1/; + $min =~ s/^(\d)$/0$1/; + $sec =~ s/^(\d)$/0$1/; + $mday =~ s/^(\d)$/0$1/; + return "$mday.$mon.$year $hour:$min:$sec"; +} + + +sub help +{ +my $B = ""; +my $BB = ""; +my($S, $L, $T, $Q, $H, $N, $D, $E); +$L = $B . "L" . $BB . $NOTEC; +$T = $B . "T" . $BB . $NOTEC; +$Q = $B . "Q" . $BB . $NOTEC; +$H = $B . "?" . $BB . $NOTEC; +$N = $B . "N" . $BB . $NOTEC; +$D = $B . "D" . $BB . $NOTEC; +$E = $B . "E" . $BB . $NOTEC; +$S = $B . "S" . $BB . $NOTEC; + +print C qq~$BORDERC +----------------------------------------------------------------------$_BORDERC $TOPICC +HELP for interactive note $version +$_TOPICC $NOTEC +The following commands are available: +$L List notes. L=long, with timestamp and l=short without timestamp. + You can also just hit for short list. + If you specify a subtopic, then list will display it's contents, + i.e.: "l mytopic" will dislpay notes under mytopic. +$N Create a new note. +$D Delete a note. You can either hit "d 1" or "d 1-4" or just hit "d". + If you don't specify a number, you will be asked for. +$S Search trough the notes database. Usage is similar to Delete, use + a string instead of a number to search for. +$E Edit a note. Usage is similar to Delete but you can only edit note + a time. +$H This help screen. +$Q Exit the program.~; +if($TOPIC) +{ +print C qq~ +$T print a list of all existing topics as a tree. T prints the tree + with all notes under each topic. + + You can change the actual topic by simply typing it's name or by using + the command "cd", i.e. "cd mytopic". You can create a new topic by creating + a new note, the first line must be the topic borderd by slashes, i.e.: + "/newtopic/". The slash is the default topic-sepearator, but you can over- + ride this in the config! If you type just ".." instead of a topic, you will + go one step back in your topic-structure. +~; +} +print C qq~ +$NOTEC +All commands except the List and Topic commands are case insensitive. $_NOTEC $BORDERC +----------------------------------------------------------------------$_BORDERC +~; +} + + +sub display_tree { + # displays a tree of all topics + my(%TREE, %res, $n, $t, $num, @nodes, $firstline, $text, $untext); + %res = $db->get_all(); + foreach $num (keys %res) + { + $n = $res{$num}->{'note'}; + $t = $res{$num}->{'date'}; + # this allows us to have multiple topics (subtopics!) + my ($firstline,$text,$untext) = split /\n/, $n, 3; + if($firstline =~ /^($TopicSep)/) + { + $firstline =~ s/($TopicSep)*$//; #remove TopicSepatator + @nodes = split(/$TopicSep/,$firstline); + } + else + { + @nodes = ();("$TopicSep"); + $text = $firstline; + } + &tree($num, $text, \%TREE, @nodes); + } + #return if ($num == 0); + # now that we have build our tree (in %TREE) go on t display it: + print C $BORDERC . "\n[" . $TopicSep . $BORDERC . "]\n"; + &print_tree(\%{$TREE{''}},"") if(%TREE); + print C $BORDERC . $_BORDERC . "\n"; +} + + +sub tree { + my($num, $text, $LocalTree, $node, @nodes) = @_; + if(@nodes) { + if(! exists $LocalTree->{$node}->{$NoteKey}) { + $LocalTree->{$node}->{$NoteKey} = []; + } + &tree($num, $text, $LocalTree->{$node}, @nodes); + } + else { + if(length($text) > ($maxlen - 5)) { + $text = substr($text, 0, ($maxlen -5)); + } + $text = $text . " (" . $NUMC . "#" . $num . $_NUMC . $NOTEC . ")" . $_NOTEC if($text ne ""); + push @{$LocalTree->{$node}->{$NoteKey}}, $text; + } +} + + +sub print_tree { + # thanks to Jens for his hints and this sub! + my $hashref=shift; + my $prefix=shift; + my @notes=@{$hashref->{$NoteKey}}; + my @subnotes=sort grep { ! /^$NoteKey$/ } keys %$hashref; + if($TreeType eq "LONG") { + for my $note (@notes) { + if($note ne "") { + print C $BORDERC ;# . $prefix. "|\n"; + print C "$prefix+---<" . $NOTEC . $note . $BORDERC . ">" . $_NOTEC . "\n"; + } + } + } + for my $index (0..$#subnotes) { + print C $BORDERC . $prefix. "|\n"; + print C "$prefix+---[" . $TOPICC . $subnotes[$index] . $BORDERC . "]\n"; + &print_tree($hashref->{$subnotes[$index]},($index == $#subnotes?"$prefix ":"$prefix| ")); + } +} + + +sub getconfig +{ + my($configfile) = @_; + my ($home, $value, $option); + # checks are already done, so trust myself and just open it! + open CONFIG, "<$configfile" || die $!; + while() { + chomp; + next if(/^\s*$/ || /^\s*#/); + my ($option,$value) = split /\s\s*=?\s*/, $_, 2; + $value =~ s/\s*$//; + $home = $value if (/^Home/); + $libpath = $value if (/^LibPath/); + $dbdriver = $value if (/^DbDriver/); + $dbhost = $value if (/^DbHost/); + $dbuser = $value if (/^DbUser/); + $dbpasswd = $value if (/^DbPasswd/); + $dbname = $value if (/^DbName/); + $table = $value if (/^DbTable/); + $fnum = $value if (/^FieldNumber/); + $fnote = $value if (/^FieldNote/); + $fdate = $value if (/^FieldDate/); + $NOTEDB = $value if (/^NoteDb/); + $MAX_NOTE = $value if (/^MaxNoteByte/); + $MAX_TIME = $value if (/^MaxTimeByte/); + $CRYPT_METHOD = $value if (/^CryptMethod/); + $USE_CRYPT = "YES" if (/^UseEncryption/ && $value == 1); + $USE_CRYPT = undef if (/^UseEncryption/ && $value == 0); + $ALWAYS_INT = "YES" if (/^AlwaysInteractive/ && $value == 1); + $ALWAYS_INT = undef if (/^AlwaysInteractive/ && $value == 0); + $DEFAULT_LIST = "LONG" if (/^DefaultLong/ && $value == 1); + $DEFAULT_LIST = undef if (/^DefaultLong/ && $value == 0); + $ALWAYS_EDIT = "YES" if (/^AlwaysEditor/ && $value == 1); + $ALWAYS_EDIT = undef if (/^AlwaysEditor/ && $value == 0); + $KEEP_TIMESTAMP = "YES" if (/^KeepTimeStamp/ && $value == 1); + $KEEP_TIMESTAMP = undef if (/^KeepTimeStamp/ && $value == 0); + $COLOR = "YES" if (/^UseColors/ && $value == 1); + $COLOR = "NO" if (/^UseColors/ && $value == 0); + $TopicSep = $value if (/^TopicSeparator/); + $maxlen = $value if (/^MaxLen/); + $BORDER_COLOR = $value if (/^BorderColor/); + $NUM_COLOR = $value if (/^NumberColor/); + $NOTE_COLOR = $value if(/^NoteColor/); + $TIME_COLOR = $value if (/^TimeColor/); + $TOPIC_COLOR = $value if (/^TopicColor/); + $PreferredEditor = $value if (/^PreferredEditor/); + $FormatText = $value if (/^FormatText/); + } + chomp $home; + $home =~ s/\/*$//; # cut eventually / at the end + $HOME = eval($home); + if($NOTEDB =~ /^(~\/)(.*)$/) { + $NOTEDB = "/home/" . $USER . "/" . $2; + } + $libpath =~ s/\/*$//; + + close CONFIG; +} + + + + +__END__ +# +# $Log: note,v $ +# Revision 1.29 2000/06/25 20:13:23 scip +# *** empty log message *** +# +# Revision 1.28 2000/06/25 19:51:51 scip +# changed pattern matching of seraching(\@ ... \E) +# added --config option +# +# Revision 1.27 2000/05/16 23:51:35 thomas +# fixed many option-parsing related bugd! +# +# Revision 1.26 2000/05/13 01:05:17 thomas +# changed config format and fixed some bugs +# as well as some other additions... +# +# Revision 1.25 2000/05/11 23:42:43 thomas +# --tree changed to --topic +# +# Revision 1.24 2000/05/10 22:59:44 thomas +# updated usage to reflect --raw and build it into output +# and display subs. +# +# Revision 1.23 2000/05/10 22:19:04 thomas +# changed to Getopt::Long, added --raw +# +# Revision 1.22 2000/05/01 18:51:40 thomas +# added "-" to sub dump +# +# Revision 1.21 2000/05/01 00:17:27 thomas +# *** empty log message *** +# +# Revision 1.20 2000/04/30 23:31:38 thomas +# added -o and coloured sub help. +# +# Revision 1.19 2000/04/30 16:07:23 thomas +# *** empty log message *** +# +# Revision 1.18 2000/04/30 14:58:21 thomas +# updated the usage and help subs +# +# Revision 1.17 2000/04/30 14:44:38 thomas +# added colors to the tree functions +# +# Revision 1.16 2000/04/30 14:28:38 thomas +# added the t command, which displays a topic-tree. +# and enhanced the list command in interactive mode +# +# Revision 1.15 2000/03/19 23:41:04 thomas +# changed set_del, now no extra TEMP file is required! +# instead I get it from $this->get_all() ! +# Revision 1.14 2000/03/19 22:51:49 thomas +# Bug in NOTEDB::binary fixed, recount of nubers was +# incorrect. +# +# Revision 1.13 2000/03/19 11:53:32 thomas +# edit bug fixed (ude => uen) +# +# Revision 1.12 2000/03/19 03:06:51 thomas +# backend support completed. +# mysql and binary backends now excluded in separate files +# +# Revision 1.11 2000/03/18 00:16:47 thomas +# added NOTEDB::mysql and changed note to work with that. +# thus, from now on there is only one script to maintain and +# it is possible to provide more bacjends as well as making +# additional scripts upon them, i.e. cgi script... +# +# Revision 1.8 2000/03/13 22:48:43 thomas +# small width bug fixed +# +# Revision 1.7 2000/03/08 23:11:19 tom +# added cd +# +# Revision 1.6 2000/03/08 22:50:41 tom +# Added the $KEEP_TIMESTAMP option and fixed a bug regarding topic names +# and invalid resolution of them in case it started with "1 name". +# +# Revision 1.5 2000/02/25 20:59:30 tom +# corrected small timestamp problem in &edit and &new +# +# Revision 1.4 2000/02/25 13:24:11 tom +# fixed a small bug, that caused to use the last line for a note title instead the 2nd. +# +# Revision 1.3 2000/02/25 11:28:53 tom +# all changes from bin version applied to sql version diff --git a/note-1.0.7/config/noterc b/note-1.0.7/config/noterc new file mode 100644 index 0000000..b396d70 --- /dev/null +++ b/note-1.0.7/config/noterc @@ -0,0 +1,148 @@ +# 1.0.6 -*- sh -*- +# This is a sample config for the note script +# There are useful defaults set in note itself. +# +# Copy it to your $HOME as .noterc +# +# note is Copyright (c) 1999-2000 Thomas Linden. +# You can contact me per email: +# +# comments start with #, empty lines will be ignored. +# 1 turns an option on, 0 turns it off. +# An option consists of an atribute-value pair separated +# by minimum one space (more spaces and/or tabs are allowed) + + +# Your home directory, better do not change it! +# can be an environment variable or a path +Home $ENV{'HOME'} + + +# specify the path, where the NOTEDB lib directory +# resides. This will only used if it is not +# installed inside the perl-lib directory structure! +LibPath /usr/local/lib + + +# you need to decide which database backend you want +# to use. Please refer to the corresponding documentation +# for closer information about the certain backend! +# Currently supported types: "binary", "dbm" or "mysql". +# You must also edit/uncomment one section below for the +# backend you want to use! +DbDriver binary + + +# backend specific settings for sql backend +#DbHost localhost +#DbUser you +#DbPasswd +#DbName mynotes +#DbTable note +#FieldNumber number +#FieldNote note +#FieldDate date +#### specific end ### + + +# backend specific settings for binary(default) backend +NoteDb ~/.notedb +# Define the maximum bytes fields can have in a +# note-entry. Do not change MaxTimeByte to less than 64! + +MaxNoteByte 4096 +MaxTimeByte 64 +#### specific end ### + + +# backend specific settings for DBM backend +# this must be an existing directory! +#DbName /home/you/.notedbm +#### specific end ### + +# You can use encryption with note, that means notes and +# timestamps will be stored encrypted. This is supported +# by every db-backend. +# Set to 1 to turn it on. The Default is 0 (off) +UseEncryption 0 + +# Specify the encryption protocol. The appropriate perl +# module needs to be installed. Possible velues are +# IDEA, DES or BLOWFISH, the default is IDEA. +CryptMethod IDEA + + +# You can run note always in interactive mode by simply +# typing "note". Set this option to 1 to turn it on. +# The default is 0 (off). +AlwaysInteractive 0 + + +# In interactive mode, note issues a list command if you +# simply hit enter. By turning this on, it will issue a +# longlist command instead if you hit just enter. +# The default is 0 (off) +DefaultLong 0 + + + +# You can use an external editor everytime from note instead +# of STDIN for creating new notes. Set to 1 to turn it on. +# The default is 0 (off). +AlwaysEditor 0 + + +# uncomment and edit it, if you want to use another +# editor than the default $EDITOR or as fallback vi. +#PreferredEditor emacs + + +# If you dont prefer that note updates the timestamp of a +# note after editing, turn this on. It will +# keep the original timestamp if this option is set. +# The default is 0(off), to turn it on set to 1. +KeepTimeStamp 0 + + +# You can specify your own topic separator here. +# the default topic separator is a normal slash: "/" +# see README for details about topics! +TopicSeparator / + + +# The maximum width for displaying a note, in CHARS. +# Depends on your screen-size. You can set it to +# "auto", if you wish that note sould determine the +# available size, but it experimental, be aware! +MaxLen 30 + + +# note can use colors for output, set this option to +# 1, if you don't want it, or if your terminal does +# not support it, set to 0. The default is 1 (on). +UseColors 1 + + +# Color-definitions of the various items. Will only +# take effect, if "UseColors" is turned on! +BorderColor BLACK +NumberColor blue +NoteColor green +TimeColor black +TopicColor BLACK +# The following colors are available: +# black, red, green, yellow, blue, magenta, cyan and white. +# for bold color write it uppercase (BLACK will be bold black) +# for underlined color append an underscore (blue_ will be underlined blue) +# for inverted color append an "I" (greenI will be inverted green) + + +# Additional to colors, you can also do a little bit of formatting your +# notes (bold, underlined, italic), see README! +# You need to set this Option to 1, if you decide to make use of this +# capabily +FormatText 1 + +# That's all about it for now. +# If you still have any questiosn, please feel free to contact +# me by email: Thomas Linden diff --git a/mysql-db/README b/note-1.0.7/mysql/README similarity index 93% rename from mysql-db/README rename to note-1.0.7/mysql/README index 5376b58..78cc14a 100644 --- a/mysql-db/README +++ b/note-1.0.7/mysql/README @@ -1,4 +1,4 @@ -README for the mysql version of note +README for the mysql database installation for note Requirements ============ @@ -28,7 +28,7 @@ Installation database and the table structure. You might edit the script before running it. - If you getting trouble, i.e. if you have not the + If you are getting trouble, i.e. if you have not the required permissions to do that, please make sure, you can. As user root, you have to give your user the @@ -36,8 +36,6 @@ Installation documentation, how to do that. After that repeat the step above. - As root, copy the perl-script "note" to /usr/bin. - You can find a sample config file within the subdirectory "config" named noterc. There are some special values which you can use to connect to a different database diff --git a/mysql-db/install.sh b/note-1.0.7/mysql/install.sh similarity index 100% rename from mysql-db/install.sh rename to note-1.0.7/mysql/install.sh diff --git a/mysql-db/permissions b/note-1.0.7/mysql/permissions similarity index 100% rename from mysql-db/permissions rename to note-1.0.7/mysql/permissions diff --git a/mysql-db/sql b/note-1.0.7/mysql/sql similarity index 100% rename from mysql-db/sql rename to note-1.0.7/mysql/sql diff --git a/note-1.0.7/note b/note-1.0.7/note new file mode 100755 index 0000000..db622a5 --- /dev/null +++ b/note-1.0.7/note @@ -0,0 +1,1639 @@ +#!/usr/bin/perl +# $Id: note,v 1.27 2000/05/16 23:51:35 thomas Exp thomas $ +# +# +# note - console notes management with database and encryption support. +# Copyright (C) 1999-2000 Thomas Linden (see README for details!) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# - Thomas Linden +# +# latest version on: +# http://www.daemon.de/software.html +# ftp://www.0x49.org/pub/scip/note/ +# + +use strict; +#use Data::Dumper; +use Getopt::Long; + +# +# prototypes +# +sub usage; # print usage message for us thumb userz :-) +sub find_editor; # returns an external editor for use +sub output; # used by &list and &display +sub C; # print colourized +sub num_bereich; # returns array from "1-4" (1,2,3,4) +sub getdate; # return pretty formatted day +sub new; # crate new note +sub edit; # edit a note +sub del; # delete a note +sub display; # display one or more notes +sub list; # note-listing +sub help; # interactive help screen +sub import; # import from notedb-dump +sub display_tree; # show nice tree-view +sub tree; # build the tree +sub print_tree; # print the tree, contributed by Jens Heunemann . THX! + + +# +# globals +# +my ( + # + # commandline options + # + $opt_, $opt_i, $opt_r, $opt_e, $opt_d, + $opt_s, $opt_t, $opt_T, $opt_l, $opt_L, + $opt_D, $opt_I, $opt_o, $opt_h, $opt_n, $opt_v, + + # + # set from commandline (or interactive) + # + $number, $searchstring, $dump_file, $ImportType, $NewType, $Raw, + + # + # options from config file .noterc + # + $maxlen, $timelen, $TOPIC, $NOTEDB, $MAX_TIME, $PreferredEditor, + $ALWAYS_INT, $KEEP_TIMESTAMP, $COLOR, $ALWAYS_EDIT, $HOME, $FormatText, + $BORDER_COLOR, $NOTE_COLOR, $NUM_COLOR, $TOPIC_COLOR, $MAX_NOTE, + $USE_CRYPT, $CRYPT_METHOD, $TopicSep, $DEFAULT_LIST, $TIME_COLOR, + + # + # db specifics from .noterc + # + $db, $dbname, $dbhost, $dbuser, $dbpasswd, + $table, $fnum, $fnote, $fdate, $date, $dbdriver, $libpath, + + # + # processed colors + # + $BORDERC, $_BORDERC, $NOTEC, $NUMC, $_NUMC, $_NOTEC, $TIMEC, + $_TIMEC, $TOPICC, $_TOPICC, + + # + # config presets + # + $DEFAULTDBNAME, $USER, $PATH, $CONF, + + # + # internals + # + $TYPE, $mode, $NoteKey, + $version, $number, $CurTopic, $CurDepth, $WantTopic, + $sizeof, %TP, $TreeType, $ListType, $SetTitle, + @ArgTopics, $key, $typedef, @NumBlock, $has_nothing, + ); + + +# +# DEFAULTS, allows one to use note without a config +# don't change them, instead use the config file! +# +$maxlen = 30; +$timelen = 22; +$date = &getdate; +$USER = getlogin || getpwuid($<); +chomp $USER; +$HOME = $ENV{'HOME'}; +$CONF = $HOME . "/.noterc"; +$dbdriver = "binary"; +$libpath = "/usr/local/lib"; +$NOTEDB = $HOME . "/.notedb"; +$MAX_NOTE = 4096; +$MAX_TIME = 64; +$COLOR = "YES"; +$BORDER_COLOR = "BLACK"; +$NUM_COLOR = "blue"; +$NOTE_COLOR = "green"; +$TIME_COLOR = "black"; +$TOPIC_COLOR = "BLACK"; +$TOPIC = 1; +$TopicSep = '/'; +$version = "1.0.6"; +if($TOPIC) +{ + $CurDepth = 1; # the current depth inside the topic "directory" structure... +} +$USE_CRYPT = "NO"; + + + + +# +# process command line args +# +if($ARGV[0] eq "") +{ + $mode = "new"; +} +elsif($#ARGV == 0 && $ARGV[0] eq "-") { + $mode = "new"; + $NewType = 1; # read from STDIN until EOF + shift; + undef $has_nothing; +} +else +{ + Getopt::Long::Configure( qw(no_ignore_case)); + GetOptions ( + "interactive|i!" => \$opt_i, # no arg + "raw|r!" => \$opt_r, # no arg + "edit|e=i" => \$opt_e, # integer, required + "delete|d=s" => \$opt_d, # integer, required + "search|s=s" => \$opt_s, # string, required + "tree|topic|t!" => \$opt_t, # no arg + "long_tree|T!" => \$opt_T, # no arg + "list|l:s" => \$opt_l, # string, optional + "long_list|L:s" => \$opt_L, # string, optional + "dump|D:s" => \$opt_D, # string, optional + "import|I:s" => \$opt_I, # string, optional + "overwrite|o!" => \$opt_o, # no arg + "help|h|?!" => \$opt_h, # no arg + "version|v!" => \$opt_v # no arg + ); + $opt_n = shift; # after that @ARGV contains eventually + # a note-number + # $opt_ is a single dash, in case of existence! + # + # determine mode + # + if($opt_i) { + $mode = "interactive"; + } + elsif(defined $opt_l || defined $opt_L) { + $mode = "list"; + if(defined $opt_l) { + @ArgTopics = split /$TopicSep/, $opt_l; + } + else { + $ListType = "LONG"; + @ArgTopics = split /$TopicSep/, $opt_L; + } + $CurDepth += $#ArgTopics + 1 if($opt_l || $opt_L); + $CurTopic = $ArgTopics[$#ArgTopics]; # use the last element everytime... + } + elsif($opt_t || $opt_T) { + $mode = "tree"; + $TreeType = "LONG" if($opt_T); + } + elsif(defined $opt_s) { + $mode = "search"; + $searchstring = $opt_s; + } + elsif($opt_e) { + $mode = "edit"; + $number = $opt_e; + } + elsif($opt_d) { + $mode = "delete"; + $number = $opt_d; + } + elsif(defined $opt_D) { + $mode = "dump"; + if(!$opt_) { + if($opt_D ne "") { + $dump_file = $opt_D; + } + else { + $dump_file = "note.dump.$$"; + print "no dumpfile specified, using $dump_file.\n"; + } + } + else { + $dump_file = "-"; # use STDIN + } + } + elsif(defined $opt_I) { + $mode = "import"; + if(!$opt_) { + if($opt_I ne "") { + $dump_file = $opt_I; + } + else { + print "Import-error! No dump_file specified!\n"; + exit(1); + } + } + else { + $dump_file = "-"; + } + } + elsif($opt_v) { + print "This is note $version by Thomas Linden .\n"; + exit(0); + } + elsif($opt_h) { + &usage; + } + else { + $has_nothing = 1; + } + ### determine generic options + if($opt_n =~ /^[\d+\-?\,*]+$/) { + # first arg is a digit! + if($mode eq "") { + $number = $opt_n; + $mode = "display"; + undef $has_nothing; + } + else { + print "mode <$mode> does not take a numerical argument!\n"; + exit(1); + } + } + elsif($opt_n ne "") { + print "Unknown option: $opt_n\n"; + &usage; + } + if($opt_r) { + $Raw = 1; + } + if($opt_o) { + $ImportType = "overwrite"; + if(!$opt_I) { + print "--overwrite is only suitable for use with --import!\n"; + exit(1); + } + } + ##### +} +if($has_nothing && $mode eq "") +{ + &usage; +} + + +# read the configfile. +if(-e $CONF) +{ + &getconfig($CONF); +} + + +# Always interactive? +if($ALWAYS_INT eq "YES" && $mode ne "dump" && $mode ne "import") +{ + $mode = "interactive"; +} + +# OK ... Long-Listing shall be default ... You wanted it!!! +if($DEFAULT_LIST eq "LONG") +{ + # takes only precedence in commandline mode + $ListType="LONG"; +} + + + +# *if* loading of the config was successful, try to load the +# configured database backend. Currently supported: mysql and binary. +push @INC, $libpath; +#if($dbdriver eq "mysql") { +# eval { +# require NOTEDB::mysql; +# $db = new NOTEDB($dbdriver, $dbname, $dbhost, $dbuser, $dbpasswd, $table, $fnum, $fnote, $fdate); +# } +#} +if($dbdriver eq "binary") { + eval { + require NOTEDB::binary; + $db = new NOTEDB($dbdriver, $NOTEDB, $MAX_NOTE, $MAX_TIME, $dbdriver); + } +} +else { + eval { + require "NOTEDB/$dbdriver.pm"; + $db = new NOTEDB($dbdriver, $dbname, $dbhost, $dbuser, $dbpasswd, $table, $fnum, $fnote, $fdate); + }; +} +if($@) { + print "Unsupported database backend: NOTEDB::$dbdriver!\n"; + print "The following error has occured:\n------------------------\n" . $@ . "\n------------------------\n"; + exit 1; +} + +# add the backend version to the note version: +$version .= " " . $db->version(); + +# calculate some constants... +$BORDERC = "<$BORDER_COLOR>"; +$_BORDERC = ""; +$NUMC = "<$NUM_COLOR>"; +$_NUMC = ""; +$NOTEC = "<$NOTE_COLOR>"; +$_NOTEC = ""; +$TIMEC = "<$TIME_COLOR>"; +$_TIMEC = ""; +$TOPICC = "<$TOPIC_COLOR>"; +$_TOPICC = ""; + +$NoteKey = $TopicSep . "notes" . $TopicSep; + + +if($ListType ne "LONG" && $mode ne "interactive") +{ + #$maxlen += $timelen; # no time will be displayed! +} + + +# check if the user wants to use encryption: +if($USE_CRYPT eq "YES" && $NOTEDB::crypt_supported == 1) { + if($CRYPT_METHOD eq "") { + $CRYPT_METHOD = "Crypt::IDEA"; + } + if(!exists $ENV{'NOTE_PASSWD'}) { + print "password: "; + eval { + local($|) = 1; + local(*TTY); + open(TTY,"/dev/tty"); + system ("stty -echo ); + print STDERR "\r\n"; + system ("stty echo ; + } + } + else { + $key = $ENV{'NOTE_PASSWD'}; + } + chomp $key; + $db->use_crypt($key,$CRYPT_METHOD); + undef $key; + # verify correctness of passwd + my ($cnote, $cdate) = $db->get_single(1); + if($cdate ne "") { + if($cdate !~ /^\d+\.\d+?/) { + print "access denied.\n"; # decrypted $date is not a number! + exit(1); + } + } #else empty! +} +else { + $db->no_crypt; + # does: NOTEDB::crypt_supported = 0; + my ($cnote, $cdate) = $db->get_single(1); + if($cdate ne "") { + if($cdate !~ /^\d+\.\d+?/) { + print "$NOTEDB seems to be encrypted!\n"; + exit(1); + } + } +} + +# main loop: ############### +if($mode eq "display") +{ + &display; +} +elsif($mode eq "search") +{ + &search; +} +elsif($mode eq "list") +{ + &list; +} +elsif($mode eq "tree") +{ + &display_tree; +} +elsif($mode eq "new") +{ + &new; +} +elsif($mode eq "delete") +{ + del; +} +elsif($mode eq "edit") +{ + &edit; +} +elsif($mode eq "dump") +{ + &dump; +} +elsif($mode eq "import") +{ + &import; +} +elsif($mode eq "interactive") +{ + &interactive; +} +else +{ + #undefined :-( +} + + +exit(0); +################## EOP ################ + + + +############################### DISPLAY ################################## +sub display +{ + my($N,$match,$note,$date,$num); + # display a certain note + print "\n"; + &num_bereich; # get @NumBlock from $numer + foreach $N (@NumBlock) + { + ($note, $date) = $db->get_single($N); + if($note) + { + if($Raw) { + print "$N\n$date\n$note\n\n"; + } + else { + output($N, $note, $date, "SINGLE"); + print "\n"; + } + $match = 1; + } + } + if(!$match) + { + print "no note with that number found!\n"; + } +} +############################### SEARCH ################################## +sub search +{ + my($n,$match,$note,$date,$num,%res); + if($searchstring eq "") + { + print "No searchstring specified!\n"; + } + else { + print "searching the database $dbname for \"$searchstring\"...\n\n"; + + %res = $db->get_search($searchstring); + + foreach $num (sort { $a <=> $b } keys %res) + { + output($num, $res{$num}->{'note'}, $res{$num}->{'date'}); + $match = 1; + } + if(!$match) + { + print "no matching note found!\n"; + } + print "\n"; + } +} + + +############################### LIST ################################## +sub list +{ + my(@topic,@RealTopic, $i,$t,$n,$num,@CurItem,$top,$in,%res); + if($mode ne "interactive" && !$Raw) + { + print "\nList of all existing notes:\n\n"; + } + else { + print "\n"; + } + + # list all available notes (number and firstline) + %res = $db->get_all(); + + if($TOPIC) + { + undef %TP; + } + + foreach $num (sort { $a <=> $b } keys %res) + { + $n = $res{$num}->{'note'}; + $t = $res{$num}->{'date'}; + if($TOPIC) + { + # this allows us to have multiple topics (subtopics!) + my ($firstline,$dummy) = split /\n/, $n, 2; + if($firstline =~ /^($TopicSep)/) + { + @topic = split(/$TopicSep/,$firstline); + } + else + { + @topic = (); + } + # looks like: "\topic\" + # collect a list of topics under the current topic + if($topic[$CurDepth-1] eq $CurTopic && $topic[$CurDepth] ne "") + { + if(exists $TP{$topic[$CurDepth]}) + { + $TP{$topic[$CurDepth]}++; + } + else + { + # only if the next item *is* a topic! + $TP{$topic[$CurDepth]} = 1 if(($CurDepth) <= $#topic); + } + } + elsif($topic[$CurDepth-1] eq $CurTopic || ($topic[$CurDepth] eq "" && $CurDepth ==1)) + { + # cut the topic off the note-text + if($n =~ /^($TopicSep)/) + { + $CurItem[$i]->{'note'} = $dummy; + } + else + { + $CurItem[$i]->{'note'} = $n; + } + # save for later output() call + $CurItem[$i]->{'num'} = $num; + $CurItem[$i]->{'time'} = $t; + $i++; + # use this note for building the $PATH! + if($RealTopic[0] eq "") + { + @RealTopic = @topic; + } + } + } + else + { + output($num, $n, $t); + } + } + if($TOPIC) + { + if($CurTopic ne "") + { + undef $PATH; + foreach (@RealTopic) + { + $PATH .= $_ . $TopicSep; + last if($_ eq $CurTopic); + } + } + else + { + $PATH = $TopicSep; + } + + # we are at top level, print a list of topics... + foreach $top (sort(keys %TP)) + { + output("-", " => ". $top . "$TopicSep ($TP{$top} notes)", + " Sub Topic "); + } + #print Dumper(@CurItem); + for($in=0;$in<$i;$in++) + { + output( $CurItem[$in]->{'num'}, + $CurItem[$in]->{'note'}, + $CurItem[$in]->{'time'} ); + } + } + + print "\n"; +} + +############################### NEW ################################## +sub new +{ + my($TEMP,$editor, $date, $note, $WARN, $c, $line, $num, @topic); + $date = &getdate; + if($ALWAYS_EDIT eq "YES") + { + $TEMP = "/tmp/note.$$"; + # let the user edit it... + $editor = &find_editor; + if($editor) + { + system $editor, $TEMP; + } + else + { + print "Could not find an editor to use!\n"; + exit(0); + } + # read it in ($note) + $note = ""; + open E, "<$TEMP" or $WARN = 1; + if($WARN) + { + print "...edit process interupted! No note has been saved.\n"; + undef $WARN; + return; + } + $c = 0; + while() + { + $note = $note . $_; + } + chomp $note; + close E; + # privacy! + unlink $TEMP; + } + else + { + $note = ""; + $line = ""; + # create a new note + if($NewType) + { + # be silent! read from STDIN until EOF. + while () { $note .= $_; } + } + else + { + print "enter the text of the note, end with .\n"; + do + { + $line = ; + $note = $note . $line; + } until $line eq ".\n"; + # remove the . ! + chop $note; + chop $note; + } + } + + # since we have not number, look for the next available: + $number = $db->get_nextnum(); + if($TOPIC && $CurTopic ne "") + { + @topic = split(/$TopicSep/,$note); + if($topic[1] eq "") + { + $note = $PATH . "\n$note"; + } + } + + + $db->set_new($number,$note,$date); + + # everything ok until here! + print "note stored. it has been assigned the number $number.\n\n"; +} + + +############################### DELETE ################################## +sub del +{ + my($i,@count, $setnum, $pos, $ERR); + # delete a note + &num_bereich; # get @NumBlock from $number + foreach $_ (@NumBlock) + { + $ERR = $db->set_del($_); + if($ERR) + { + print "no note with number $_ found!\n"; + } + else + { + print "note number $_ has been deleted.\n"; + } + } + # recount the notenumbers: + $db->set_recountnums(); + + @NumBlock = (); +} + +############################### EDIT ################################## +sub edit +{ + my($keeptime, $date, $editor, $TEMP, $note, $t, $num, $match); + # edit a note + $date = &getdate; + ($note, $keeptime) = $db->get_single($number); + if($keeptime eq "") + { + print "no note with that number found!\n\n"; + exit(0) if($mode ne "interactive"); + } + $TEMP = "/tmp/note.$USER.$$"; + open NOTE,">$TEMP" or die "Could not open $TEMP\n"; + select NOTE; + + print $note; + close NOTE; + select STDOUT; + $editor = &find_editor; + if($editor) + { + system $editor, $TEMP; + } + else + { + print "Could not find an editor to use!\n"; + exit(0); + } + $note = ""; + open NOTE,"<$TEMP" or die "Could not open $TEMP\n"; + + while() + { + $note = $note . $_; + } + chomp $note; + close NOTE; + + unlink $TEMP; + + if($KEEP_TIMESTAMP eq "YES") + { + $t = $keeptime; + } + else + { + $t = $date; + } + + # we got it, now save to db + $db->set_edit($number, $note, $t); + + print "note number $number has been changed.\n"; +} + + +sub dump +{ + my(%res, $num, $DUMP); + # $dump_file + if($dump_file eq "-") { + $DUMP = *STDOUT; + } + else { + open (DUMPFILE, ">$dump_file") or die "could not open $dump_file\n"; + $DUMP = *DUMPFILE; + } + select $DUMP; + %res = $db->get_all(); + foreach $num (sort { $a <=> $b } keys %res) + { + print STDOUT "dumping note number $num to $dump_file\n" if($dump_file ne "-"); + print "Number: $num\n" + ."Timestamp: $res{$num}->{'date'}\n" + ."$res{$num}->{'note'}\n"; + } + print "\n"; + close(DUMP); + select STDOUT; +} + +sub import +{ + my($num, $start, $complete, $dummi, $note, $date, $time, $number, $stdin, $DUMP); + # open $dump_file and import it into the notedb + $stdin = 1 if($dump_file eq "-"); + if($stdin) { + $DUMP = *STDIN; + } + else { + open (DUMPFILE, "<$dump_file") or die "could not open $dump_file\n"; + $DUMP = *DUMPFILE; + } + $db->set_del_all() if($ImportType ne ""); + $complete=0; + $start = 0; + while(<$DUMP>) + { + chomp $_; + if($_ =~ /^Number:\s\d+/) + { + if($start == 0) + { + # we have no previous record + ($dummi,$number) = split(/\s/,$_); + $start = 1; + } + else + { + # we got a complete record, save it! + $number = $db->get_nextnum(); + $db->set_new($number,$note, $date); + print "note number $number from $dump_file inserted into notedb.\n" if(!$stdin); + $complete = 0; + $note = ""; + $date = ""; + ($dummi,$number) = split(/\s/,$_); + } + } + elsif($_ =~ /^Timestamp:\s\d+/ && $complete == 0) + { + ($dummi,$date,$time) = split(/\s/,$_); + $date = "$date $time"; + $complete = 1; + } + else + { + $note .= $_ . "\n"; + } + } + if($note ne "" && $date ne "") + { + # the last record, if existent + $number = $db->get_nextnum(); + $db->set_new($number,$note, $date); + print "note number $number from $dump_file inserted into notedb.\n" if(!$stdin); + } +} + + + +sub interactive +{ + my($B, $BB, $menu, $char, @LastTopic, $Channel); + $Channel = $|; + # create menu: + $B = ""; + $BB = ""; + $menu = "[" . $B . "L" . $BB . "-List "; + if($TOPIC) { + $menu .= $B . "T" . $BB . "-Topics "; + } + $menu .= $B . "N" . $BB . "-New " + . $B . "D" . $BB . "-Delete " + . $B . "S" . $BB . "-Search " + . $B . "E" . $BB . "-Edit " + . $B . "?" . $BB . "-Help " + . $B . "Q" . $BB . "-Quit] "; # $CurTopic will be empty if $TOPIC is off! + # per default let's list all the stuff: + # Initially do a list command! + $ListType = ($DEFAULT_LIST eq "LONG") ? "LONG" : ""; + &list; + + for(;;) + { + $ListType = ($DEFAULT_LIST eq "LONG") ? "LONG" : ""; + undef $SetTitle; + if($CurDepth > 2) + { + print C $menu . $TOPICC . "../" . $CurTopic . $_TOPICC . ">"; + } + else + { + print C $menu . $TOPICC . $CurTopic . $_TOPICC . ">"; + } + + # endless until user press "Q" or "q"! + $char = ; + #$char = $term->readline(''); + chomp $char; + if($char =~ /^\d+\s*[\di*?,*?\-*?]*$/) + { + $ListType = ""; #overrun + # display notes + $number = $char; + &display; + } + elsif($char =~ /^n$/i) + { + # create a new one + &new; + } + elsif($char =~ /^$/) + { + &list; + } + elsif($char =~ /^l$/) + { + $ListType = ""; + &list; + } + elsif($char =~ /^L$/) + { + $ListType = "LONG"; + &list; + undef $SetTitle; + } + elsif($char =~ /^h$/i || $char =~ /^\?/) + { + # zu dumm der Mensch ;-) + &help; + } + elsif($char =~ /^d\s+([\d*?,*?\-*?]*)$/i) + { + # delete one! + $number = $1; + &del; + } + elsif($char =~ /^d$/i) + { + # we have to ask her: + print "enter number(s) of note(s) you want to delete: "; + $char = ; + chomp $char; + $number = $char; + &del; + } + elsif($char =~ /^e\s+(\d+\-*\,*\d*)/i) + { + # edit one! + $number = $1; + &edit; + } + elsif($char =~ /^e$/i) + { + # we have to ask her: + print "enter number of the note you want to edit: "; + $char = ; + chomp $char; + $number = $char; + &edit; + } + elsif($char =~ /^s\s+/i) + { + # she want's to search + $searchstring = $'; + chomp $searchstring; + &search; + } + elsif($char =~ /^s$/i) + { + # we have to ask her: + print "enter the string you want to search for: "; + $char = ; + chomp $char; + $char =~ s/^\n//; + $searchstring = $char; + &search; + } + elsif($char =~ /^q$/i) + { + # schade!!! + $| = $Channel; + print "\n\ngood bye!\n"; + exit(0); + } + elsif($char =~ /^t$/) + { + $TreeType = ""; + &display_tree; + } + elsif($char =~ /^T$/) + { + $TreeType = "LONG"; + &display_tree; + $TreeType = ""; + } + elsif($char =~ /^\.\.$/ || $char =~ /^cd\s*\.\.$/) + { + $CurDepth-- if ($CurDepth > 1); + $CurTopic = $LastTopic[$CurDepth]; + &list; + } + elsif($char =~ /^l\s+(\w+)$/) + { + # list + $WantTopic = $1; + if(exists $TP{$WantTopic}) + { + my %SaveTP = %TP; + $LastTopic[$CurDepth] = $CurTopic; + $CurTopic = $1; + $CurDepth++; + + &list; + + $CurTopic = $LastTopic[$CurDepth]; + $CurDepth--; + %TP = %SaveTP; + } + else + { + print "\nunknown command!\n"; + } + } + else + { + # unknown + my $unchar = $char; + $unchar =~ s/^cd //; # you may use cd now! + if(exists $TP{$char} || exists $TP{$unchar}) + { + $char = $unchar if(exists $TP{$unchar}); + $LastTopic[$CurDepth] = $CurTopic; + $CurTopic = $char; + $CurDepth++; + &list; + } + else + { + print "\nunknown command!\n"; + } + undef $unchar; + } + } +} + + + +sub usage +{ +print qq~This is the program note $version by Thomas Linden (c) 1999-2000. +It comes with absolutely NO WARRANTY. It is distributed under the +terms of the GNU General Public License. Use it at your own risk :-) +Usage: note [ options ] [ number [,number...]] +Options: +-h --help displays this help screen +-v --version displays the version number +-l --list [] lists all existing notes If no topic were specified, + it will display a list of all existing topics. +-L --longlist [] the same as -l but prints also the timestamp +-t --topic prints a list of all topics as a tree. +-T --longtopc prints the topic-tree with the notes under each topic +-s --search searches for trough the notes database +-e --edit edit note with +-d --delete delete note with +-D --Dump [ | -] dumps the notes to the textfile . if is simply + a "-" it will printed out to standard output. +-I --Import | - imports a previously dumped textfile into the + note-database. Data will be appended by default. + You can also specify a dash "note -I -" instead of a , + which causes note, silently to read in a dump from STDIN. +-o --overwrite only suitable for use with --Import. Overwrites an + existing notedb. +-r --raw raw mode, output will not be formatted. Works not in interactive + mode, only on cmd-line for list and display. +-i --interactive interactive mode +- if you run note only with one dash: "note -", then it will + read in a new note from STDIN until EOF, this makes it + possible to pipe text into a new note. + + o if you specify only a number (i.e. "note 4"), then the note with that + number will be displayed. + o you can specify more then one number for delete and display, for example: + "note -d 3,4" deletes #3 and #4. "note 5-7" displays #5, #6 and #7. + o if you run note without any parameter and if "AlwaysInteractive" in the config + set off, then note will create a new note and prompt you for new text. + o If it finds \~/.noterc, it will process it. Refer to the manpage for more + informations about the configuration. + o In interactive mode you can get help at any time by typing "?" or "h" at + the prompt. + o If encryption support is turned on, note will ask you for a passphrase every + time it runs. You can avoid this behavior by setting the environment-variable + \$NOTE_PASSWD. You will need this for example, if you call note from a script. +~; + #my ($package, $filename, $line) = caller; + #print "called from line $line\n"; + exit 1; +} + +sub find_editor { + return $PreferredEditor || $ENV{"VISUAL"} || $ENV{"EDITOR"} || "vim" || "vi" || "pico"; +} + +#/ + +sub format { + # make text bold/underlined/inverse using current $NOTEC + # s/\[([^]]*)\]/$param{$1}/g; + my($note) = @_; + if($FormatText) { + my $BN = uc($NOTEC); + my $_BN = uc($_NOTEC); + my $UN = $NOTEC; + $UN =~ s/<(.*)>/<$1_>/; + my $_UN = $UN; + $_UN =~ s/<(.*)>/<\/$1>/; + my $IN = $NOTEC; my $_IN = $_NOTEC; + $IN =~ s/<(.*)>/<$1I>/; + $_IN =~ s/<(.*)>/<$1I>/; + #$note =~ s/ (\*)(.+)(\*) / $BN$2$_BN /g; + #$note =~ s/ (_)(.+)(_) / $UN$2$_UN /g; + #$note =~ s/ (\/)(.+)(\/) / $IN$2$_IN /g; + $note =~ s/\*\*([^\*^\*]*)\*\*/$BN$1$_BN/g; + $note =~ s/__([^_^_]*)__/$UN$1$_UN/g; + $note =~ s/{{([^}^}]*)}}/$IN$1$_IN/g; + } + $note =~ s/(<\/.*>)/$1$NOTEC/g; + $note; +} + +sub output +{ + my($SSS, $LINE, $num, $note, $time, $TYPE, $L, $LONGSPC, $R, $PathLen, $SP, $title, $CUTSPACE, + $len, $diff, $Space, $nlen, $txtlen); + ($num, $note, $time, $TYPE) = @_; + $txtlen = ($ListType eq "LONG") ? $maxlen : $timelen + $maxlen; + + $note = &format($note); + + $SSS = "-" x ($maxlen + 31); + + $nlen = length("$num"); + $LINE = "$BORDERC $SSS $_BORDERC\n"; + $L = $BORDERC . "[" . $_BORDERC; + $LONGSPC = " " x (26 - $nlen); + $R = $BORDERC . "]" . $_BORDERC; + $PathLen = length($PATH); # will be ZERO, if not in TOPIC mode! + if($TYPE ne "SINGLE") + { + if(!$SetTitle) + { + $SP = ""; + # print only if it is the first line! + $SP = " " x ($maxlen - 2 - $PathLen); + if(!$Raw) { + # no title in raw-mode! + print C $LINE; + + print C "$L $NUMC#$_NUMC "; + if($ListType eq "LONG") + { + print C " $TIMEC" . "creation date$_TIMEC "; + } + else + { + print $LONGSPC; + } + if($TOPIC) + { + print C $TOPICC . "$PATH $_TOPICC$SP$R\n"; + } + else + { + print C $NOTEC . "note$_NOTEC$SP$R\n"; + } + + print C $LINE; + } + $SetTitle = 1; + } + $title = ""; + $CUTSPACE = " " x $txtlen; + $note =~ s/\n/$CUTSPACE/g; + $len = length($note); + if($len < ($txtlen - 2 - $nlen)) + { + $diff = $txtlen - $len; + $Space = " " x $diff; + if(!$Raw) { + if($num eq "-") + { + $title = $BORDERC . $TOPICC . "\"" . $note . "\"" . $_TOPICC . $Space . "$_BORDERC"; + } + else + { + $title = $BORDERC . $NOTEC . "\"" . $note . "\"" . $_NOTEC . $Space . "$_BORDERC"; + } + } + else { + $title = $note; + } + } + else + { + $title = substr($note,0,($txtlen - 2 - $nlen)); + if(!$Raw) { + $title = $BORDERC . $NOTEC . "\"" . $title . "...\"$_NOTEC$_BORDERC"; + } + } + if($Raw) { + print "$num "; + print "$time " if($ListType eq "LONG"); + if($title =~ /^ => (.*)$TopicSep (.*)$/) { + $title = "$1$TopicSep $2"; # seems to be a topic! + } + print "$title\n"; + } + else { + # $title should now look as: "A sample note " + print C "$L $NUMC$num$_NUMC $R"; + if($ListType eq "LONG") + { + print C "$L$TIMEC" . $time . " $_TIMEC$R"; + } + print C "$L $NOTEC" . $title . "$_NOTEC $R\n"; + print C $LINE; + } + } + else + { + # we will not reach this in raw-mode, therefore no decision here! + chomp $note; + $Space = " " x (($maxlen + $timelen) - 16); + print C $LINE; + print C "$L $NUMC$num$_NUMC $R$L$TIMEC$time$_TIMEC $Space$R\n"; + print C $LINE; + print C $NOTEC . $note . $_NOTEC . "\n"; + print C $LINE; + } + +} + + + +sub C +{ + my(%Color, $default, $S, $Col, $NC, $T); + # \033[1m%30s\033[0m + %Color = ( 'black' => '0;30', + 'red' => '0;31', + 'green' => '0;32', + 'yellow' => '0;33', + 'blue' => '0;34', + 'magenta' => '0;35', + 'cyan' => '0;36', + 'white' => '0;37', + 'B' => '1;30', + 'BLACK' => '1;30', + 'RED' => '1;31', + 'GREEN' => '1;32', + 'YELLOW' => '1;33', + 'BLUE' => '1;34', + 'MAGENTA' => '1;35', + 'CYAN' => '1;36', + 'WHITE' => '1;37', + 'black_' => '4;30', + 'red_' => '4;31', + 'green_' => '4;32', + 'yellow_' => '4;33', + 'blue_' => '4;34', + 'magenta_' => '4;35', + 'cyan_' => '4;36', + 'white_' => '4;37', + 'blackI' => '7;30', + 'redI' => '7;31', + 'greenI' => '7;32', + 'yellowI' => '7;33', + 'blueI' => '7;34', + 'magentaI' => '7;35', + 'cyanI' => '7;36', + 'whiteI' => '7;37' + ); + $default = "\033[0m"; + $S = $_[0]; + foreach $Col (%Color) + { + if ($S =~ /<$Col>/g) + { + if($COLOR ne "NO") + { + $NC = "\033[" . $Color{$Col} . "m"; + $S =~ s/<$Col>/$NC/g; + $S =~ s/<\/$Col>/$default/g; + } + else + { + $S =~ s/<$Col>//g; + $S =~ s/<\/$Col>//g; + } + } + } + return $S; +} + + + +sub num_bereich +{ + my($m,@LR,@Sorted_LR,$i); + # $number is the one we want to delete! + # But does it contain kommas? + @NumBlock = (); #reset + $m = 0; + if($number =~ /\,/) + { + # accept -d 3,4,7 + @NumBlock = split(/\,/,$number); + } + elsif($number =~ /^\d+\-\d+$/) + { + # accept -d 3-9 + @LR = split(/\-/,$number); + @Sorted_LR = (); + + if($LR[0] > $LR[1]) + { + @Sorted_LR = ($LR[1], $LR[0]); + } + elsif($LR[0] == $LR[1]) + { + # 0 and 1 are the same + @Sorted_LR = ($LR[0], $LR[1]); + } + else + { + @Sorted_LR = ($LR[0], $LR[1]); + } + + for($i=$Sorted_LR[0]; $i<=$Sorted_LR[1]; $i++) + { + # from 3-6 create @NumBlock (3,4,5,6) + $NumBlock[$m] = $i; + $m++; + } + } + else + { + @NumBlock = ($number); + } + +} + +sub getdate +{ + my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + $year += 1900; + $mon += 1; + $mon =~ s/^(\d)$/0$1/; + $hour =~ s/^(\d)$/0$1/; + $min =~ s/^(\d)$/0$1/; + $sec =~ s/^(\d)$/0$1/; + $mday =~ s/^(\d)$/0$1/; + return "$mday.$mon.$year $hour:$min:$sec"; +} + + +sub help +{ +my $B = ""; +my $BB = ""; +my($S, $L, $T, $Q, $H, $N, $D, $E); +$L = $B . "L" . $BB . $NOTEC; +$T = $B . "T" . $BB . $NOTEC; +$Q = $B . "Q" . $BB . $NOTEC; +$H = $B . "?" . $BB . $NOTEC; +$N = $B . "N" . $BB . $NOTEC; +$D = $B . "D" . $BB . $NOTEC; +$E = $B . "E" . $BB . $NOTEC; +$S = $B . "S" . $BB . $NOTEC; + +print C qq~$BORDERC +----------------------------------------------------------------------$_BORDERC $TOPICC +HELP for interactive note $version +$_TOPICC $NOTEC +The following commands are available: +$L List notes. L=long, with timestamp and l=short without timestamp. + You can also just hit for short list. + If you specify a subtopic, then list will display it's contents, + i.e.: "l mytopic" will dislpay notes under mytopic. +$N Create a new note. +$D Delete a note. You can either hit "d 1" or "d 1-4" or just hit "d". + If you don't specify a number, you will be asked for. +$S Search trough the notes database. Usage is similar to Delete, use + a string instead of a number to search for. +$E Edit a note. Usage is similar to Delete but you can only edit note + a time. +$H This help screen. +$Q Exit the program.~; +if($TOPIC) +{ +print C qq~ +$T print a list of all existing topics as a tree. T prints the tree + with all notes under each topic. + + You can change the actual topic by simply typing it's name or by using + the command "cd", i.e. "cd mytopic". You can create a new topic by creating + a new note, the first line must be the topic borderd by slashes, i.e.: + "/newtopic/". The slash is the default topic-sepearator, but you can over- + ride this in the config! If you type just ".." instead of a topic, you will + go one step back in your topic-structure. +~; +} +print C qq~ +$NOTEC +All commands except the List and Topic commands are case insensitive. $_NOTEC $BORDERC +----------------------------------------------------------------------$_BORDERC +~; +} + + +sub display_tree { + # displays a tree of all topics + my(%TREE, %res, $n, $t, $num, @nodes, $firstline, $text, $untext); + %res = $db->get_all(); + foreach $num (keys %res) + { + $n = $res{$num}->{'note'}; + $t = $res{$num}->{'date'}; + # this allows us to have multiple topics (subtopics!) + my ($firstline,$text,$untext) = split /\n/, $n, 3; + if($firstline =~ /^($TopicSep)/) + { + $firstline =~ s/($TopicSep)*$//; #remove TopicSepatator + @nodes = split(/$TopicSep/,$firstline); + } + else + { + @nodes = ();("$TopicSep"); + $text = $firstline; + } + &tree($num, $text, \%TREE, @nodes); + } + #return if ($num == 0); + # now that we have build our tree (in %TREE) go on t display it: + print C $BORDERC . "\n[" . $TopicSep . $BORDERC . "]\n"; + &print_tree(\%{$TREE{''}},"") if(%TREE); + print C $BORDERC . $_BORDERC . "\n"; +} + + +sub tree { + my($num, $text, $LocalTree, $node, @nodes) = @_; + if(@nodes) { + if(! exists $LocalTree->{$node}->{$NoteKey}) { + $LocalTree->{$node}->{$NoteKey} = []; + } + &tree($num, $text, $LocalTree->{$node}, @nodes); + } + else { + if(length($text) > ($maxlen - 5)) { + $text = substr($text, 0, ($maxlen -5)); + } + $text = $text . " (" . $NUMC . "#" . $num . $_NUMC . $NOTEC . ")" . $_NOTEC if($text ne ""); + push @{$LocalTree->{$node}->{$NoteKey}}, $text; + } +} + + +sub print_tree { + # thanks to Jens for his hints and this sub! + my $hashref=shift; + my $prefix=shift; + my @notes=@{$hashref->{$NoteKey}}; + my @subnotes=sort grep { ! /^$NoteKey$/ } keys %$hashref; + if($TreeType eq "LONG") { + for my $note (@notes) { + if($note ne "") { + print C $BORDERC ;# . $prefix. "|\n"; + print C "$prefix+---<" . $NOTEC . $note . $BORDERC . ">" . $_NOTEC . "\n"; + } + } + } + for my $index (0..$#subnotes) { + print C $BORDERC . $prefix. "|\n"; + print C "$prefix+---[" . $TOPICC . $subnotes[$index] . $BORDERC . "]\n"; + &print_tree($hashref->{$subnotes[$index]},($index == $#subnotes?"$prefix ":"$prefix| ")); + } +} + + +sub getconfig +{ + my($configfile) = @_; + my ($home, $value, $option); + # checks are already done, so trust myself and just open it! + open CONFIG, "<$configfile" || die $!; + while() { + chomp; + next if(/^\s*$/ || /^\s*#/); + my ($option,$value) = split /\s\s*=?\s*/, $_, 2; + $value =~ s/\s*$//; + $home = $value if (/^Home/); + $libpath = $value if (/^LibPath/); + $dbdriver = $value if (/^DbDriver/); + $dbhost = $value if (/^DbHost/); + $dbuser = $value if (/^DbUser/); + $dbpasswd = $value if (/^DbPasswd/); + $dbname = $value if (/^DbName/); + $table = $value if (/^DbTable/); + $fnum = $value if (/^FieldNumber/); + $fnote = $value if (/^FieldNote/); + $fdate = $value if (/^FieldDate/); + $NOTEDB = $value if (/^NoteDb/); + $MAX_NOTE = $value if (/^MaxNoteByte/); + $MAX_TIME = $value if (/^MaxTimeByte/); + $CRYPT_METHOD = $value if (/^CryptMethod/); + $USE_CRYPT = "YES" if (/^UseEncryption/ && $value == 1); + $USE_CRYPT = undef if (/^UseEncryption/ && $value == 0); + $ALWAYS_INT = "YES" if (/^AlwaysInteractive/ && $value == 1); + $ALWAYS_INT = undef if (/^AlwaysInteractive/ && $value == 0); + $DEFAULT_LIST = "LONG" if (/^DefaultLong/ && $value == 1); + $DEFAULT_LIST = undef if (/^DefaultLong/ && $value == 0); + $ALWAYS_EDIT = "YES" if (/^AlwaysEditor/ && $value == 1); + $ALWAYS_EDIT = undef if (/^AlwaysEditor/ && $value == 0); + $KEEP_TIMESTAMP = "YES" if (/^KeepTimeStamp/ && $value == 1); + $KEEP_TIMESTAMP = undef if (/^KeepTimeStamp/ && $value == 0); + $COLOR = "YES" if (/^UseColors/ && $value == 1); + $COLOR = "NO" if (/^UseColors/ && $value == 0); + $TopicSep = $value if (/^TopicSeparator/); + $maxlen = $value if (/^MaxLen/); + $BORDER_COLOR = $value if (/^BorderColor/); + $NUM_COLOR = $value if (/^NumberColor/); + $NOTE_COLOR = $value if(/^NoteColor/); + $TIME_COLOR = $value if (/^TimeColor/); + $TOPIC_COLOR = $value if (/^TopicColor/); + $PreferredEditor = $value if (/^PreferredEditor/); + $FormatText = $value if (/^FormatText/); + } + chomp $home; + $home =~ s/\/*$//; # cut eventually / at the end + $HOME = eval($home); + if($NOTEDB =~ /^(~\/)(.*)$/) { + $NOTEDB = "/home/" . $USER . "/" . $2; + } + $libpath =~ s/\/*$//; + + close CONFIG; +} + + + + +__END__ +# +# $Log: note,v $ +# Revision 1.27 2000/05/16 23:51:35 thomas +# fixed many option-parsing related bugd! +# +# Revision 1.26 2000/05/13 01:05:17 thomas +# changed config format and fixed some bugs +# as well as some other additions... +# +# Revision 1.25 2000/05/11 23:42:43 thomas +# --tree changed to --topic +# +# Revision 1.24 2000/05/10 22:59:44 thomas +# updated usage to reflect --raw and build it into output +# and display subs. +# +# Revision 1.23 2000/05/10 22:19:04 thomas +# changed to Getopt::Long, added --raw +# +# Revision 1.22 2000/05/01 18:51:40 thomas +# added "-" to sub dump +# +# Revision 1.21 2000/05/01 00:17:27 thomas +# *** empty log message *** +# +# Revision 1.20 2000/04/30 23:31:38 thomas +# added -o and coloured sub help. +# +# Revision 1.19 2000/04/30 16:07:23 thomas +# *** empty log message *** +# +# Revision 1.18 2000/04/30 14:58:21 thomas +# updated the usage and help subs +# +# Revision 1.17 2000/04/30 14:44:38 thomas +# added colors to the tree functions +# +# Revision 1.16 2000/04/30 14:28:38 thomas +# added the t command, which displays a topic-tree. +# and enhanced the list command in interactive mode +# +# Revision 1.15 2000/03/19 23:41:04 thomas +# changed set_del, now no extra TEMP file is required! +# instead I get it from $this->get_all() ! +# Revision 1.14 2000/03/19 22:51:49 thomas +# Bug in NOTEDB::binary fixed, recount of nubers was +# incorrect. +# +# Revision 1.13 2000/03/19 11:53:32 thomas +# edit bug fixed (ude => uen) +# +# Revision 1.12 2000/03/19 03:06:51 thomas +# backend support completed. +# mysql and binary backends now excluded in separate files +# +# Revision 1.11 2000/03/18 00:16:47 thomas +# added NOTEDB::mysql and changed note to work with that. +# thus, from now on there is only one script to maintain and +# it is possible to provide more bacjends as well as making +# additional scripts upon them, i.e. cgi script... +# +# Revision 1.8 2000/03/13 22:48:43 thomas +# small width bug fixed +# +# Revision 1.7 2000/03/08 23:11:19 tom +# added cd +# +# Revision 1.6 2000/03/08 22:50:41 tom +# Added the $KEEP_TIMESTAMP option and fixed a bug regarding topic names +# and invalid resolution of them in case it started with "1 name". +# +# Revision 1.5 2000/02/25 20:59:30 tom +# corrected small timestamp problem in &edit and &new +# +# Revision 1.4 2000/02/25 13:24:11 tom +# fixed a small bug, that caused to use the last line for a note title instead the 2nd. +# +# Revision 1.3 2000/02/25 11:28:53 tom +# all changes from bin version applied to sql version diff --git a/note-1.0.7/stresstest.sh b/note-1.0.7/stresstest.sh new file mode 100755 index 0000000..4913a02 --- /dev/null +++ b/note-1.0.7/stresstest.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# create notes with topics which then represents the corresponding +# directory structure. Depending on how many files the directory +# contains, the resulting note-database may become very large. +# It will then have thousands of notes! +STARTDIR=$1 +case $STARTDIR in + "") + echo "usage: stresstest.sh " + exit 1 + ;; + *) + LOCPFAD=`echo $STARTDIR | grep "^[a-zA-Z0-9.]"` + case $LOCPFAD in + "") + #echo nix + ;; + *) + STARTDIR=`echo $STARTDIR | sed 's/^\.*//'` + STARTDIR="`pwd`/$STARTDIR" + STARTDIR=`echo $STARTDIR | sed 's/\/\//\//g'` + ;; + esac + ;; +esac + + +stress () +{ + FILES="" + for file in `ls $1|sort` + do + echo "$1/$file" + if [ -d "$1/$file" ] ; then + stress "$1/$file" + else + #echo "$1/" > /tmp/$$ + #echo $file >> /tmp/$$ + #`cat /tmp/$$ | note -` + FILES="$FILES $file" + fi + done + echo "$1/" > /tmp/$$ + echo "$FILES" >> /tmp/$$ + case $FILES in + "") + ;; + *) + RES=`cat /tmp/$$ | note -` + ;; + esac + FILES="" +} + +stress $STARTDIR diff --git a/noterc b/noterc deleted file mode 100644 index 7e93501..0000000 --- a/noterc +++ /dev/null @@ -1,71 +0,0 @@ -# 0.3 (binary database) -# This is a sample config for the note script -# You do not need it, if you keep the values -# here unchanged. -# -# Copy it to your $HOME as .noterc -# -# IMPORTANT: -# If you previously used note 0.1 or 0.2 then -# you will already have such a file. This file -# is not compatible with the one for note 0.3! -# You have to delete it and to create a new one. -# -# There is no more a mysql database needed. If -# want to stay with your note-mysql-database, -# use note 0.2. -# -# This config has to be valid perl code. Therefore -# please be carefull! -# -# You can contact me per email: -# -# Thomas Linden, 01/2000 - - - -# Define the maximum bytes a note can have in a -# note-entry. -$MAX_NOTE = 1024; - - -# Define the maximum bytes a timestamp can have -# in a note-entry. -$MAX_TIME = 64; - - -# The maximum width for displaying a note. -$maxlen = 30; - - -# Your home, better do not change it! -$HOME = `echo \$HOME`; -chomp $HOME; - - -# The location of the note-database. If it does -# not exist, it will be created. -$NOTEDB = $HOME . "/.notedb"; - - -# if $COLOR equals NO, then everything will be -# displayed with your default colors (mostly black) -$COLOR = "NO"; - - -# Color-definitions of the various fields. Will be -# ignored if $COLOR = "NO". -$BORDER_COLOR = "BLACK"; # Borders -$NUM_COLOR = "blue"; # Note number -$NOTE_COLOR = "magenta"; # The note itself -$TIME_COLOR = "black"; # The time - -# The following colors are available: -# black, red, green, yellow, blue, magenta, cyan and white. -# It will be bold if it is uppercase. -# You can append an underscore, if you like it underscored, -# ie: blue_ -# Or, you can append an "I", if you like it inverted - -# keep this "1;" please! -1; diff --git a/sql b/sql deleted file mode 100644 index dec6864..0000000 --- a/sql +++ /dev/null @@ -1,8 +0,0 @@ -CREATE TABLE note ( - id int(10) DEFAULT '0' NOT NULL auto_increment, - number int(10), - firstline text, - note text, - date text, - PRIMARY KEY (id) -);