diff --git a/Changelog b/Changelog index 66e0339..a03c219 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,28 @@ ================================================================================== +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"! diff --git a/NOTEDB/README b/NOTEDB/README new file mode 100644 index 0000000..447198c --- /dev/null +++ b/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/NOTEDB/binary.pm b/NOTEDB/binary.pm new file mode 100644 index 0000000..9b6383c --- /dev/null +++ b/NOTEDB/binary.pm @@ -0,0 +1,331 @@ +#!/usr/bin/perl +use strict; +use Data::Dumper; +use IO::Seekable; + +package NOTEDB; +use Fcntl qw(LOCK_EX LOCK_UN); + +# Globals: +my ($NOTEDB, $sizeof, $typedef,$version); +$version = "(NOTEDB::binary, 1.1)"; + + +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 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++; + 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 =~ /$searchstring/i) + { + $res{$num}->{'note'} = $n; + $res{$num}->{'date'} = $t; + } + } + flock NOTE, LOCK_UN; + close NOTE; + + return %res; +} + + + +sub set_recountnums +{ + my $this = shift; + my(@count, $i, $num, $setnum, $buffer, $buff, $note, $date); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + $setnum = 1; + my $TEMP = "/tmp/note.$$"; # save temporarily in $TEMP + system("/bin/touch", $TEMP); + open TEMP, "+<$TEMP" or die "Could not open $TEMP($!)\n"; + + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) { + ($num, $note, $date) = unpack($typedef, $buffer); + $buff = pack($typedef, $setnum, $note, $date); + seek(TEMP, 0, IO::Seekable::SEEK_END); # APPEND + print TEMP $buffer; + $setnum++; + } + close(TEMP); + + flock NOTE, LOCK_UN; + close NOTE; + + system("/bin/cp",$TEMP, $NOTEDB); + + unlink $TEMP; +} + + + +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($note, $date, $T, $setnum, $buffer, $buff, $n); + + $setnum = 1; + my $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"; + flock NOTE, LOCK_EX; + + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) { + ($n, $note, $date) = unpack($typedef, $buffer); + $buff = pack($typedef, $setnum, $note, $date); + if($n != $num) { + seek(TEMP, 0, IO::Seekable::SEEK_END); # APPEND + print TEMP $buff; + } + else + { + $T = $date; + } + $setnum++; + } + close(TEMP); + + flock NOTE, LOCK_UN; + close NOTE; + + system("/bin/cp",$TEMP, $NOTEDB); + + unlink $TEMP; + + return "ERROR" if($T eq ""); # signal success! +} + +sub uen +{ + my($T); + $T = pack("u", $_[0]); + chomp $T; + return $T; +} + +sub ude +{ + my($T); + $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); + + # 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); + +=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/NOTEDB/mysql.pm b/NOTEDB/mysql.pm new file mode 100644 index 0000000..0ca4510 --- /dev/null +++ b/NOTEDB/mysql.pm @@ -0,0 +1,258 @@ +#!/usr/bin/perl +use DBI; +use strict; +use Data::Dumper; + +package NOTEDB; + +# Globals: +my ($DB, $table, $fnum, $fnote, $fdate, $version); +$table = "note"; +$fnum = "number"; +$fnote = "note"; +$fdate = "date"; +$version = "(NOTEDB::mysql, 1.0)"; + +# 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 = ?"; +###################################################################################################### + +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 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 $note, $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'} = $note; + $res{$num}->{'date'} = $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); + $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; + } + return %res; +} + + + +sub set_recountnums +{ + my $this = shift; + my(@count, $i, $num, $setnum); + $setnum = 1; + my $statement = $DB->prepare($sql_incrnum) || die $DB->errstr(); + my $sub_statement = $DB->prepare($sql_setnum) || die $DB->errstr(); + + $statement->execute || die $DB->errstr(); + $statement->bind_columns(undef, \($num)) || die $DB->errstr(); + + while($statement->fetch) { + $sub_statement->execute($setnum,$num) || die $DB->errstr(); + $setnum++; + } +} + + + +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($note, $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, $note, $date) || die $DB->errstr(); +} + + +sub set_del +{ + my($this, $num) = @_; + my($note, $date, $T); + + my $stat = $DB->prepare($sql_getsingle) || die $DB->errstr(); + $stat->execute($num) || die $DB->errstr(); + $stat->bind_columns(undef, \($note, $date)) || die $DB->errstr(); + while($stat->fetch) { + $T = $date; + } + + my $statement = $DB->prepare($sql_del) || die $DB->errstr(); + + $statement->execute($num) || die $DB->errstr(); + + $this->set_recountnums(); + + return "ERROR" if($T eq ""); # signal success! +} + + + +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); + +=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/README b/README index a8b4ece..b1a1d99 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -note 0.7 by Thomas Linden, 08/03/2000 +note 0.8 by Thomas Linden, 19/03/2000 Introduction @@ -17,20 +17,15 @@ Introduction sort your notes in different topics, which is usefull if you have a lot of them. - There are now two version of note in one package: - o (binary) the binary version resists in the - subdirectory "binary-db". - It uses a binary file for data storage. - The format of this file will be described - later on. - o (mysql) the mysql version resists in the - subdirectory mysql-db. It uses a mysql - database as backend. There are some - special installation steps required in - order to run the mysql version which are - documented in the README within this - subdirectory. - + There are currently two 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! Requirements @@ -38,20 +33,22 @@ Requirements You need the following things: o perl installed (5.004x) - o The module IO::Seekable, which should be + o The module IO::Seekable and Fcntl, which should be already installed with your perl distributuion. - o Mysql.pm if you want to use the mysql version. + o DBI module and DBI::mysql if you want to use the + mysql version. Installation ============ - Simple: Copy it to a place inside your $PATH, - probably as root. (for example to /usr/bin). + There is a script provided called "install.sh", which will + ask you a few questions about file destinations and database + backends. Simply answer this questions and it does the rest. - For installation instructions for the mysql version see - mysql-db/README. + For installation instructions for the mysql database installation + see mysql/README. @@ -65,20 +62,19 @@ Configuration 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 ===== - Usage of the mysql and binary version is similar, there - are only differences between the database backends of - each other. 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 1024 bytes, + the note (the length is by default limited to 4096 bytes, which you can change from your config file). End by typing a . on a line itself. note will tell you the number of the note. @@ -121,8 +117,8 @@ Usage provides you the most functions of note. You can also dump the contents of your note-database into a - ASCII-textfile. You can use this file later to import it into - your note-database. This is usefull, if you want quickly trans- + 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). @@ -141,12 +137,16 @@ Topics (or whatever you prefer, set $TopicSep 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. The list-command will only - show you notes under this topic. If you create a new note, it will auto- - magically inserted under the current topic (note will prepend the string - "/topicname/" to the text of your note). + 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 $TopicSep) @@ -197,7 +197,7 @@ Topics -Format of the notedb (binary version) +Format of the notedb (binary backend) ===================================== The database where the notes are stored is a binary file of @@ -217,7 +217,7 @@ Format of the notedb (binary version) -The note-database (mysql version) +The note-database (mysql backend) ================================= The sql-database for the mysql version has the following design: @@ -324,10 +324,11 @@ License -Author -====== +Author and Copyright +==================== The author is Thomas Linden. + note is Copyright of Thomas Linden. @@ -335,4 +336,4 @@ Author Last changed ============ - 21.02.2000 + 19/03/2000 diff --git a/UPGRADE b/UPGRADE new file mode 100644 index 0000000..5069955 --- /dev/null +++ b/UPGRADE @@ -0,0 +1,3 @@ +if you are upgrading an existing note installation, +you need to reedit your configfile, since there are now +some new required options! diff --git a/VERSION b/VERSION index eb49d7c..aec258d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.7 +0.8 diff --git a/bin/note b/bin/note new file mode 100755 index 0000000..7cec7c6 --- /dev/null +++ b/bin/note @@ -0,0 +1,1214 @@ +#!/usr/bin/perl +# $Author: thomas $ $Id: note,v 1.13 2000/03/19 11:53:32 thomas Exp thomas $ $Revision: 1.13 $ +# +# $Log: note,v $ +# 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 +# +# 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 Term::ReadLine; +#use POSIX qw(:sys_wait_h); + +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, $dbdriver, $libpath, $db + ); + +#################################################################### +# 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 = 24; +$COLOR = "YES"; +$BORDER_COLOR = "BLACK"; +$NUM_COLOR = "blue"; +$NOTE_COLOR = "green"; +$TIME_COLOR = "black"; +$TOPIC_COLOR = "BLACK"; +$TOPIC = 1; +$TopicSep = '/'; +$version = "0.8 r1.12"; +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 "no 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"; +} + + +# *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); + } +} +elsif($dbdriver eq "binary") { + eval { + require NOTEDB::binary; + $db = new NOTEDB($dbdriver, $NOTEDB, $MAX_NOTE, $MAX_TIME, $dbdriver); + } +} +else { + print "Unsupported database backend: NOTEDB::$dbdriver!\n"; + exit 1; +} +if($@) { + print "backend-error: " . $@; + 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 = ""; + + + +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,$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) + { + 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); + $maxlen += $timelen; + if($searchstring eq "") + { + &usage; + exit(1); + } + 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") + { + print "List of all existing notes:\n\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 + 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: + @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_file + open (DUMP, ">$dump_file") or die "could not open $dump_file\n"; + select DUMP; + %res = $db->get_all(); + foreach $num (sort { $a <=> $b } keys %res) + { + print STDOUT "dumping note number $num to $dump_file\n"; + 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); + # 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->set_new(0,$note, $date); + print "note number $number from $dump_file inserted into notedb.\n"; + $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 + $db->set_new(0,$note, $date); + print "note number $number from $dump_file inserted into notedb.\n"; + } +} + + + +sub interactive +{ + #$|=1; + #my $term = new Term::ReadLine(''); + #my $OUT = $term->OUT || *STDOUT; + #my $term->MinLine(undef); + #my $attribs = $term->Attribs; + #$term->bind_key(ord "\cc", 'abort'); + 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 = ; + #$char = $term->readline(''); + chomp $char; + if($char =~ /^\d+\s*[\di*?,*?\-*?]*$/) + { + # 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*?,*?\-*?]*)$/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} || 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, $nlen); + ($num, $note, $time, $TYPE) = @_; + if($ListType ne "LONG") + { + $SSS = "-" x ($maxlen + 31 - $timelen); + } + else + { + $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! + 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 - 2 - $nlen)) + { + $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 - 2 - $nlen)); + $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/config/noterc b/config/noterc index ff55c48..890b5a0 100644 --- a/config/noterc +++ b/config/noterc @@ -1,34 +1,65 @@ -# 0.7 +# 0.8 # This is a sample config for the note script -# You do not need it, if you keep the values -# here unchanged. +# There are usefully defaults set in note itself. +# +# The default database backend is NOTEDB::binary. # # 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 and higher! -# You have to delete it and to create a new one. -# # This config has to be valid perl code. Therefore -# please be carefull! +# please be careful! # # You can contact me per email: # -# Thomas Linden, 23/2000 +# Thomas Linden, 19/03/2000 + + +# Your home, better do not change it! +$HOME = $ENV{'HOME'}; + + +# specify the path, where the NOTEDB directory +# resides +$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" or "mysql". +$dbdriver = "binary"; + + +# backend specific settings: +####### mysql ############### +# sql database settings. +$dbhost = ""; # mysql server (hostname) +$dbuser = ""; # mysql username +$dbpasswd = ""; # her password +$dbname = ""; # database name +$table = "note"; # Table and field names. +$fnum = "number"; +$fnote = "note"; +$fdate = "date"; +######## end mysql ########### + + +####### binary db ################## +# The location of the note-database. If it does +# not exist, it will be created. Only if $driver = "binary" +$NOTEDB = $HOME . "/.notedb"; +# Define the maximum bytes a note can have in a +# note-entry. +$MAX_NOTE = 4096; + +# Define the maximum bytes a timestamp can have +# in a note-entry. +$MAX_TIME = 24; +####### end binary ################# + -# mysql database settings. leave them uncommented -# if you are not using the mysql version of note. -# $dbhost = ""; # mysql server (hostname) -# $dbuser = ""; # mysql username -# $dbpasswd = ""; # her password -# $dbname = ""; # database name -# $table = "note"; # Table and field names. -# $fnum = "number"; -# $fnote = "note"; -# $fdate = "date"; # uncomment this, if you want to run note always # in interactive mode @@ -62,40 +93,20 @@ $TOPIC = 1; #$TopicSep = '/'; -# 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 = "YES"; # 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 +$NOTE_COLOR = "green"; # The note itself $TIME_COLOR = "black"; # The time $TOPIC_COLOR = "BLACK"; # The topic "prompt" diff --git a/install.sh b/install.sh index c9cec31..429dc4e 100755 --- a/install.sh +++ b/install.sh @@ -1,19 +1,56 @@ #!/bin/sh -# installs note +# installer for note 0.8 > -echo "Welcome to note `cat VERSION` installation." -echo "the install script will ask you a view questions," -echo "make sure to answer them correctly!" +# $Id: install.sh,v 1.1 2000/03/19 03:33:28 thomas Exp thomas $ + +die () +{ + MSG=$1 + echo $MSG + exit 1 +} + +SRC=. + +NOTEDB="$SRC/NOTEDB" + +BIN="$SRC/bin" + +echo "Enter the destination for the note perl modules [/usr/local/lib] :" + +read LIBDIR + +echo "Enter the destination for the note program [/usr/local/bin] :" + +read BINDIR + +if [ "${LIBDIR}" = "" ] ; then + LIBDIR=/usr/local/lib +fi + +if [ "${BINDIR}" = "" ] ; then + BINDIR=/usr/local/bin +fi + +if [ ! -d ${LIBDIR} ] ; then + mkdir -p ${LIBDIR} || die "Could not create ${LIBDIR}!" +fi + +if [ ! -d ${BINDIR} ] ; then + mkdir -p ${BINDIR} || die "Could not create ${BINDIR}!" +fi + +echo "Installing note ..." + +cp -ri ${NOTEDB} ${LIBDIR} || die "Could not copy modules!" + +cp -i "${BIN}/note" ${BINDIR} || die "Could not copy note script!" + +chmod 755 ${BINDIR}/note +chmod 755 ${LIBDIR}/NOTEDB +chmod 644 ${LIBDIR}/NOTEDB/* + +echo "done. Please copy ${SRC}/config/noterc to ~/.noterc" +echo "and edit it if you like. " echo - -/bin/echo -n "creating the note database..." -NAME="_note" -DBNAME="$USER$NAME" -echo "DBNAME=$DBNAME" -mysqladmin create $DBNAME -echo "done." -/bin/echo -n "creating the table structure using defaults..." -mysql $DBNAME < sql -echo "done." - - +echo "Thanks for using note 0.8!" diff --git a/mysql/README b/mysql/README new file mode 100644 index 0000000..78cc14a --- /dev/null +++ b/mysql/README @@ -0,0 +1,62 @@ +README for the mysql database installation for note + +Requirements +============ + + You need the following things: + o perl installed (5.004x) + o mysql database installed and running + o Mysql perlmodule (you can find it on + http://www.mysql.org) PLEASE NOTE: + It needs the Module "Mysql". The install.sh + script will install it for you directly from + CPAN if you like. Newer versions + are DBI, which you can also use to access + mysql databases. If you want to use it, you + have to rewrite the program. Please let me + know, if you did it :-) + o permissions to create a new database and + to write data to this database. + + + +Installation +============ + + First, make sure all these things above are ok. + You can use the script "install.sh" to create a new + database and the table structure. You might edit + the script before running it. + + 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 + neccessary permissions. Please refer to the mysql + documentation, how to do that. + After that repeat the step above. + + 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 + then the default. + install.sh will create the following database: + name: user_note + Maintable: note + Number: number(int 10) + Note: note(text) + Date: date(text) + + You can use the file "permissions" as a template for + modifying a users permissions to her database. Please + note, that there are different version of mysql out + there with different access privilege systems, which + are not compatible, refer to the documentation shipped + with your mysql installation to learn, how many fields + are available and what they are for. + + You may also take a look to: + http://www.mysql.org/Manual_chapter/manual_Privilege_system.html + + + This should be all. diff --git a/mysql/install.sh b/mysql/install.sh new file mode 100755 index 0000000..5bd2b2a --- /dev/null +++ b/mysql/install.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# installs note +# This is the installer for the mysql version only! + +echo "Welcome to note `cat VERSION` installation." +echo "the install script will ask you a view questions," +echo "make sure to answer them correctly!" +echo + +/bin/echo -n "creating the note database..." +NAME="_note" +DBNAME="$USER$NAME" +echo "DBNAME=$DBNAME" +mysqladmin create $DBNAME +echo "done." +/bin/echo -n "creating the table structure using defaults..." +mysql $DBNAME < sql + +echo "Shall I try to install the required MySQL driver from CPAN?" +read YESNO + +case $YESNO in + "y" | "Y") + if [ $UID != 0 ] ; then + echo "You should be root for that!" + exit + fi + perl -MCPAN -e shell cpan> install mysql + ;; +esac +echo "done." + + diff --git a/mysql/permissions b/mysql/permissions new file mode 100644 index 0000000..966d1bf --- /dev/null +++ b/mysql/permissions @@ -0,0 +1,2 @@ +insert into user values + ('localhost','','','Y','Y','Y','Y','Y','Y','N','N','N','N','N','N','N','Y'); diff --git a/mysql/sql b/mysql/sql new file mode 100644 index 0000000..37d6072 --- /dev/null +++ b/mysql/sql @@ -0,0 +1,8 @@ +CREATE TABLE note ( + number int(10) DEFAULT '0' NOT NULL auto_increment, + note text, + date text, + PRIMARY KEY (number) +); +# sample grant statement: +#GRANT ALL PRIVILEGES ON tom_note TO tom@localhost IDENTIFIED BY 'password';