diff --git a/Changelog b/Changelog deleted file mode 100644 index 817673f..0000000 --- a/Changelog +++ /dev/null @@ -1,715 +0,0 @@ --*-text-*- -1.4.1: -Fixed https://rt.cpan.org/Ticket/Display.html?id=155578: - -Feeding a new entry into note from STDIN didn't work correctly -anymore. Using the default builtin config and no config file it didn't -work at all. Now it works as one would expect. A bare - as argument -ALWAYS reads a new entry from STDIN. The same happens if one uses -n --. In addition note now prints a message if it attempts to read from -STDIN to avoid confusion. - -The parameter -n has been added to be able to force note to create a -new entry directly from commandline, regardless of any configuration. - -Fixed regex to check if a note has been specified as argument. Now it -does not match a bare - anymore. - -Reorganized a little code. - - -1.4.1: -Fixed https://codeberg.org/scip/note/issues/11: - -Every backend now uses a different default file extension and the -default config file has it configured the same way. - -The error message about an encrypted file when expecting an -unencrypted one has been adjusted to be more understandable by new -users. - -Documentation updates. - -Deprecation Warning: binary and text backend support will be removed -in the upcoming version 1.5.0. - - - -1.4.0: -Added support for JSON encoded export files instead of YAML. -Currently this is just an option, which can be set in the config -with UseJSON or commandline -j. The old export format is now -being considered deprecated (a warning will be shown) and will -be removed in 1.5. Fixes https://codeberg.org/scip/note/issues/10. - -A helper script has been added to help to combine two notedb's -into one: contrib/sync-combine-two-yaml-exports-into-one.pl. It is -still using YAML mode, JSON support will be added in the future. - - - -1.3.26: -fixed installer, on newer perls NOTEDB/* is being ignored - - - -1.3.25: -fixed indents - - - -1.3.24: -removed bashism in mysql installer. - - - -1.3.23: -defect distritbution. do not use. - - - -1.3.22: -fixed bug in mysql backend. -added retry feature for NOTEDB::pwsafe3 backend save() password -entering. bails out after 5 retries. - - - -1.3.21: -Changed note id generation in NOTEDB::pwsafe3::_uuid(), again. -Instead of crc checksums and the loop to avoid duplicates, I just -use a counter and sort the entries by ctime, so that older entries -keep their note id. Also this should fix a rare bug, where the -code hangs because of said loop. - - - -1.3.20: -fixed bug in NOTEDB::pwsafe3::_retrieve(), it iterated over the -records unsorted which resulted in different note ids each time -the program runs. - - - -1.3.19: -revert fix in NOTEDB::pwsafe3::filechanged(), use > again. - - - -1.3.18: -fixed unit tests and added more (lots of them) -fixed several bugs in backend modules, which I found during -writing of the unit tests. - - - -1.3.17: -applied patch by Bill Carlson, which fixes string length issues -in non-interactive search mode. -fixed usage text (-h) so that it now contains the available -options. - - - -1.3.16: -fixed checking of encrypted notes when encryption is turned off. -instead of checking note id 1, we now check the first entry, -whatever id it may have. - - - -1.3.15: -fixed bug in NOTEDB::pwsafe3 backend, it converted the date -of a note entry into the wrong formatted timestamp. - - - -1.3.14: -fixed bug in NOTEDB::pwsafe3 backend, it used lockging on the -database file for reading, which is wrong. - - - -1.3.13: -ADDED: new config parameter 'motd', a note entry which will be shown -on startup (if exists). -CHANGED: the prompt will now show if the current instance is running -in readonly mode. - - - -1.3.12: -FIXED: NOTEDB::general data backend module did overwrite records if -there were some deleted ones in the database. - - - -1.3.11: -FIXED: NOTEDB::pwsafe3 contained the old python stuff in delete code. - - - -1.3.10: -FIXED: the YAML export/import change were missing too. grml... -FIXED: NOTEDB::general backend fixed loading Config::General - - - -1.3.9: -FIXED: bin/note were missing. for whatever reason, I don't know. - - - -1.3.8: -ADDED: New backend added: NOTEDB::pwsafe3, which adds support to store -notes in a Password Safe v3 database. -FIXED: -d didn't work, because of a typo in mode assignment. - - - -1.3.7: -ADDED: added ticket feature, which adds a unique id to each -new note, which persists during imports/exports. the -id is a randomly generated string. - - - -1.3.6: -ADDED: Added test cases for "make test" -ADDED: Added test for optional and required perl modules in -Makefile.PL -FIXED: NOTEDB::dumper version string were wrong, therefore -cpan didn't index is properly. - - - -1.3.5: -FIXED: Applied patch by Elmar Loos which fixes misbehavior for --t and -T (identical output) -FIXED: Fixed import bug which omitted the timestamp of the last -entry, supmitted by Bill Barnard. -FIXED: Fixed another import "bug" (or design flaw) which caused -imported notes to get new numbering after importing them. -Submitted by Bill Barnard. -CHANGED: Until 1.3.4 missing Crypt:: modules lead to unencrypted -fallback by note. From 1.3.5 on this will no more happen, -it croaks now until you install the desired modules -or modify your configuration to use no encryption. -CHANGED: default config and default settings without config have -been changed. They are now simpler, no colours or anything -so that it works better out of the box in any terminal -window or shell (e.g. on dark ones or the like). -ADDED: New interactive mode command: "c". It is now possible to -change note's behavior at runtime. No database related -parameters can be modified. - - - -1.3.4: -ADDED: Each note now contains a "ticket number" which identifies -it against other notes. Those tickets are not changing when -notes will be reorganized. -ADDED: added support for less to view note entries instead of -just printing it to STDOUT. (interactive mode). - - - -1.3.3: -ADDED: new configfile parameter PrintLines (default: YES), which -controls wether listings are separated by horizontal lines. - - - -1.3.2: -FIXED: NOTEDB::mysql backend parameter fixed (dbtype) -FIXED: NOTEDB::mysql didn't fetch topics correctly -FIXED: NOTEDB::text didn't correctly return last highest note id - - - -1.3.1: -FIXED: most config variables not related to drivers had -invalid sentence in note, so the new ones of the new config -were ignored. -FIXED: added version to NOTEDB::text. -FIXED: fixed handling of NOTEDB::crypt_supported, now encryption -works again. -ADDED: NOTEDB::text now supports internal caching too. -CHANGED: lock() sets the umask internally to 022, so that other -users are able to read the lockfile. - - - -1.3.0: -ADDED: new config option: ReadOnly -ADDED: new database backend: NOTEDB::text, which uses the Storable -module. -CHANGED: the data import will now written to db once. -CHANGED: added global database locking support, which is usually -useful in multiuser environments. -ADDED: new database backend: NOTEDB::general, which uses the -Config::General module. -CLEANUP: almost everywhere -CHANGED: noterc config format changed! especially the config for -backend drivers has changed a lot. -CHANGED: the configuration variables are now stored in a hash, this -saved some global variables, the driver variables are stored -in an extra hash, which contains one key per driver, this -hash gets supplied to the driver backend module 1:1. -CHANGED: the libpath variable has been removed, it didnt't work either. -use now .. instead, so that a local installation for a non -root user is still possible. - - - -1.2.6: -FIXED: the binary driver (NOTEDB::binary) encounters now if a note -entry is bigger then MaxNoteByte. It prints the overlapping -part to STDERR, and a warning message and finally saves -the complete, unchanged note entry to an external text file. - - - -1.2.5: -FIXED: removed any file/path actions using '/'. replaced by portable -functions by using File::Spec. This makes it possible to run -note unchanged on win32 (and possibly any other) environments. -FIXED: added a whitespace to the prompt in interactive mode to -circumvent a bug in the win32 Term::ReadLine module which causes -the cursor to be displayed on the left side (column 0) of -the screen. -FIXED: added "or die" code to some commands which are running inside -an eval{} block to fetch errors. Without the "or die"s no -error could ever catched. -CHANGED: removed HOME variable support of the noterc. in fact, if it -exists, no error will occur, but it will no longer be used. -It didn't work in older versions anyway. -ADDED: It is now possible to quit note using CTRL-D (or: EOF) - - - -1.2.4: -CHANGED: in the function find_editor() the alternatives vim and pico -has been removed because they would never had a match. -FIXED: applied patch by Bill Barnard -which fixes a bug in the sub format() which features bold -hidden or underlined text. Now its possible to use a ^ char -in hidden texts too. I applied the same for the other regexps. -ADDED: if the config variable FormatText is set to 'simple' then -only one * _ { or / will make the text tagged with them to -be displayed formatted, instead of two. -ADDED: added Term::ReadLine support (auto-completion and history). - - - -1.2.3: -ADDED: if FormatText is enabled one can now use a new special format -tag: //. If a text is surrounded by two slashes, i.e.: //blah// -then it appears "invisible" by using blue forground and blue -background color for displaying. This is handy for passwords -since no nobody can grab you password by looking at your -monitor, but you can copy&paste it. - - - -1.2.2: -FIXED: oneliner note entries caused breaked displaying in interactive -mode. -FIXED: list displaying in interactiv mode corrected. the width of the -note number will now correctly used. -CHANGED: the default setting of note will now be to use an external -editor instead of stdin. -CHANGED: the unneccessary apostrophes in listings has been removed. -ADDED: the note version will be displayed in the titlebar of interactive -mode. -ADDED: new config variable AutoClear, which is turned on by default, -which controls wether the screen shall be cleared after each -item (display, list and so on). - - - -1.2.1: -CHANGED: added the correct installation instructions to the README file. -REMOVED: removed the usage guidelines from te README file. This information -were redundant because its also contained in the manpage. -FIXED: on FreeBSD the setting of MaxLen to 'auto' had no effect because the -output of 'stty -a' which I use in note to determine the actual -size of the terminal, is different from that on linux. -ADDED: topics can now be abbreviated in interactive mode, which -avoids typing. abbreviation works only if an explicit -match could be found, otherwise the available topics that -matches will be suggested. - - - -1.2.0: -CHANGED: using Makemaker instead of self-written code in Makefile.PL -for installation. No more dependency checks built-in because -note runs out-of-the-box without additional modules, as a matter fact. -ADDED: if a search matches exactly on one note it will be displayed -directly, which avoids typing. -CHANGED: the main if-else contruct for calling the several subs has -been replaced by a simple closure call. -CHANGED: notes will now displayed in a slightly simpler fashion in interactive -mode, without the separator line between the title and the note. -ADDED: note can now determine automatically the width and height of -the terminal window it runs in (in interactive mode only) and -sets the width/height of what it prints accordingly. the config -variable "MaxLen" must be set to "auto" (which is the default -from now on) to get this to work. -ADDED: any interactive command will now clear the screen before it does -anything. this look much more uncluttered. -ADDED: if multiple notes are printed at once (i.e. note 1,2) then the -separator line between them will no more being printed because -every notes title is preceded by a line anyway. -CHANGED: by default the default operation mode is now interactive mode, -which is somewhat kindlier to new users. -CHANGED: changed to order which editor note tries to find. vi got now -higher precedence, because it is likely installed on almost -any unix system. -CHANGED: cosmetics. -NOTE: increased minor version number from 1 to 2 to indicate that -development begun after 2 1/2 years pause again :-) - - - -1.1.2: -FIXED: Empty notes will no longer stored. -ADDED: A new config option which allows you to specify a time format -other than the default one which is used by note. - - - -1.1.1: -FIXED: Some odd typos in README and note.pod. -FIXED: if ShortCd was on and one used "cd 3" and after that "cd .." -then the current topic was wrong (empty $PATH). -FIXED: if the current topic contained no notes and one created a new -note without specifying a topic, then note did not add a -proper topic (also because of empty $PATH). -CHANGED: the default colors are now visible both on black and white -backgrounds, see next entry. -ADDED: two more color values: and . -CHANGED: the color hash is now in ::main instead of ::C. - - - -1.1.0: -CHANGED: does no more use the external touch command to create a new -file, use perls open() instead. -CHANGED: excluded some of the help texts from the usage message and the -interactive help command to a manpage. -ADDED: new commandline flag "--encrypt" which one can use to encrypt -the mysql database password. This will be decrypted before -connecting to the db. There is also a new config file option -"encrypt_passwd" which indicates an encrypted db-password. -ADDED: another new config option "ShortCd", which can be set to "yes" -or 1 and if set, then a command like "cd 13" would jump -directly to the topic of the note with the number 13. -ADDED: now you can at any time cd back to the "root" of the -topic-structure using the command "cd /". -CHANGED: mysql.pm does now only do a table-lock on single write -accesses, no more on the whole session. This allows one to -access the same db twice or more. -FIXED: Changed README and Changelog for readability on 80 by 25 -displays. And changed indentation of the note script itself. -ADDED: NOTEDB.pm - a generic module, which holds some methods, which -are used by binary.pm, mysql.pm and dbm.pm. -ADDED: NOTEDB.pm generate_search(), which allows one to -use AND, OR and various combinations of them using ( and ). -ADDED: a search does now return the 2nd line of a note if a matching -note's first line is a topic. -CHANGED: use "unshift" instead of push to add $libpath to @INC. -ADDED: a new feature, Caching of notes. supported by binary.pm and -mysql.pm. To turn it on, one need to set "Cache" in the config -to a true value. -CHANGED: oop-ized and re-indented the modules dbm.pm, mysql.pm and -binary.pm. -ADDED: You can now specify a port for the mysql backend ("DbPort"). - - - -1.0.9: jumped directly to 1.1.0, too many additions. - - - -1.0.8: -FIXED: typo in noterc shipped with package may caused confusion -(BLOWFISH instead of Blowfish). -CHANGED: changed the way note manages temporary filez. It uses now a -random string instead of just it's own PID. It does also change -it's umask to 077 and, if applicable (on ext2 filesystems) -issues "chattr +s" which will cause the ext2 inodes to be -zero'd after file deletion. -ADDED: A new config option allows the user to specify her own -temp-directory. The default is still /tmp. - - - -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 checks 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 ;-((( -Thanks to Peter Palmreuter for the following fixed/additions: -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. -FIXED: sub search prints now an appropriate error-message in -case no searchstring was given instead of jumping to -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 to pipe another commands output to note! -ADDED: you can now use an environment variable for the passphrase -(when using encryption). If it is present, note will not ask -for a passphrase. This is very useful 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 to 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 -autoincrement 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 -stringlength 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 -commandline. -FIXED: a small bug fiyed, it was impossible to use -D or -I from -commandline, 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 more 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/MANIFEST b/MANIFEST deleted file mode 100644 index 2f2524a..0000000 --- a/MANIFEST +++ /dev/null @@ -1,28 +0,0 @@ -MANIFEST -bin/stresstest.sh -bin/note -mysql/permissions -mysql/sql -mysql/install.sh -mysql/README -VERSION -config/rc -config/noterc -README -UPGRADE -note.pod -TODO -t/run.t -lib/NOTEDB/mysql.pm -lib/NOTEDB/text.pm -lib/NOTEDB/dumper.pm -lib/NOTEDB/pwsafe3.pm -lib/NOTEDB/dbm.pm -lib/NOTEDB/README -lib/NOTEDB/binary.pm -lib/NOTEDB/general.pm -lib/NOTEDB.pm -Changelog -Makefile.PL -META.yml -META.json diff --git a/Makefile.PL b/Makefile.PL deleted file mode 100644 index bfa4c49..0000000 --- a/Makefile.PL +++ /dev/null @@ -1,41 +0,0 @@ -use ExtUtils::MakeMaker; - -my %optional = ( - 'Crypt::CBC' => "Required by encryption support", - 'Crypt::Rijndael' => "Required by encryption support", - 'Data::Dumper' => "Required by dumper DB backend", - 'MIME::Base64' => "Required by varios optional backends", - 'Storable' => "Required by text DB backend", - 'Config::General' => "Required by general DB backend", - 'DB_File' => "Required by dbm DB backend", - 'DBI' => "Required by mysql DB backend", - 'DBD::mysql' => "Required by mysql DB backend", - 'Crypt::PWSafe3' => "Required by Password Safe v3 backend" - ); - -foreach my $module (sort keys %optional) { - eval "require $module"; - if ($@) { - warn("Optional module $module not installed, $optional{$module}\n"); - } -} - - -WriteMakefile( - 'NAME' => 'note', - 'VERSION_FROM' => 'bin/note', # finds $VERSION - 'EXE_FILES' => [ 'bin/note' ], - 'PREREQ_PM' => { - 'IO::File' => 0, - 'FileHandle' => 0, - 'File::Spec' => 0, - 'File::Glob' => 0, - 'FileHandle' => 0, - 'Getopt::Long' => 0, - 'Fcntl' => 0, - 'IO::Seekable' => 0, - 'YAML' => 0, - }, - ($ExtUtils::MakeMaker::VERSION ge '6.31'? ('LICENSE' => 'perl', ) : ()), - 'clean' => { FILES => 't/*.out t/test.cfg *~ */*~' } - ); diff --git a/README.md b/README.md index c3602b1..003e3c3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # note - a perl script for maintaining notes. +> [!CAUTION] +> This software is now being maintained on [Codeberg](https://codeberg.org/scip/note/). + This is the perl script 'note' in version 1.4.2 from 24/09/2024. ## Introduction diff --git a/TODO b/TODO deleted file mode 100644 index c4a5f00..0000000 --- a/TODO +++ /dev/null @@ -1,6 +0,0 @@ -- &output() has to be rewritten, its a historically - growed mutant. - -- ncurses support - - diff --git a/UPGRADE b/UPGRADE deleted file mode 100644 index 32611ee..0000000 --- a/UPGRADE +++ /dev/null @@ -1,73 +0,0 @@ -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/VERSION b/VERSION deleted file mode 100644 index 9df886c..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.4.2 diff --git a/bin/note b/bin/note deleted file mode 100755 index 9ff4001..0000000 --- a/bin/note +++ /dev/null @@ -1,1915 +0,0 @@ -#!/usr/bin/perl -# -# note - console notes management with database and encryption support. -# Copyright (C) 1999-2024 T.v.Dein (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 von Dein -# -# latest version on: -# http://www.daemon.de/note/ -# https://codeberg.org/scip/note/ -# - -use lib qw(blib/lib); - -BEGIN { - # works on unix or cygwin only! - my $path = $0; - $path =~ s#/[^/]*$##; - unshift @INC, "$path/.."; -} - -use strict; -no strict 'refs'; -use Getopt::Long; -use FileHandle; -use File::Spec; -use YAML; -use JSON::PP; - - -# -# 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! -sub ticket; # return a random string which is used as ticket number for new note entries - -# -# globals -# -my ( - # - # commandline options - # - $opt_, $opt_i, $opt_r, $opt_e, $opt_d, $opt_enc, - $opt_s, $opt_t, $opt_T, $opt_l, $opt_L, $opt_c, - $opt_D, $opt_I, $opt_o, $opt_h, $opt_n, $opt_v, - $opt_j, $opt_new, - - # - # set from commandline (or interactive) - # - $number, $searchstring, $dump_file, $ImportType, $StdinMode, $Raw, $TOPIC, - - # - # configuration options - %conf, %driver, - - # - # processed colors - # - $BORDERC, $_BORDERC, $NOTEC, $NUMC, $_NUMC, $_NOTEC, $TIMEC, - $_TIMEC, $TOPICC, $_TOPICC, - - # - # config presets - # - $DEFAULTDBNAME, $USER, $PATH, $CONF, - - # - # internals - # - $TYPE, $mode, $NoteKey, %Color, @LastTopic, $timelen, $maxlen, - $VERSION, $CurTopic, $CurDepth, $WantTopic, $db, - $sizeof, %TP, $TreeType, $ListType, $SetTitle, $clearstring, - @ArgTopics, $key, $typedef, @NumBlock, $has_nothing, @completion_topics, @completion_notes, - @randomlist, $hardparams - ); - - -# -# DEFAULTS, allows one to use note without a config -# don't change them, instead use the config file! -# - -%conf = ( - 'numbercolor' => 'blue', - 'bordercolor' => 'black', - 'timecolor' => 'black', - 'topiccolor' => 'black', - 'notecolor' => 'green', - 'alwaysinteractive' => 1, - 'keeptimestamp' => 0, - 'readonly' => 0, - 'shortcd' => 1, - 'autoclear' => 0, - 'maxlen' => 'auto', - 'defaultlong' => 0, - 'dbdriver' => 'binary', # will be depcrecated in 1.5.0 and replaced by dumper. - 'timeformat' => 'DD.MM.YYYY hh:mm:ss', - 'usecolors' => 0, - 'addticket' => 0, - 'formattext' => 0, - 'alwayseditor' => 1, - 'useencryption' => 0, - 'tempdirectory' => File::Spec->tmpdir(), - 'topicseparator' => '/', - 'printlines' => 0, - 'cache' => 0, - 'preferrededitor' => '', - 'motd' => '', - 'usejson' => 0, # will be the default in the future -); - -# these are not customizable at runtime! -$hardparams = "(readonly|maxlen|dbdriver|useencryption|cryptmethod)"; -$CONF = File::Spec->catfile($ENV{HOME}, ".noterc"); -$USER = getlogin || getpwuid($<); chomp $USER; -$TOPIC = 1; -$VERSION = "1.4.2"; -$CurDepth = 1; # the current depth inside the topic "directory" structure... -$maxlen = "auto"; -$timelen = 22; - -@randomlist = ('a'..'z', 0..9, 'A'..'Z'); - -# colors available -# \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', - 'white_black' => '40;37;01', - 'bold' => ';01', - 'hide' => '44;34' - ); - -# -# process command line args -# -if ($ARGV[0] eq "") { - $mode = "new"; -} -elsif ($#ARGV == 0 && $ARGV[0] eq "-") { - $mode = "new"; - $StdinMode = 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 - "new|n:s" => \$opt_new, # no arg or optional string - "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 - "json|j" => \$opt_j, # bool, 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 - "encrypt=s" => \$opt_enc, # string, required - ); - - # after that @ARGV contains eventually a note-number or a single dash - $opt_n = shift; - - # - # determine mode - # - if ($opt_i) { - $mode = "interactive"; - } - elsif (defined $opt_new) { - $mode = "new"; - if ($opt_new eq "-") { - $StdinMode = 1; # read from STDIN - } - } - elsif (defined $opt_l || defined $opt_L) { - $mode = "list"; - if (defined $opt_l) { - @ArgTopics = split /$conf{topicseparator}/, $opt_l; - } - else { - $ListType = "LONG"; - @ArgTopics = split /$conf{topicseparator}/, $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"; - $mode = "display_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 = "del"; - $number = $opt_d; - } - elsif ($opt_enc) { - $mode = "encrypt_passwd"; - $clearstring = $opt_enc; - } - 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 - } - - if (defined $opt_j) { - $conf{usejson} = 1; # force JSON - } - } - 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 von Dein .\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[\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 eq "-") { - $StdinMode = 1; # read from STDIN - $mode = "new"; - } - 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); -} - -# directly jump to encrypt, 'cause this sub does -# not require a database connection -if ($mode eq "encrypt_passwd") { - &encrypt_passwd; - exit; -} - -# Always interactive? with the exception if stdin was requested -if ($conf{alwaysinteractive} && $mode ne "dump" && $mode ne "import" && !$StdinMode && !defined $opt_new) { - $mode = "interactive"; -} - -# OK ... Long-Listing shall be default ... You wanted it!!! -if ($conf{defaultlong}) { - # takes only precedence in commandline mode - $ListType="LONG"; -} - - - - -# calculate some constants... -$BORDERC = "<$conf{bordercolor}>"; -$_BORDERC = ""; -$NUMC = "<$conf{numbercolor}>"; -$_NUMC = ""; -$NOTEC = "<$conf{notecolor}>"; -$_NOTEC = ""; -$TIMEC = "<$conf{timecolor}>"; -$_TIMEC = ""; -$TOPICC = "<$conf{topiccolor}>"; -$_TOPICC = ""; - -$NoteKey = $conf{topicseparator} . "notes" . $conf{topicseparator}; - - - - -# default permissions on new files (tmp) -umask 077; - - -# load the parent module -&load_driver(1); - -# check wether the user wants to use encryption: -if ($conf{useencryption} && $NOTEDB::crypt_supported == 1) { - if ($conf{cryptmethod} eq "") { - $conf{cryptmethod} = "Crypt::IDEA"; - } - if (!exists $ENV{'NOTE_PASSWD'}) { - print "note password: "; - eval { - local($|) = 1; - local(*TTY); - open(TTY,"/dev/tty") or die "No /dev/tty!"; - system ("stty -echo ); - print STDERR "\r\n"; - system ("stty echo ; - } - } - else { - $key = $ENV{'NOTE_PASSWD'}; - } - chomp $key; - if ($conf{dbdriver} eq "mysql") { - eval { - require Crypt::CBC; - my $cipher = new Crypt::CBC($key, $conf{cryptmethod}); - # decrypt the dbpasswd, if it's encrypted! - $driver{mysql}->{dbpasswd} = - $cipher->decrypt(unpack("u", $driver{mysql}->{dbpasswd})) if($driver{mysql}->{encrypt_passwd}); - &load_driver(); - }; - die "Could not connect to db: $@!\n" if($@); - } - else { - &load_driver(); - } - $db->use_crypt($key,$conf{cryptmethod}); - 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 database! -} -elsif ($conf{useencryption} && $NOTEDB::crypt_supported == 0) { - print STDERR "WARNING: You enabled database encryption but neither Crypt::CBC\n"; - print STDERR "WARNING: or Crypt::$conf{cryptmethod} are installed! Please turn\n"; - print STDERR "WARNING: off encryption or install the desired modules! Thanks!\n"; - exit 1; -} -else { - # as of 1.3.5 we do not fall back to cleartext anymore - # I consider this as unsecure, if you don't, fix your installation! - - &load_driver(); - $db->no_crypt; - - # does: NOTEDB::crypt_supported = 0; - my %all = $db->get_all(); - if(scalar keys %all > 0) { - my $id = (keys %all)[0]; - if($all{$id}->{date} !~ /^\d+\.\d+?/) { - print "Warning! Encryption is not enabled, but notedb seems to be encrypted or in a non-text binary format. Please check your db file and your config!\n"; - exit(1); - } - } -} - - -# do we use the db cache? -if ($conf{cache}) { - $db->use_cache(); -} - - -# add the backend version to the note version: -$VERSION .= ", " . $conf{dbdriver} . " " . $db->version(); - - -# main loop: ############### -&$mode; -exit(0); -################## EOP ################ - - - - - - - - - - - - - - -############ encrypt a given password ############## -sub encrypt_passwd { - my($key, $crypt_string); - print "password: "; - eval { - local($|) = 1; - local(*TTY); - open(TTY,"/dev/tty") or die "No /dev/tty!"; - system ("stty -echo ); - print STDERR "\r\n"; - system ("stty echo ; - } - chomp $key; - eval { - require Crypt::CBC; - my $cipher = new Crypt::CBC($key, $conf{cryptmethod}); - $crypt_string = pack("u", $cipher->encrypt($clearstring)); - }; - if ($@) { - print "Something went wrong: $@\n"; - exit 1; - } - else { - print "Encrypted password:\n$crypt_string\n"; - } -} -############################### MOTD ################################## -sub motd { - my($N,$match,$note,$date,$num); - # display a configured motd note, if any - ($note, $date) = $db->get_single($conf{motd}); - if ($note) { - print "\n\n$note\n\n"; - } -} - -############################### DISPLAY ################################## -sub display { - my($N,$match,$note,$date,$num); - # display a certain note - print "\n"; - &num_bereich; # get @NumBlock from $numer - my $count = scalar @NumBlock; - 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", $count); - print "\n"; - } - $match = 1; - } - $count--; - } - 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 $conf{dbname} for \"$searchstring\"...\n\n"; - - %res = $db->get_search($searchstring); - my $nummatches = scalar keys %res; - &determine_width; - foreach $num (sort { $a <=> $b } keys %res) { - if ($nummatches == 1) { - output($num, $res{$num}->{'note'}, $res{$num}->{'date'}, "SINGLE"); - } - else { - output($num, $res{$num}->{'note'}, $res{$num}->{'date'}, "search"); - } - $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 =~ /^($conf{topicseparator})/) { - @topic = split(/$conf{topicseparator}/,$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 =~ /^($conf{topicseparator})/) { - $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 "") { - if ($i) { - # only if there were notes under current topic - undef $PATH; - foreach (@RealTopic) { - $PATH .= $_ . $conf{topicseparator}; - last if($_ eq $CurTopic); - } - } - else { - # it is an empty topic, no notes here - $PATH = join $conf{topicseparator}, @LastTopic; - $PATH .= $conf{topicseparator} . $CurTopic . $conf{topicseparator}; - $PATH =~ s/^\Q$conf{topicseparator}$conf{topicseparator}\E/$conf{topicseparator}/; - } - } - else { - $PATH = $conf{topicseparator}; - } - - @completion_topics = (); - @completion_notes = (); - # we are at top level, print a list of topics... - foreach $top (sort(keys %TP)) { - push @completion_topics, $top; - output("-", " => ". $top . "$conf{topicseparator} ($TP{$top} notes)", - " Sub Topic "); - } - #print Dumper(@CurItem); - for ($in=0;$in<$i;$in++) { - push @completion_notes, $CurItem[$in]->{'num'}; - 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); - if ($conf{readonly}) { - print "readonly\n"; - return; - } - - $date = &getdate; - $note = ""; - $line = ""; - - return if $db->lock(); - - if ($StdinMode) { - # create a new note from STDIN - print STDERR "Reading from STDIN ...\n"; - while () { - $note .= $_; - } - } - elsif ($conf{alwayseditor} && &is_interactive()) { - # read a new note interactively or by using the editor - $TEMP = &gettemp; - # security! - unlink $TEMP; - - # let the user edit it... - $editor = &find_editor; - if ($editor) { - # create the temp file - open NEW, "> $TEMP" or die "Could not write $TEMP: $!\n"; - close NEW; - system "chattr", "+s", $TEMP; # ignore errors, since only on ext2 supported! - system $editor, $TEMP; - } - else { - print "Could not find an editor to use!\n"; - $db->unlock(); - 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; - $db->unlock(); - return; - } - - $c = 0; - while () { - $note = $note . $_; - } - chomp $note; - close E; - - # privacy! - unlink $TEMP; - } - else { - print "enter the text of the note, end with a single .\n"; - do { - $line = ; - $note = $note . $line; - } until $line eq ".\n"; - # remove the . ! - chop $note; - chop $note; - } - - # look if the note was empty, so don't store it! - if ($note =~ /^\s*$/) { - print "...your note was empty and will not be saved.\n"; - $db->unlock(); - return; - } - # since we have not a number, look for the next one available: - $number = $db->get_nextnum(); - if ($TOPIC && $CurTopic ne "") { - @topic = split(/$conf{topicseparator}/,$note); - if ($topic[1] eq "") { - $note = $PATH . "\n$note"; - } - } - $note = &add_ticket($note); - - $db->set_new($number,$note,$date); - # everything ok until here! - print "note stored. it has been assigned the number $number.\n\n"; - $db->unlock(); - } - -sub add_ticket { - my $orignote = shift; - if ($conf{addticket}) { - my ($topic, $title, $rest) = split /\n/, $orignote, 3; - my $note = ""; - if ($topic =~ /^\//) { - # topic path, keep it - $note .= "$topic\n"; - } - else { - # no topic - $rest = "$title\n$rest"; - $title = $topic; - } - if ($title !~ /^\[[a-z0-9A-Z]+\]/) { - # no ticket number, so create one - my $ticket = &ticket(); - $title = "[" . ticket() . "] " . $title; - } - $note .= "$title\n$rest"; - return $note; - } - else { - return $orignote; - } -} - - -############################### DELETE ################################## -sub del { - my($i,@count, $setnum, $pos, $ERR); - if ($conf{readonly}) { - print "readonly\n"; - return; - } - # delete a note - &num_bereich; # get @NumBlock from $number - - return if $db->lock(); - - 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(); - - $db->unlock(); - @NumBlock = (); - } - -############################### EDIT ################################## -sub edit { - my($keeptime, $date, $editor, $TEMP, $note, $t, $num, $match, $backup); - if ($conf{readonly}) { - print "readonly\n"; - return; - } - # edit a note - $date = &getdate; - - return if $db->lock(); - - ($note, $keeptime) = $db->get_single($number); - if ($keeptime eq "") { - print "no note with that number found ($number)!\n\n"; - if($mode ne "interactive") { - $db->unlock(); - exit(0); - } - else { - $db->unlock(); - return; - } - } - - $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; - $editor = &find_editor; - - $backup = $note; - - if ($editor) { - system ($editor, $TEMP) and die "Could not execute $editor: $!\n"; - } - 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 || die $!; - - if ($note ne $backup) { - if ($conf{keeptimestamp}) { - $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"; - } - else { - print "note number $number has not changed, no save done.\n"; - } - $db->unlock(); - } - -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(); - - # FIXME: prepare hashing in NOTEDB class - foreach $num (sort { $a <=> $b } keys %res) { - print STDOUT "dumping note number $num to $dump_file\n" if($dump_file ne "-"); - my($title, $path, $body); - if ($res{$num}->{note} =~ /^\//) { - ($path, $title, $body) = split /\n/, $res{$num}->{note}, 3; - } - else { - ($title, $body) = split /\n/, $res{$num}->{note}, 2; - $path = ''; - } - my $date = $res{$num}->{date}; - $res{$num} = { body => $body, title => $title, path => $path, date => $date}; - } - - if($conf{usejson}) { - my $json = JSON::PP->new->utf8->pretty; - print $json->encode(\%res); - } - else { - warn "Deprecation notice: YAML export format will not be supported in the future! -Enable JSON using the UseJSON config parameter or the -j commandline parameter!"; - print Dump(\%res); - } - - close(DUMPFILE); - select STDOUT; -} - -sub import { - my($num, $start, $complete, $dummi, $note, $date, $time, $number, $stdin, $DUMP, %data); - # 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; - } - - my $serialized = join '', <$DUMP>; - - my $res; - - if($serialized =~ /^\{/) { - $res = decode_json($serialized); - } - else { - $res = Load($serialized); - } - - foreach my $number (keys %{$res}) { - my $note; - if ($res->{$number}->{path}) { - $note = "$res->{$number}->{path}\n$res->{$number}->{title}\n$res->{$number}->{body}"; - } - else { - $note = "$res->{$number}->{title}\n$res->{$number}->{body}"; - } - $data{$number} = { - date => $res->{$number}->{date}, - note => &add_ticket($note) - }; - print "fetched note number $number from $dump_file from $res->{$number}->{date}.\n" if(!$stdin); - $number++; - } - - $db->set_del_all() if($ImportType ne ""); - $db->import_data(\%data); -} - - - -sub determine_width { - # determine terminal wide, if possible - if ($maxlen eq "auto") { - eval { - my $wide = `stty -a`; - if ($wide =~ /columns (\d+?);/) { - $maxlen = $1 - 32; # (32 = timestamp + borders) - } - elsif ($wide =~ /; (\d+?) columns;/) { - # bsd - $maxlen = $1 - 32; # (32 = timestamp + borders) - } - else { - # stty didn't work - $maxlen = 80 - 32; - } - }; - } -} - -sub clear { - # first, try to determine the terminal height - return if(!$conf{autoclear}); - my $hoch; - eval { - my $height = `stty -a`; - if ($height =~ /rows (\d+?);/) { - $hoch = $1; - } - elsif ($height =~ /; (\d+?) rows;/) { - # bsd - $hoch = $1; - } - }; - if (!$hoch) { - # stty didn't work - $hoch = 25; - } - print "\n" x $hoch; -} - -sub interactive { - my($B, $BB, $menu, $char, $Channel); - $Channel = $|; - local $| = 1; - # 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! - &determine_width; - $ListType = ($conf{defaultlong}) ? "LONG" : ""; - - # show initial note entry - if ($conf{motd}) { - &motd; - } - - # show initial listing - &list; - - my ($term, $prompt, $attribs); - eval { require Term::ReadLine; }; - if (!$@) { - $term = new Term::ReadLine(''); - $attribs = $term->Attribs; - $attribs->{completion_function} = \&complete; - } - - for (;;) { - $ListType = ($conf{defaultlong}) ? "LONG" : ""; - undef $SetTitle; - if ($CurDepth > 2) { - print C $menu . $TOPICC . "../" . $CurTopic . $_TOPICC; - } - else { - print C $menu . $TOPICC . $CurTopic . $_TOPICC; - } - - if ($conf{readonly}) { - print " [readonly] "; - } - - print ">"; - - # endless until user press "Q" or "q"! - if ($term) { - if (defined ($char = $term->readline(" "))) { - $term->addhistory($char) if $char =~ /\S/; - $char =~ s/\s*$//; # remove trailing whitespace (could come from auto-completion) - } - else { - # shutdown - $| = $Channel; - print "\n\ngood bye!\n"; - exit(0); - } - } - else { - $char = ; - chomp $char; - } - - &determine_width; - &clear; - - 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 =~ /^c\s*$/) { - print "Missing parameter (parameter=value), available ones:\n"; - foreach my $var (sort keys %conf) { - if ($var !~ /^$hardparams/ && $var !~ /::/) { - printf "%20s = %s\n", $var, $conf{$var}; - } - } - } - elsif ($char =~ /^c\s*(.+?)\s*=\s*(.+?)/) { - # configure - my $param = $1; - my $value = $2; - if ($param !~ /^$hardparams/ && $param !~ /::/ && exists $conf{$param}) { - print "Changing $param from $conf{$param} to $value\n"; - $conf{$param} = $value; - } - else { - print "Unknown config parameter $param!\n"; - } - } - elsif ($char =~ /^\.\.$/ || $char =~ /^cd\s*\.\.$/) { - $CurDepth-- if ($CurDepth > 1); - $CurTopic = $LastTopic[$CurDepth]; - pop @LastTopic; # remove last element - &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 ($unchar =~ /^\d+?$/ && $conf{short_cd}) { - # just a number! - my @topic; - my ($cnote, $cdate) = $db->get_single($unchar); - my ($firstline,$dummy) = split /\n/, $cnote, 2; - if ($firstline =~ /^($conf{topicseparator})/) { - @topic = split(/$conf{topicseparator}/,$firstline); - } - else { - @topic = (); - } - if (@topic) { - # only jump, if, and only if there were at least one topic! - $CurDepth = $#topic + 1; - $CurTopic = pop @topic; - @LastTopic = (""); - push @LastTopic, @topic; - } - &list; - } - elsif ($unchar eq $conf{topicseparator}) { - # cd / - $CurDepth = 1; - $CurTopic = ""; - &list; - } - elsif (exists $TP{$char} || exists $TP{$unchar}) { - $char = $unchar if(exists $TP{$unchar}); - $LastTopic[$CurDepth] = $CurTopic; - $CurTopic = $char; - $CurDepth++; - &list; - } - else { - # try incomplete match - my @matches; - foreach my $topic (keys %TP) { - if ($topic =~ /^$char/) { - push @matches, $topic; - } - } - my $nm = scalar @matches; - if ($nm == 1) { - # match on one incomplete topic, use this - $LastTopic[$CurDepth] = $CurTopic; - $CurTopic = $matches[0]; - $CurDepth++; - &list; - } - elsif ($nm > 1) { - print "available topics: " . join( "," , @matches) . "\n"; - } - else { - print "\nunknown command!\n"; - } - } - undef $unchar; - } - } - } - - -sub usage - { - print qq~This is the program note $VERSION by T.v.Dein (c) 1999-2017. -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: - - -c, --config file - Use another config file than the default \$HOME/.noterc. - - -n, --new - Create a new note entry. - - -l, --list [topic] - Lists all existing notes. If no topic were specified, it will - display a list of all existing topics. See the section TOPICS for - details about topics. - - -L, --longlist [topic] - The same as -l but prints also the timestamp of the notes. - - -t, --topic - Prints a list of all topics as a tree. - - -T, --longtopic - Prints the topic-tree with the notes under each topic. - - -s, --search string - Searches for trough the notes database. See the section - SEARCHING for details about the search engine. - - -e, --edit number - Edit the note with the number using your default editor or - the one you specified in the config file. - - -d, --delete number - Delete the note with the number . You can delete multiple - notes with one command. "1-4" deletes the notes 1,2,3,4. And - "1,5,7" deletes the specified ones. - - -D, --Dump [file | -] - Dumps all notes to the textfile . If is a "-" it will - be printed out to standard output (STDOUT). - - -I, --Import file | - - 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. - Use with care. - - -r, --raw - Raw mode, output will not be formatted. Works not in interactive - mode, only on cmd-line for list and display. That means, no colors - will be used and no lines or titles. - - -i, --interactive - Start note in interactive mode. See the section INTERACTIVE MODE - for details on this mode. - - --encrypt cleartext - Encrypt the given clear text string. You would need that if you - want to store the mysql password not in cleartext in the config(if - you are using the mysql backend!). - - -h, --help - Display this help screen. - - -v, --version - Display the version number. - - - If you run note just 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, i.e.: - - cat sometextfile | note - - -Read the note(1) manpage for more details. -~; - exit 1; - } - -sub find_editor { - return $conf{preferrededitor} || $ENV{"VISUAL"} || $ENV{"EDITOR"} || "vi"; -} - -#/ - -sub format { - # make text bold/underlined/inverse using current $NOTEC - my($note) = @_; - if ($conf{formattext}) { - # prepare colors to be used for replacement - 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>/; - - if ($conf{formattext} eq "simple") { - $note =~ s/\*([^\*]*)\*/$BN$1$_BN/g; - $note =~ s/_([^_]*)_/$UN$1$_UN/g; - $note =~ s/{([^}]*)}/$IN$1$_IN/g; - $note =~ s#(?$1#g; - } - else { - $note =~ s/\*\*([^\*]{2,})\*\*/$BN$1$_BN/g; - $note =~ s/__([^_]{2,})__/$UN$1$_UN/g; - $note =~ s/\{\{([^}]{2,})\}\}/$IN$1$_IN/g; - $note =~ s#//([^/]{2,})//#$1#g; - } - - $note =~ s/(<\/.*>)/$1$NOTEC/g; - } - $note; -} - -sub output { - my($SSS, $LINE, $num, $note, $time, $TYPE, $L, $LONGSPC, $R, $PathLen, $SP, $title, $CUTSPACE, - $VersionLen, $len, $diff, $Space, $nlen, $txtlen, $count); - ($num, $note, $time, $TYPE, $count) = @_; - - $txtlen = ($ListType eq "LONG") ? $maxlen : $timelen + $maxlen; - $note = &format($note); - - $SSS = "-" x ($maxlen + 30); - $nlen = length("$num"); - $LINE = "$BORDERC $SSS $_BORDERC\n"; - $LONGSPC = " " x (25 - $nlen); - if ($conf{printlines}) { - $L = $BORDERC . "[" . $_BORDERC; - $R = $BORDERC . "]" . $_BORDERC; - } - $PathLen = length($PATH); # will be ZERO, if not in TOPIC mode! - $VersionLen = length($VERSION) + 7; - - if ($TYPE ne "SINGLE") { - if (!$SetTitle) { - $SP = ""; - # print only if it is the first line! - $SP = " " x ($maxlen - 2 - $PathLen - $VersionLen); - if (!$Raw) { - # no title in raw-mode! - print C $LINE if ($conf{printlines}); - print C "$L $NUMC#$_NUMC "; - if ($ListType eq "LONG") { - print C " $TIMEC" . "creation date$_TIMEC "; - } - else { - print $LONGSPC if ($conf{printlines}); - } - if ($TOPIC) { - print C $TOPICC . "$PATH $_TOPICC$SP" . " note $VERSION $R\n"; - } - else { - print C $NOTEC . "note$_NOTEC$SP" . " note $VERSION $R\n"; - } - print C $LINE if ($conf{printlines}); - } - $SetTitle = 1; - } - $title = ""; - $CUTSPACE = " " x $txtlen; - if ($TYPE eq "search") { - $note =~ s/^\Q$conf{topicseparator}\E.+?\Q$conf{topicseparator}\E\n//; - } - $note =~ s/\n/$CUTSPACE/g; - $len = length($note); - if ($len < ($txtlen - 2 - $nlen)) { - $diff = $txtlen - $len; - if (!$Raw) { - if ($num eq "-") { - $Space = " " x $diff; - $title = $BORDERC . $TOPICC . $note . " " . $_TOPICC . $Space . "$_BORDERC"; - } - else { - $Space = " " x ($diff - ($nlen - 1)); - $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 =~ /^ => (.*)$conf{topicseparator} (.*)$/) { - $title = "$1$conf{topicseparator} $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 if ($conf{printlines}); - } - } - else { - # we will not reach this in raw-mode, therefore no decision here! - chomp $note; - $Space = " " x (($maxlen + $timelen) - $nlen - 16); - - *CHANNEL = *STDOUT; - my $usecol = $conf{usecolors}; - - if ($conf{less}) { - my $less = "less"; - if ($conf{less} ne 1) { - # use given less command line - $less = $conf{less}; - } - if (open LESS, "|$less") { - *CHANNEL = *LESS; - $conf{usecolors} = 0; - } - } - - print CHANNEL C $LINE if ($conf{printlines}); - print CHANNEL C "$L $NUMC$num$_NUMC $R$L$TIMEC$time$_TIMEC $Space$R\n"; - print CHANNEL C "\n"; - print CHANNEL C $NOTEC . $note . $_NOTEC . "\n"; - print CHANNEL C $LINE if ($count == 1 && $conf{printlines}); - - if ($conf{less}) { - close LESS; - } - - $conf{usecolors} = $usecol; - } - } - - - -sub C { - my($default, $S, $Col, $NC, $T); - $default = "\033[0m"; - $S = $_[0]; - foreach $Col (%Color) { - if ($S =~ /<$Col>/g) { - if ($conf{usecolors}) { - $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 commas? - @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/; - if ($conf{timeformat}) { - my $back = $conf{timeformat}; - $back =~ s/YYYY/$year/; - $back =~ s/YY/substr($year, 1, 2)/e; - $back =~ s/MM/$mon/; - $back =~ s/DD/$mday/; - $back =~ s/mm/$min/; - $back =~ s/hh/$hour/; - $back =~ s/ss/$sec/; - return $back; - } - return "$mday.$mon.$year $hour:$min:$sec"; - } - - -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 = File::Spec->catfile($conf{tempdirectory}, $USER . $random); - if (-e $tempfile) { - # avoid race conditions! - unlink $tempfile; - } - return $tempfile; - } - - - -sub help { - my $B = ""; - my $BB = ""; - my($S, $L, $T, $Q, $H, $N, $D, $E, $C); - $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; - $C = $B . "C" . $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. -$C Change note config online. Use with care! -$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.~; - } - print C qq~ - -All commands except the List and Topic commands are case insensitive. -Read the note(1) manpage for more details.$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 =~ /^($conf{topicseparator})/) { - $firstline =~ s/($conf{topicseparator})*$//; #remove Topicseparator - @nodes = split(/$conf{topicseparator}/,$firstline); - } - else { - @nodes = (); #("$conf{topicseparator}"); - $text = $firstline; - } - &determine_width; # ensure $maxlen values for &tree in non interactive modes - &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[" . $conf{topicseparator} . $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*$//; - $value =~ s/\s*#.*$//; - if ($value =~ /^(~\/)(.*)$/) { - $value = File::Spec->catfile($ENV{HOME}, $2); - } - - if ($value =~ /^(yes|on|1)$/i) { - $value = 1; - } - elsif ($value =~ /^(no|off|0)$/i) { - $value = 0; - } - - $option = lc($option); - - if ($option =~ /^(.+)::(.*)$/) { - # driver option - $driver{$1}->{$2} = $value; - } - else { - # other option - $conf{$option} = $value; - } - } - - close CONFIG; -} - - -sub complete { - my ($text, $line, $start) = @_; - - if ($line =~ /^\s*$/) { - # notes or topics allowed - return @completion_topics, @completion_notes; - } - if ($line =~ /^cd/) { - # only topics allowed - return @completion_topics, ".."; - } - if ($line =~ /^l/i) { - # only topics allowed - return @completion_topics; - } - if ($line =~ /^[ed]/) { - # only notes allowed - return @completion_notes; - } - if ($line =~ /^[snt\?q]/i) { - # nothing allowed - return (); - } -} - -sub load_driver { - my ($parent) = @_; - - if ($parent) { - my $pkg = "NOTEDB"; - eval "use $pkg;"; - if ($@) { - die "Could not load the NOTEDB module: $@\n"; - } - } - else { - # load the backend driver - my $pkg = "NOTEDB::$conf{dbdriver}"; - eval "use $pkg;"; - if ($@) { - die "$conf{dbdriver} backend unsupported: $@\n"; - } - else { - $db = $pkg->new(%{$driver{$conf{dbdriver}}}); - } - } -} - -sub ticket { - return join "", (map { $randomlist[int(rand($#randomlist))] } (0 .. 10) ); -} - -sub is_interactive { - return -t STDIN && -t STDOUT; -} - -__END__ diff --git a/bin/stresstest.sh b/bin/stresstest.sh deleted file mode 100755 index 4913a02..0000000 --- a/bin/stresstest.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/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/config/noterc b/config/noterc deleted file mode 100644 index bf78f19..0000000 --- a/config/noterc +++ /dev/null @@ -1,280 +0,0 @@ -# note 1.4.1 -*- conf -*- -# -# This is a sample config for the note script There are useful -# defaults set in note itself. -# -# Copy it to your $HOME as .noterc -# -# Comments start with #, empty lines will be ignored. -# -# To turn on an option, set it to: 1, on or yes -# To turn off an option, set it to: 0, off or no -# -# An option consists of an atribute-value pair separated by minimum -# one space (more spaces and/or tabs are allowed) and an optional -# equal sign in between. -# -# Variable names are case in-sensitive. -# -# Refer to the manpage to learn more about the config - - - - -# -# 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", "mysql", "general", "dumper", "pwsafe3" or "text". You must -# also edit/uncomment one section below for the backend you want to -# use! -dbdriver = binary - - - -# -# BINARY backend (the default) -binary::dbname = ~/.notedb # filename -binary::MaxNoteByte = 4096 # max bytes per note entry -binary::MaxTimeByte = 64 # max bytes for the date - - - -# -# MYSQL backend -mysql::dbhost = localhost # hostname -mysql::dbport = 3306 # tcp port -mysql::dbuser = you # db login -mysql::dbpasswd = # db password -mysql::dbname = # database name (default: note) -mysql::encrypt_passwd = 0 # mysql::dbpasswd is - # encrypted (note --encrypt) - - -# -# DBM backend -dbm::directory = ~/.notedb.dbm - - - -# -# GENERAL backend -general::dbname = ~/.notedb.txt - - -# -# TEXT backend -text::dbname = ~/.notedb.storable - - -# -# DUMPER backend -dumper::dbname = ~/.notedb.dumper - - - -# -# Password Safe v3 backend Some notes on this one: This backend -# maintains encryption itself, which is mandatory as well. So you'll -# have to disable encryption (UseEncryption = NO)! -# -# The Password Safe v3 file has its own fields for password and -# username, which note doesn't have. To be compatible, the pwsafe3 -# backend parses the note text for those fields and stores them -# accordignly to the db: -# -# For username field: user|username|login|account|benutzer -# For passwd field: password|pass|passwd|kennwort|pw -# -# If it doesn't find it, it will put empty strings into the pwsafe3 -# database. -# -# The pwsafe3 database can be accessed by Password Safe (see: -# http://passwordsafe.sourceforge.net/) or other tools which support -# the format (see: -# http://passwordsafe.sourceforge.net/relatedprojects.shtml) -pwsafe3::dbname = ~/.notedb.psafe3 - - -# -# You can use encryption with note, that means notes and timestamps -# will be stored encrypted. This is supported by every db-backend, but -# not the pwsafe3 backend because this one has builtin encryption -# support. -UseEncryption = NO - - - -# -# 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". The default is: YES. -AlwaysInteractive = YES - - - -# -# 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: NO -DefaultLong = NO - - - -# -# You can use an external editor everytime from note instead of STDIN -# for creating new notes. The default is: YES -AlwaysEditor = YES - - - -# -# By default, note looks in the environment for a variable $EDITOR or, -# if this is not the case, for $VISUAL and as fallback it uses 'vi'. -# You can override this by setting this variable here. -PreferredEditor = - - - -# -# If you don't 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: NO -KeepTimeStamp = NO - - - -# -# You can specify your own topic separator here. The default topic -# separator is a normal slash: "/" -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 should -# determine the available size automatically. -MaxLen = auto - - - -# -# Turn this off if you dont want note to automatically clear the -# screen after displaying something and after exit. The default is: NO -AutoClear = NO - - - -# -# note can use colors for output, turn this of, if you don't like it, -# or if your terminal does not support it. The default is: YES -UseColors = NO - - - -# -# Color-definitions of the various items. Will only take effect, if -# "UseColors" is turned on! -# -# 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). -BorderColor BLACK -NumberColor blue -NoteColor green -TimeColor black -TopicColor BLACK - - - -# -# Additional to colors, you can also do a little bit of formatting -# your notes (bold, underlined, italic) text. The default is: YES. -FormatText = NO - - - -# -# 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 = ~/tmp - - - -# -# You can jump to a topic by typing "cd 13" in interactive mode. The -# deault is: NO -ShortCd = YES - - - -# -# note can use a cached copy of the note database for list/tree/search -# this is currently only supported by the binary and the mysql -# backends, the general and text backends have an internal cache. The -# default is: NO -Cache = NO - - - -# -# You can define your very own time format for time stamps -# YY - the last 2 digits of a year -# YYYY - year -# MM - month -# DD - day -# hh - hours -# mm - minutes -# ss - seconds -# This is the default: (18.10.2000 21:32:08) -TimeFormat = DD.MM.YYYY hh:mm:ss - - - -# -# You can make note readonly which is useful for database copies The -# default is: NO -ReadOnly = NO - - - -# -# Note may separate titles and topics using horizontal lines when -# listing them. You can turn on this behavior by setting PrintLines to -# YES. The default is: NO -PrintLines = NO - - - -# -# Add a hash to identify notes. Such a hash will persist several -# importy/export cycles and makes each single note unique. -AddTicket = NO - - -# -# Show an entry on startup. If you want it, create such an entry and -# supply its number here -motd = - - -# -# Enable JSON formatted backups. The option will be removed in version -# 1.5 and become the only available option. In earlier versions: if -# unset or set to NO, YAML will be used. -UseJSON = YES - diff --git a/contrib/sync-combine-two-yaml-exports-into-one.pl b/contrib/sync-combine-two-yaml-exports-into-one.pl deleted file mode 100755 index d65cfc6..0000000 --- a/contrib/sync-combine-two-yaml-exports-into-one.pl +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/perl -use warnings; -use strict; -no strict "refs"; - -use IO::All; -use Encode; -# only YAML::XS is able to properly load our data (others fail -# invariably) -use YAML::XS qw(Load); -# only YAML is able to properly Dump the data YAML::XS generates -# various kinds of multiline entries like "line\nline2\nline3" end up -# literally in the generated yaml, which note is then unable to -# feed. So, the pure perl version is better as it always generates -# multiline entries for data containing newlines -use YAML qw(Dump); -use Data::Dumper; -use Term::ANSIColor; - -my ($yf1, $yf2, $outfile) = @ARGV; - - -# read both input files and parse yaml into data structure, fix -# non-printables -my $badutf81 < io $yf1; -my $yaml1 = decode( 'UTF-8', $badutf81 =~ s/[^\x00-\x7F]+//gr ); -my $y1 = Load $yaml1 or die "Could not load $yf1: $!"; - -my $badutf82 < io $yf2; -my $yaml2 = decode( 'UTF-8', $badutf82 =~ s/[^\x00-\x7F]+//gr ); -my $y2 = Load $yaml2 or die "Could not load $yf2: $!"; - -# convert to comparable hashes with unique keys -my $hash1 = &hashify($y1); -my $hash2 = &hashify($y2); - -# diff and recombine the two into a new one -my $combinedhash = &hash2note(&diff($hash1, $hash2)); - -#print Dumper($combinedhash); exit; - -# turn into yaml -my $combindedyaml = Dump($combinedhash); - -# perl uses scalars as hash keys (read: strings) so we need to unquote -# them here to make note happy -$combindedyaml =~ s/^'(\d+)':/$1:/gm; - -# done -my $out = io $outfile; -$combindedyaml > $out; - - -print "\nDone. Wrote combined hashes to $outfile\n"; - -sub hash2note { - # convert given hash into note format with number as key - my $hash = shift; - my $new; - my $i = 0; - - foreach my $path (sort keys %{$hash}) { - $new->{++$i} = $hash->{$path}; - } - - return $new; -} - -sub diff { - # diff the two hashes, create a new combined one - my($hash1, $hash2) = @_; - my $new; - - # iterate over hash1, store duplicates and remove them in hash2, - # store different entries and remove in both, - # store those missing in hash2 and delete them in hash1 - foreach my $path (sort keys %{$hash1}) { - if (exists $hash2->{$path}) { - if ($hash2->{$path}->{body} eq $hash1->{$path}->{body}) { - #printf STDERR "%s => %s is duplicate\n", $path, $hash1->{$path}->{title}; - $new->{$path} = delete $hash2->{$path}; - delete $hash1->{$path}; - } - else { - printf STDERR "%s => %s is different\n", $path, $hash1->{$path}->{title}; - my $which = &askdiff($hash1->{$path}->{body}, $hash2->{$path}->{body}, $hash1->{$path}->{title}); - - if ($which eq 'l') { - # use left - $new->{$path} = delete $hash1->{$path}; - delete $hash2->{$path}; - } - elsif ($which eq 'r') { - # use right - $new->{$path} = delete $hash2->{$path}; - delete $hash1->{$path}; - } - else { - # both - $new->{$path} = delete $hash1->{$path}; - $new->{$path . 2} = delete $hash2->{$path}; - } - } - } - else { - #printf STDERR "%s => %s is missing in hash2\n", $path, $hash1->{$path}->{title}; - $new->{$path} = delete $hash1->{$path}; - } - } - - # store any lefovers of hash1 - foreach my $path (sort keys %{$hash1}) { - #printf STDERR "%s => %s is left in hash1\n", $path, $hash1->{$path}->{title}; - $new->{$path} = $hash1->{$path}; - } - - # store any lefovers of hash2 - foreach my $path (sort keys %{$hash2}) { - #printf STDERR "%s => %s is left in hash2\n", $path, $hash2->{$path}->{title}; - $new->{$path} = $hash2->{$path}; - } - - return $new -} - -sub askdiff { - my ($left, $right, $title) = @_; - $left > io("/tmp/$$-body-left"); - $right > io("/tmp/$$-body-right"); - my $diff = `diff --side-by-side /tmp/$$-body-left /tmp/$$-body-right`; - - print color ('bold'); - print "\n\nEntry $title exists in both hashes but differ. Diff:\n"; - print color ('reset'); - - print "$diff\n"; - - print color ('bold'); - print "keep [l]eft, keep [r]ight, keep [b]oth? "; - print color ('reset'); - - my $answer = ; - chomp $answer; - - system("rm -f /tmp/$$-body-left /tmp/$$-body-right"); - - if ($answer !~ /^[blr]$/) { - print "Wrong answer $answer, using [b]oth!\n"; - return 'b'; - } - - return $answer; -} - -sub hashify { - # create new hash with path+title as key instead of id's - my $data = shift; - my $new = {}; - - foreach my $id (keys %{$data} ) { - my $path = $data->{$id}->{path} . '|' . $data->{$id}->{title}; - if (exists $new->{$path}) { - die "$path already exists!\n"; - } - else { - $new->{$path} = $data->{$id}; - } - } - - return $new; -} - diff --git a/lib/NOTEDB.pm b/lib/NOTEDB.pm deleted file mode 100644 index 7e7f5ac..0000000 --- a/lib/NOTEDB.pm +++ /dev/null @@ -1,306 +0,0 @@ -# -# this is a generic module, used by note database -# backend modules. -# -# Copyright (c) 2000-2017 T.v.Dein - - -package NOTEDB; - -use Exporter (); -use vars qw(@ISA @EXPORT $crypt_supported); - -$NOTEDB::VERSION = "1.45"; - -BEGIN { - # make sure, it works, otherwise encryption - # is not supported on this system! - eval { require Crypt::CBC; }; - if($@) { - $NOTEDB::crypt_supported = 0; - } - else { - $NOTEDB::crypt_supported = 1; - } -} - - -sub no_crypt { - $NOTEDB::crypt_supported = 0; -} - - -sub use_crypt { - my($this,$key,$method) = @_; - my($cipher); - if($NOTEDB::crypt_supported == 1) { - eval { - $cipher = new Crypt::CBC($key, $method); - }; - if($@) { - print "warning: Crypt::$method not supported by system!\n"; - $NOTEDB::crypt_supported = 0; - } - else { - $this->{cipher} = $cipher; - } - } - else{ - print "warning: Crypt::CBC not supported by system!\n"; - } -} - - -sub use_cache { - # - # this sub turns on cache support - # - my $this = shift; - $this->{use_cache} = 1; - $this->{changed} = 1; -} - -sub cache { - # - # store the whole db as hash - # if use_cache is turned on - # - my $this = shift; - if ($this->{use_cache}) { - my %res = @_; - %{$this->{cache}} = %res; - } -} - -sub unchanged { - # - # return true if $this->{changed} is true, this will - # be set to true by writing subs using $this->changed(). - # - my $this = shift; - return 0 if(!$this->{use_cache}); - if ($this->{changed}) { - $this->{changed} = 0; - return 0; - } - else { - print "%\n"; - return 1; - } -} - -sub changed { - # - # turn on $this->{changed} - # this will be used by update or create subs. - # - my $this = shift; - $this->{changed} = 1; - return 1; -} - - -sub generate_search { - # - # get user input and create perlcode ready for eval - # sample input: - # "ann.a OR eg???on AND u*do$" - # resulting output: - # "$match = 1 if(/ann\.a/i or /eg...on/i and /u.*do\$/i ); - # - my($this, $string) = @_; - - my $case = "i"; - - if ($string =~ /^\/.+?\/$/) { - return $string; - } - elsif (!$string) { - return "/^/"; - } - - # we will get a / in front of the first word too! - $string = " " . $string . " "; - - # check for apostrophs - $string =~ s/(?<=\s)(\(??)("[^"]+"|\S+)(\)??)(?=\s)/$1 . $this->check_exact($2) . $3/ge; - - # remove odd spaces infront of and after »and« and »or« - $string =~ s/\s\s*(AND|OR)\s\s*/ $1 /g; - - # remove odd spaces infront of »(« and after »)« - $string =~ s/(\s*\()/\(/g; - $string =~ s/(\)\s*)/\)/g; - - # remove first and last space so it will not masked! - $string =~ s/^\s//; - $string =~ s/\s$//; - - # mask spaces if not infront of or after »and« and »or« - $string =~ s/(?check_or($1, $case) /ge; - - # remove slashes on »and« and »or« - $string =~ s/\/(and|or)\/$case/$1/g; - - # remove spaces inside /string/ constructs - $string =~ s/(? '.*', - '?' => '.', - '[' => '[', - ']' => ']', - '+' => '\+', - '.' => '\.', - '$' => '\$', - '@' => '\@', - '/' => '\/', - '|' => '\|', - '}' => '\}', - '{' => '\{', - ); - - my %escapes = ( - '*' => '\*', - '?' => '\?', - '[' => '[', - ']' => ']', - '+' => '\+', - '.' => '\.', - '$' => '\$', - '@' => '\@', - '(' => '\(', - ')' => '\)', - '/' => '\/', - '|' => '\|', - '}' => '\}', - '{' => '\{', - ); - - # mask backslash - $str =~ s/\\/\\\\/g; - - - if ($str =~ /^"/ && $str =~ /"$/) { - # mask bracket-constructs - $str =~ s/(.)/$escapes{$1} || "$1"/ge; - } - else { - $str =~ s/(.)/$wildcards{$1} || "$1"/ge; - } - - $str =~ s/^"//; - $str =~ s/"$//; - - # mask spaces - $str =~ s/\s/\\s/g; - return $str; -} - - - - -sub lock { - my ($this) = @_; - - if (-e $this->{LOCKFILE}) { - open LOCK, "<$this->{LOCKFILE}" or die "could not open $this->{LOCKFILE}: $!\n"; - my $data = ; - close LOCK; - chomp $data; - print "-- waiting for lock by $data --\n"; - print "-- remove the lockfile if you are sure: \"$this->{LOCKFILE}\" --\n"; - } - - my $timeout = 60; - - eval { - local $SIG{ALRM} = sub { die "timeout" }; - local $SIG{INT} = sub { die "interrupted" }; - alarm $timeout - 2; - while (1) { - if (! -e $this->{LOCKFILE}) { - umask 022; - open LOCK, ">$this->{LOCKFILE}" or die "could not open $this->{LOCKFILE}: $!\n"; - flock LOCK, LOCK_EX; - - my $now = scalar localtime(); - print LOCK "$ENV{USER} since $now (PID: $$)\n"; - - flock LOCK, LOCK_UN; - close LOCK; - alarm 0; - return 0; - } - printf " %0d\r", $timeout; - $timeout--; - sleep 1; - } - }; - if($@) { - if ($@ =~ /^inter/) { - print " interrupted\n"; - } - else { - print $@; - print " timeout\n"; - } - return 1; - } - return 0; -} - -sub unlock { - my ($this) = @_; - unlink $this->{LOCKFILE}; -} - - - -1; diff --git a/lib/NOTEDB/README b/lib/NOTEDB/README deleted file mode 100644 index 390f83a..0000000 --- a/lib/NOTEDB/README +++ /dev/null @@ -1,7 +0,0 @@ -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 other ideas in mind... - -Therefore, please ignore these file. There is nothing -to edit or to do. Simply leave this directory :-) diff --git a/lib/NOTEDB/binary.pm b/lib/NOTEDB/binary.pm deleted file mode 100644 index 1c7a25b..0000000 --- a/lib/NOTEDB/binary.pm +++ /dev/null @@ -1,496 +0,0 @@ -#!/usr/bin/perl -# $Id: binary.pm,v 1.3 2000/08/11 00:05:58 zarahg Exp $ -# Perl module for note -# binary database backend. see docu: perldoc NOTEDB::binary -# -package NOTEDB::binary; - -$NOTEDB::binary::VERSION = "1.13"; - -use strict; -use IO::Seekable; -use File::Spec; -use FileHandle; -use Fcntl qw(LOCK_EX LOCK_UN); - -use NOTEDB; -use Exporter (); -use vars qw(@ISA @EXPORT); -@ISA = qw(NOTEDB Exporter); - - - - -sub new { - my($this, %param) = @_; - - my $class = ref($this) || $this; - my $self = {}; - bless($self,$class); - - $self->{NOTEDB} = $self->{dbname} = $param{dbname} || File::Spec->catfile($ENV{HOME}, ".notedb"); - my $MAX_NOTE = $param{MaxNoteByte} || 4096; - my $MAX_TIME = $param{MaxTimeByte} || 64; - - if(! -e $self->{NOTEDB}) { - open(TT,">$self->{NOTEDB}") or die "Could not create $self->{NOTEDB}: $!\n"; - close (TT); - } - elsif(! -w $self->{NOTEDB}) { - print "$self->{NOTEDB} is not writable!\n"; - exit(1); - } - - - my $TYPEDEF = "i a$MAX_NOTE a$MAX_TIME"; - my $SIZEOF = length pack($TYPEDEF, () ); - - $self->{sizeof} = $SIZEOF; - $self->{typedef} = $TYPEDEF; - $self->{maxnote} = $MAX_NOTE; - $self->{LOCKFILE} = $self->{NOTEDB} . "~LOCK"; - - return $self; - } - - -sub DESTROY - { - # clean the desk! - } - - sub version { - my $this = shift; - return $NOTEDB::binary::VERSION; - } - - - - sub set_del_all - { - my $this = shift; - unlink $this->{NOTEDB}; - open(TT,">$this->{NOTEDB}") or die "Could not create $this->{NOTEDB}: $!\n"; - close (TT); - } - - - sub get_single { - my($this, $num) = @_; - my($address, $note, $date, $n, $t, $buffer, ); - - open NOTE, "+<$this->{NOTEDB}" or die "could not open $this->{NOTEDB}\n"; - flock NOTE, LOCK_EX; - - $address = ($num-1) * $this->{sizeof}; - seek(NOTE, $address, IO::Seekable::SEEK_SET); - read(NOTE, $buffer, $this->{sizeof}); - ($num, $n, $t) = unpack($this->{typedef}, $buffer); - - $note = $this->ude($n); - $date = $this->ude($t); - - flock NOTE, LOCK_UN; - close NOTE; - - return $note, $date; -} - - -sub get_all -{ - my $this = shift; - my($num, $note, $date, %res); - - if ($this->unchanged) { - return %{$this->{cache}}; - } - open NOTE, "+<$this->{NOTEDB}" or die "could not open $this->{NOTEDB}\n"; - flock NOTE, LOCK_EX; - my($buffer, $t, $n); - seek(NOTE, 0, 0); # START FROM BEGINNING - while(read(NOTE, $buffer, $this->{sizeof})) { - ($num, $note, $date) = unpack($this->{typedef}, $buffer); - $t = $this->ude($date); - $n = $this->ude($note); - $res{$num}->{'note'} = $n; - $res{$num}->{'date'} = $t; - } - flock NOTE, LOCK_UN; - close NOTE; - - $this->cache(%res); - return %res; -} - -sub import_data { - my ($this, $data) = @_; - foreach my $num (sort keys %{$data}) { - my $pos = $this->get_nextnum(); - $this->set_edit($pos, $data->{$num}->{note}, $data->{$num}->{date}); - } -} - -sub get_nextnum -{ - my $this = shift; - my($num, $te, $me, $buffer); - - if ($this->unchanged) { - $num = 1; - foreach (keys %{$this->{cache}}) { - $num++; - } - return $num; - } - open NOTE, "+<$this->{NOTEDB}" or die "could not open $this->{NOTEDB}\n"; - flock NOTE, LOCK_EX; - - seek(NOTE, 0, 0); # START FROM BEGINNING - while(read(NOTE, $buffer, $this->{sizeof})) { - ($num, $te, $me) = unpack($this->{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, $match); - - my $regex = $this->generate_search($searchstring); - eval $regex; - if ($@) { - print "invalid expression: \"$searchstring\"!\n"; - return; - } - $match = 0; - - if ($this->unchanged) { - foreach my $num (keys %{$this->{cache}}) { - $_ = $this->{cache}{$num}->{note}; - eval $regex; - if ($match) { - $res{$num}->{note} = $this->{cache}{$num}->{note}; - $res{$num}->{date} = $this->{cache}{$num}->{date} - } - $match = 0; - } - return %res; - } - - open NOTE, "+<$this->{NOTEDB}" or die "could not open $this->{NOTEDB}\n"; - flock NOTE, LOCK_EX; - - seek(NOTE, 0, 0); # START FROM BEGINNING - while(read(NOTE, $buffer, $this->{sizeof})) { - ($num, $note, $date) = unpack($this->{typedef}, $buffer); - $n = $this->ude($note); - $t = $this->ude($date); - $_ = $n; - eval $regex; - if($match) - { - $res{$num}->{'note'} = $n; - $res{$num}->{'date'} = $t; - } - $match = 0; - } - flock NOTE, LOCK_UN; - close NOTE; - - return %res; -} - - - - -sub set_edit { - my($this, $num, $note, $date) = @_; - - $this->warn_if_too_big($note, $num); - - my $address = ($num -1 ) * $this->{sizeof}; - - open NOTE, "+<$this->{NOTEDB}" or die "could not open $this->{NOTEDB}\n"; - flock NOTE, LOCK_EX; - - seek(NOTE, $address, IO::Seekable::SEEK_SET); - my $n = $this->uen($note); - my $t = $this->uen($date); - - my $buffer = pack($this->{typedef}, $num, $n, $t); - print NOTE $buffer; - - flock NOTE, LOCK_UN; - close NOTE; - - $this->changed; -} - - -sub set_new { - my($this, $num, $note, $date) = @_; - - $this->warn_if_too_big($note, $num); - - open NOTE, "+<$this->{NOTEDB}" or die "could not open $this->{NOTEDB}\n"; - flock NOTE, LOCK_EX; - - seek(NOTE, 0, IO::Seekable::SEEK_END); # APPEND - my $n = $this->uen($note); - my $t = $this->uen($date); - my $buffer = pack($this->{typedef}, $num, $n, $t); - print NOTE $buffer; - - flock NOTE, LOCK_UN; - close NOTE; - - $this->changed; -} - - -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, ">$this->{NOTEDB}" or die "could not open $this->{NOTEDB}\n"; - flock NOTE, LOCK_EX; - seek(NOTE, 0, 0); # START FROM BEGINNING - foreach $N (keys %orig) { - $n = $this->uen($orig{$N}->{'note'}); - $t = $this->uen($orig{$N}->{'date'}); - $buffer = pack( $this->{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; - - $this->changed; - - return; -} - -sub set_recountnums -{ - my($this) = @_; - my(%orig, $note, $date, $T, $setnum, $buffer, $n, $N, $t); - - $setnum = 1; - %orig = $this->get_all(); - - open NOTE, ">$this->{NOTEDB}" or die "could not open $this->{NOTEDB}\n"; - flock NOTE, LOCK_EX; - seek(NOTE, 0, 0); # START FROM BEGINNING - - foreach $N (sort {$a <=> $b} keys %orig) { - $n = $this->uen($orig{$N}->{'note'}); - $t = $this->uen($orig{$N}->{'date'}); - $buffer = pack( $this->{typedef}, $setnum, $n, $t); - print NOTE $buffer; - seek(NOTE, 0, IO::Seekable::SEEK_END); - $setnum++; - } - flock NOTE, LOCK_UN; - close NOTE; - - $this->changed; - - return; -} - -sub uen -{ - my $this = shift; - my($T); - if($NOTEDB::crypt_supported == 1) { - eval { - $T = pack("u", $this->{cipher}->encrypt($_[0])); - }; - } - else { - $T = pack("u", $_[0]); - } - chomp $T; - - return $T; -} - -sub ude -{ - my $this = shift; - my($T); - if($NOTEDB::crypt_supported == 1) { - eval { - $T = $this->{cipher}->decrypt(unpack("u",$_[0])); - }; - } - else { - $T = unpack("u", $_[0]); - } - return $T; -} - - -sub warn_if_too_big { - my ($this, $note, $num) = @_; - - my $len = length($this->uen($note)); - - if ($len > $this->{maxnote}) { - # calculate the 30% uuencoding overhead - my $overhead = int(($this->{maxnote} / 100) * 28); - - # fetch what's left by driver - my $left = substr $note, $this->{maxnote} - $overhead; - - $left = "\n$left\n"; - $left =~ s/\n/\n> /gs; - - print STDERR "*** WARNING $this->{version} WARNING ***\n" - ."The driver encountered a string length problem with your\n" - ."note entry number $num. The entry is too long. Either shorten\n" - ."the entry or resize the database field for entries.\n\n" - ."The following data has been cut off the entry:\n" - ."\n$left\n\n"; - - my $copy = File::Spec->catfile($ENV{'HOME'}, "entry-$num.txt"); - open N, ">$copy" or die "Could not open $copy: $!\n"; - print N $note; - close N; - - print "*** Wrote the complete note entry number $num to file: $copy ***\n"; - } -} - -sub _retrieve { - my ($this) = @_; - my $file = $this->{dbname}; - if (-s $file) { - if ($this->changed() || $this->{unread}) { - open NOTE, "+<$this->{NOTEDB}" or die "could not open $this->{NOTEDB}\n"; - flock NOTE, LOCK_EX; - my($buffer, $t, $n, %res); - seek(NOTE, 0, 0); # START FROM BEGINNING - while(read(NOTE, $buffer, $this->{sizeof})) { - my ($num, $note, $date) = unpack($this->{typedef}, $buffer); - $t = $this->ude($date); - $n = $this->ude($note); - $res{$num}->{'note'} = $n; - $res{$num}->{'date'} = $t; - } - flock NOTE, LOCK_UN; - close NOTE; - - $this->cache(%res); - return %res; - } - else { - return %{$this->{data}}; - } - } - else { - return (); - } -} - -sub _store { - # compatibility dummy - return 1; -} - -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 returns 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 web interface to -note... - -=head1 USAGE - -please see the section SYNOPSIS, it says it all. - -=head1 AUTHOR - -Thomas Linden . - - -=cut diff --git a/lib/NOTEDB/dbm.pm b/lib/NOTEDB/dbm.pm deleted file mode 100644 index 3d14685..0000000 --- a/lib/NOTEDB/dbm.pm +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/perl -# $Id: dbm.pm,v 1.3 2000/08/11 00:05:58 zarahg Exp $ -# Perl module for note -# DBM database backend. see docu: perldoc NOTEDB::dbm -# - -package NOTEDB::dbm; - -$NOTEDB::dbm::VERSION = "1.42"; - -use DB_File; -use NOTEDB; -use strict; -use Exporter (); -use vars qw(@ISA @EXPORT %note %date); -@ISA = qw(NOTEDB Exporter); - - - - - - -sub new -{ - my($this, %param) = @_; - my $class = ref($this) || $this; - my $self = {}; - bless($self,$class); - - my $notefile = "note.dbm"; - my $timefile = "date.dbm"; - my $dbm_dir = $self->{dbname} = $param{dbname} || File::Spec->catfile($ENV{HOME}, ".notedb.dbm"); - - if (! -d $dbm_dir) { - # try to make it - mkdir $dbm_dir || die "Could not create $dbm_dir: $!\n"; - } - - tie %note, "DB_File", "$dbm_dir/$notefile" || die "Could not tie $dbm_dir/$notefile: $!\n"; - tie %date, "DB_File", "$dbm_dir/$timefile" || die "Could not tie $dbm_dir/$timefile: $!\n"; - - $self->{LOCKFILE} = $param{dbname} . "~LOCK"; - - return $self; -} - - -sub DESTROY -{ - # clean the desk! - untie %note, %date; -} - -sub version { - my $this = shift; - return $this->{version}; -} - - -sub get_single -{ - my($this, $num) = @_; - my($note, $date); - return $this->ude ($note{$num}), $this->ude($date{$num}); -} - - -sub get_all -{ - my $this = shift; - my($num, $note, $date, %res, $real); - foreach $num (sort {$a <=> $b} keys %date) { - $res{$num}->{'note'} = $this->ude($note{$num}); - $res{$num}->{'date'} = $this->ude($date{$num}); - } - return %res; -} - -sub import_data { - my ($this, $data) = @_; - foreach my $num (keys %{$data}) { - my $pos = $this->get_nextnum(); - $note{$pos} = $this->ude($note{$num}->{note}); - $date{$pos} = $this->ude($date{$num}->{date}); - } -} - -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, $match); - - my $regex = $this->generate_search($searchstring); - eval $regex; - if ($@) { - print "invalid expression: \"$searchstring\"!\n"; - return; - } - $match = 0; - foreach $num (sort {$a <=> $b} keys %date) { - $_ = $this->ude($note{$num}); - eval $regex; - if ($match) { - $res{$num}->{'note'} = $this->ude($note{$num}); - $res{$num}->{'date'} = $this->ude($date{$num}); - } - $match = 0; - } - - 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} = $this->uen($note); - $date{$num} = $this->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 $this = shift; - my($T); - if($NOTEDB::crypt_supported == 1) { - eval { - $T = pack("u", $this->{cipher}->encrypt($_[0])); - }; - } - else { - $T = $_[0]; - } - chomp $T; - return $T; -} - -sub ude -{ - my $this = shift; - my($T); - if($NOTEDB::crypt_supported == 1) { - eval { - $T = $this->{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 returns hash like the one from get_search above - - # get the next noteid available - $next_num = $db->get_nextnum(); - - # recount all noteids starting by 1 (useful 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 web interface to -note... - -=head1 USAGE - -please see the section SYNOPSIS, it says it all. - -=head1 AUTHOR - -Thomas Linden . - - - -=cut diff --git a/lib/NOTEDB/dumper.pm b/lib/NOTEDB/dumper.pm deleted file mode 100644 index 846d279..0000000 --- a/lib/NOTEDB/dumper.pm +++ /dev/null @@ -1,371 +0,0 @@ -# Perl module for note -# text database backend. see docu: perldoc NOTEDB::text -# using Storable as backend. - -package NOTEDB::dumper; - -$NOTEDB::dumper::VERSION = "1.03"; - -use strict; -use Data::Dumper; -use File::Spec; -use MIME::Base64; - -use NOTEDB; - -use Fcntl qw(LOCK_EX LOCK_UN); - -use Exporter (); -use vars qw(@ISA @EXPORT); -@ISA = qw(NOTEDB Exporter); - - - - -sub new { - my($this, %param) = @_; - - my $class = ref($this) || $this; - my $self = {}; - bless($self,$class); - - $self->{NOTEDB} = $self->{dbname} = $param{dbname} || File::Spec->catfile($ENV{HOME}, ".notedb.dumper"); - - if(! -e $param{dbname}) { - open(TT,">$param{dbname}") or die "Could not create $param{dbname}: $!\n"; - close (TT); - } - elsif(! -w $param{dbname}) { - print "$param{dbname} is not writable!\n"; - exit(1); - } - - $self->{LOCKFILE} = $param{dbname} . "~LOCK"; - $self->{mtime} = $self->get_stat(); - $self->{unread} = 1; - $self->{data} = {}; - - return $self; -} - - -sub DESTROY -{ - # clean the desk! -} - -sub version { - my $this = shift; - return $NOTEDB::text::VERSION; -} - -sub get_stat { - my ($this) = @_; - my $mtime = (stat($this->{dbname}))[9]; - return $mtime; -} - - -sub set_del_all { - my $this = shift; - unlink $this->{NOTEDB}; - open(TT,">$this->{NOTEDB}") or die "Could not create $this->{NOTEDB}: $!\n"; - close (TT); -} - - -sub get_single { - my($this, $num) = @_; - my($address, $note, $date, $n, $t, $buffer, ); - - my %data = $this->get_all(); - return ($data{$num}->{note}, $data{$num}->{date}); -} - - -sub get_all { - my $this = shift; - my($num, $note, $date, %res); - - if ($this->unchanged) { - return %{$this->{cache}}; - } - - my %data = $this->_retrieve(); - foreach my $num (keys %data) { - $res{$num}->{note} = $this->ude($data{$num}->{note}); - $res{$num}->{date} = $this->ude($data{$num}->{date}); - } - - $this->cache(%res); - return %res; -} - -sub import_data { - my ($this, $data) = @_; - my %res = $this->_retrieve(); - my $pos = (scalar keys %res) + 1; - foreach my $num (keys %{$data}) { - $res{$pos}->{note} = $this->uen($data->{$num}->{note}); - $res{$pos}->{date} = $this->uen($data->{$num}->{date}); - $pos++; - } - $this->_store(\%res); -} - -sub get_nextnum { - my $this = shift; - my($num, $te, $me, $buffer); - - if ($this->unchanged) { - $num = 1; - foreach (keys %{$this->{cache}}) { - $num++; - } - return $num; - } - - my %data = $this->get_all(); - my $size = scalar keys %data; - $num = $size + 1; - return $num; -} - -sub get_search { - my($this, $searchstring) = @_; - my($buffer, $num, $note, $date, %res, $t, $n, $match); - - my $regex = $this->generate_search($searchstring); - eval $regex; - if ($@) { - print "invalid expression: \"$searchstring\"!\n"; - return; - } - $match = 0; - - if ($this->unchanged) { - foreach my $num (keys %{$this->{cache}}) { - $_ = $this->{cache}{$num}->{note}; - eval $regex; - if ($match) { - $res{$num}->{note} = $this->{cache}{$num}->{note}; - $res{$num}->{date} = $this->{cache}{$num}->{date} - } - $match = 0; - } - return %res; - } - - my %data = $this->get_all(); - - foreach my $num(sort keys %data) { - $_ = $data{$num}->{note}; - eval $regex; - if($match) - { - $res{$num}->{note} = $data{$num}->{note}; - $res{$num}->{date} = $data{$num}->{data}; - } - $match = 0; - } - - return %res; -} - - - - -sub set_edit { - my($this, $num, $note, $date) = @_; - - my %data = $this->_retrieve(); - - $data{$num} = { - note => $this->uen($note), - date => $this->uen($date) - }; - - $this->_store(\%data); - - $this->changed; -} - - -sub set_new { - my($this, $num, $note, $date) = @_; - $this->set_edit($num, $note, $date); -} - - -sub set_del { - my($this, $num) = @_; - my(%data, $note, $date, $T, $setnum, $buffer, $n, $N, $t); - - $setnum = 1; - - %data = $this->_retrieve(); - return "ERROR" if (! exists $data{$num}); - - delete $data{$num}; - - $this->_store(\%data); - - $this->changed; - - return; -} - -sub set_recountnums { - my($this) = @_; - my(%orig, %data, $note, $date, $T, $setnum, $buffer, $n, $N, $t); - - $setnum = 1; - %orig = $this->_retrieve(); - - foreach $N (sort {$a <=> $b} keys %orig) { - $data{$setnum} = { - note => $orig{$N}->{note}, - date => $orig{$N}->{date} - }; - $setnum++; - } - - $this->_store(\%data); - - $this->changed; - - return; -} - -sub uen { - my ($this, $raw) = @_; - my($crypted); - if($NOTEDB::crypt_supported == 1) { - eval { - $crypted = $this->{cipher}->encrypt($raw); - return encode_base64($crypted); - }; - } - else { - return $raw; - } -} - -sub ude { - my ($this, $crypted) = @_; - my($raw); - if($NOTEDB::crypt_supported == 1) { - eval { - $raw = $this->{cipher}->decrypt(decode_base64($crypted)); - }; - return $raw; - } - else { - return $crypted; - } -} - - -sub _store { - my ($this, $data) = @_; - open N, ">$this->{NOTEDB}" or die "Could not open db: $!\n"; - print N Data::Dumper->Dump([$data], [qw(*data)]); - close N; -} - -sub _retrieve { - my $this = shift; - if (-s $this->{NOTEDB}) { - if ($this->changed() || $this->{unread}) { - open N, "<$this->{NOTEDB}" or die "Could not open db: $!\n"; - my $content = join "", ; - close N; - my %data; - eval $content; # creates %data - $this->{unread} = 0; - $this->{data} = \%data; - return %data; - } - } - else { - return (); - } -} - - -1; # keep this! - -__END__ - -=head1 NAME - -NOTEDB::text - module lib for accessing a notedb from perl - -=head1 SYNOPSIS - - # include the module - use NOTEDB; - - # create a new NOTEDB object - $db = new NOTEDB("text", "/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 returns 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. This backend uses -a text file for storage and Storable for accessing the file. - -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 web interface to -note... - -=head1 USAGE - -please see the section SYNOPSIS, it says it all. - -=head1 AUTHOR - -Thomas Linden . - - -=cut diff --git a/lib/NOTEDB/general.pm b/lib/NOTEDB/general.pm deleted file mode 100644 index 74bf678..0000000 --- a/lib/NOTEDB/general.pm +++ /dev/null @@ -1,412 +0,0 @@ -# Perl module for note -# general database backend. see docu: perldoc NOTEDB::general -# using Config::General as backend. - -package NOTEDB::general; - -$NOTEDB::general::VERSION = "1.05"; - -use strict; -#use Data::Dumper; -use File::Spec; -use Config::General qw(ParseConfig SaveConfig SaveConfigString); -use MIME::Base64; -use FileHandle; -use NOTEDB; - -use Fcntl qw(LOCK_EX LOCK_UN); - -use Exporter (); -use vars qw(@ISA @EXPORT); -@ISA = qw(NOTEDB Exporter); - - - - - -sub new { - my($this, %param) = @_; - - my $class = ref($this) || $this; - my $self = {}; - bless($self,$class); - - $self->{dbname} = $param{dbname} || File::Spec->catfile($ENV{HOME}, ".notedb.txt"); - - if(! -e $param{dbname}) { - open(TT,">$param{dbname}") or die "Could not create $param{dbname}: $!\n"; - close (TT); - } - elsif(! -w $param{dbname}) { - print "$param{dbname} is not writable!\n"; - exit(1); - } - - $self->{mtime} = $self->get_stat(); - $self->{unread} = 1; - $self->{changed} = 1; - $self->{data} = {}; - $self->{LOCKFILE} = $param{dbname} . "~LOCK"; - - return $self; -} - - -sub DESTROY { - # clean the desk! -} - -sub version { - my $this = shift; - return $NOTEDB::general::VERSION; -} - -sub get_stat { - my ($this) = @_; - my $mtime = (stat($this->{dbname}))[9]; - return $mtime; -} - -sub changed { - my ($this) = @_; - my $current = $this->get_stat(); - if ($current > $this->{mtime}) { - $this->{mtime} = $current; - return $current; - } - else { - return 0; - } -} - -sub set_del_all { - my $this = shift; - unlink $this->{dbname}; - open(TT,">$this->{dbname}") or die "Could not create $this->{dbname}: $!\n"; - close (TT); -} - - -sub get_single { - my($this, $num) = @_; - my($address, $note, $date, $n, $t, $buffer, ); - - my %data = $this->get_all(); - - return ($data{$num}->{note}, $data{$num}->{date}); -} - - -sub get_all { - my $this = shift; - my($num, $note, $date, %res); - - if ($this->unchanged) { - return %{$this->{cache}}; - } - - my %data = $this->_retrieve(); - - foreach my $num (keys %data) { - $res{$num}->{note} = $this->ude($data{$num}->{note}); - $res{$num}->{date} = $this->ude($data{$num}->{date}); - } - - $this->cache(%res); - return %res; -} - -sub import_data { - my ($this, $data) = @_; - my %res = $this->_retrieve(); - my $pos = (scalar keys %res) + 1; - foreach my $num (keys %{$data}) { - $res{$pos}->{note} = $this->uen($data->{$num}->{note}); - $res{$pos}->{date} = $this->uen($data->{$num}->{date}); - $pos++; - } - $this->_store(\%res); -} - -sub get_nextnum { - my $this = shift; - my($num, $te, $me, $buffer); - - if ($this->unchanged) { - $num = 1; - foreach (keys %{$this->{cache}}) { - $num++; - } - return $num; - } - - my %data = $this->get_all(); - my @numbers = sort { $a <=> $b } keys %data; - $num = pop @numbers; - $num++; - - return $num; -} - -sub get_search { - my($this, $searchstring) = @_; - my($buffer, $num, $note, $date, %res, $t, $n, $match); - - my $regex = $this->generate_search($searchstring); - eval $regex; - if ($@) { - print "invalid expression: \"$searchstring\"!\n"; - return; - } - $match = 0; - - if ($this->unchanged) { - foreach my $num (keys %{$this->{cache}}) { - $_ = $this->{cache}{$num}->{note}; - eval $regex; - if ($match) { - $res{$num}->{note} = $this->{cache}{$num}->{note}; - $res{$num}->{date} = $this->{cache}{$num}->{date} - } - $match = 0; - } - return %res; - } - - my %data = $this->get_all(); - - foreach my $num(sort keys %data) { - $_ = $data{$num}->{note}; - eval $regex; - if($match) - { - $res{$num}->{note} = $data{$num}->{note}; - $res{$num}->{date} = $data{$num}->{data}; - } - $match = 0; - } - - return %res; -} - - - - -sub set_edit { - my($this, $num, $note, $date) = @_; - - my %data = $this->_retrieve(); - - $data{$num} = { - note => $this->uen($note), - date => $this->uen($date) - }; - - $this->_store(\%data); - - $this->changed; -} - - -sub set_new { - my($this, $num, $note, $date) = @_; - $this->set_edit($num, $note, $date); -} - - -sub set_del { - my($this, $num) = @_; - my(%data, $note, $date, $T, $setnum, $buffer, $n, $N, $t); - - $setnum = 1; - - %data = $this->_retrieve(); - return "ERROR" if (! exists $data{$num}); - - delete $data{$num}; - - $this->_store(\%data); - - $this->changed; - - return; -} - -sub set_recountnums { - my($this) = @_; - my(%orig, %data, $note, $date, $T, $setnum, $buffer, $n, $N, $t); - - $setnum = 1; - %orig = $this->_retrieve(); - - foreach $N (sort {$a <=> $b} keys %orig) { - $data{$setnum} = { - note => $orig{$N}->{note}, - date => $orig{$N}->{date} - }; - $setnum++; - } - - $this->_store(\%data); - - $this->changed; - - return; -} - -sub uen { - my ($this, $raw) = @_; - my($crypted); - if($NOTEDB::crypt_supported == 1) { - eval { - $crypted = $this->{cipher}->encrypt($raw); - }; - print $@; - } - else { - $crypted = $raw; - } - my $coded = encode_base64($crypted); - chomp $coded; - return $coded; -} - -sub ude { - my ($this, $crypted) = @_; - my($raw); - if($NOTEDB::crypt_supported == 1) { - eval { - $raw = $this->{cipher}->decrypt(decode_base64($crypted)); - }; - } - else { - $raw = decode_base64($crypted) - } - return $raw; -} - - - -sub _store { - my ($this, $data) = @_; - open NOTE, ">$this->{dbname}" or die "could not open $this->{dbname}: $!\n"; - flock NOTE, LOCK_EX; - - if (%{$data}) { - my $content = SaveConfigString($data) or die "could not serialize data: $!\n"; - print NOTE $content; - } - else { - print NOTE ""; - } - - flock NOTE, LOCK_UN; - close NOTE; - - # finally re-read the db, so that we always have the latest data - $this->_retrieve(); -} - -sub _retrieve { - my ($this) = @_; - my $file = $this->{dbname}; - if (-s $file) { - if ($this->{changed} || $this->{unread}) { - my $fh = new FileHandle "<$this->{dbname}" or die "could not open $this->{dbname}\n"; - flock $fh, LOCK_EX; - - my %data = ParseConfig(-ConfigFile => $fh) or die "could not read to database: $!\n"; - - flock $fh, LOCK_UN; - $fh->close(); - - $this->{unread} = 0; - $this->{data} = \%data; - return %data; - } - else { - return %{$this->{data}}; - } - } - else { - return (); - } -} - - -1; # keep this! - -__END__ - -=head1 NAME - -NOTEDB::general - module lib for accessing a notedb from perl - -=head1 SYNOPSIS - - # include the module - use NOTEDB; - - # create a new NOTEDB object - $db = new NOTEDB("text", "/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 returns 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. This backend uses -a text file for storage and Config::General for accessing the file. - -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 web interface to -note... - -=head1 USAGE - -please see the section SYNOPSIS, it says it all. - -=head1 AUTHOR - -Thomas Linden . - - -=cut diff --git a/lib/NOTEDB/mysql.pm b/lib/NOTEDB/mysql.pm deleted file mode 100644 index f571838..0000000 --- a/lib/NOTEDB/mysql.pm +++ /dev/null @@ -1,425 +0,0 @@ -# -# Perl module for note -# mysql database backend. see docu: perldoc NOTEDB::mysql -# - - -package NOTEDB::mysql; - -$NOTEDB::mysql::VERSION = "1.51"; - -use DBI; -use strict; -#use Data::Dumper; -use NOTEDB; - -use Exporter (); -use vars qw(@ISA @EXPORT); -@ISA = qw(NOTEDB Exporter); - - - - -sub new { - my($this, %param) = @_; - - my $class = ref($this) || $this; - my $self = {}; - bless($self,$class); - - my $dbname = $param{dbname} || "note"; - my $dbhost = $param{dbhost} || "localhost"; - my $dbuser = $param{dbuser} || ""; - my $dbpasswd = $param{dbpasswd} || ""; - my $dbport = $param{dbport} || ""; - my $fnum = "number"; - my $fnote = "note"; - my $fdate = "date"; - my $ftopic = "topic"; - - my $database; - if ($dbport) { - $database = "DBI:mysql:$dbname;host=$dbhost:$dbport"; - } - else { - $database = "DBI:mysql:$dbname;host=$dbhost"; - } - - $self->{table} = "note"; - - $self->{sql_getsingle} = "SELECT $fnote,$fdate,$ftopic FROM $self->{table} WHERE $fnum = ?"; - $self->{sql_all} = "SELECT $fnum,$fnote,$fdate,$ftopic FROM $self->{table}"; - $self->{sql_nextnum} = "SELECT max($fnum) FROM $self->{table}"; - $self->{sql_incrnum} = "SELECT $fnum FROM $self->{table} ORDER BY $fnum"; - $self->{sql_setnum} = "UPDATE $self->{table} SET $fnum = ? WHERE $fnum = ?"; - $self->{sql_edit} = "UPDATE $self->{table} SET $fnote = ?, $fdate = ?, $ftopic = ? WHERE $fnum = ?"; - $self->{sql_insertnew} = "INSERT INTO $self->{table} VALUES (?, ?, ?, ?)"; - $self->{sql_del} = "DELETE FROM $self->{table} WHERE $fnum = ?"; - $self->{sql_del_all} = "DELETE FROM $self->{table}"; - - $self->{DB} = DBI->connect($database, $dbuser, $dbpasswd) or die DBI->errstr(); - - return $self; -} - - -sub DESTROY -{ - # clean the desk! - my $this = shift; - $this->{DB}->disconnect; -} - - -sub lock { - my($this) = @_; - # LOCK the database! - my $lock = $this->{DB}->prepare("LOCK TABLES $this->{table} WRITE") - || die $this->{DB}->errstr(); - $lock->execute() || die $this->{DB}->errstr(); -} - - -sub unlock { - my($this) = @_; - my $unlock = $this->{DB}->prepare("UNLOCK TABLES") || die $this->{DB}->errstr; - $unlock->execute() || die $this->{DB}->errstr(); -} - - -sub version { - my $this = shift; - return $this->{version}; -} - - -sub get_single { - my($this, $num) = @_; - - my($note, $date, $topic); - my $statement = $this->{DB}->prepare($this->{sql_getsingle}) || die $this->{DB}->errstr(); - - $statement->execute($num) || die $this->{DB}->errstr(); - $statement->bind_columns(undef, \($note, $date, $topic)) || die $this->{DB}->errstr(); - - while($statement->fetch) { - $note = $this->ude($note); - if ($topic) { - $note = "$topic\n" . $note; - } - return $note, $this->ude($date); - } -} - - -sub get_all -{ - my $this = shift; - my($num, $note, $date, %res, $topic); - - if ($this->unchanged) { - return %{$this->{cache}}; - } - - my $statement = $this->{DB}->prepare($this->{sql_all}) or die $this->{DB}->errstr(); - - $statement->execute or die $this->{DB}->errstr(); - $statement->bind_columns(undef, \($num, $note, $date, $topic)) or die $this->{DB}->errstr(); - - while($statement->fetch) { - $res{$num}->{'note'} = $this->ude($note); - $res{$num}->{'date'} = $this->ude($date); - if ($topic) { - $res{$num}->{'note'} = "$topic\n" . $res{$num}->{'note'}; - } - } - - $this->cache(%res); - return %res; -} - - -sub get_nextnum -{ - my $this = shift; - my($num); - if ($this->unchanged) { - $num = 1; - foreach (keys %{$this->{cache}}) { - $num++; - } - return $num; - } - - my $statement = $this->{DB}->prepare($this->{sql_nextnum}) || die $this->{DB}->errstr(); - - $statement->execute || die $this->{DB}->errstr(); - $statement->bind_columns(undef, \($num)) || die $this->{DB}->errstr(); - - while($statement->fetch) { - return $num+1; - } -} - -sub get_search -{ - my($this, $searchstring) = @_; - my($num, $note, $date, %res, $match, $use_cache, $topic); - - my $regex = $this->generate_search($searchstring); - eval $regex; - if ($@) { - print "invalid expression: \"$searchstring\"!\n"; - return; - } - $match = 0; - - if ($this->unchanged) { - foreach my $num (keys %{$this->{cache}}) { - $_ = $this->{cache}{$num}->{note}; - eval $regex; - if ($match) { - $res{$num}->{note} = $this->{cache}{$num}->{note}; - $res{$num}->{date} = $this->{cache}{$num}->{date} - } - $match = 0; - } - return %res; - } - - my $statement = $this->{DB}->prepare($this->{sql_all}) or die $this->{DB}->errstr(); - - $statement->execute or die $this->{DB}->errstr(); - $statement->bind_columns(undef, \($num, $note, $date, $topic)) or die $this->{DB}->errstr(); - - while($statement->fetch) { - $note = $this->ude($note); - $date = $this->ude($date); - if ($topic) { - $note = "$topic\n" . $note; - } - $_ = $note; - eval $regex; - if($match) { - $res{$num}->{'note'} = $note; - $res{$num}->{'date'} = $date; - } - $match = 0; - } - return %res; -} - - - - -sub set_edit -{ - my($this, $num, $note, $date) = @_; - - $this->lock; - my $statement = $this->{DB}->prepare($this->{sql_edit}) or die $this->{DB}->errstr(); - $note =~ s/'/\'/g; - $note =~ s/\\/\\\\/g; - $statement->execute($this->uen($note), $this->uen($date), $num) - or die $this->{DB}->errstr(); - $this->unlock; - $this->changed; -} - - -sub set_new -{ - my($this, $num, $note, $date) = @_; - $this->lock; - my $statement = $this->{DB}->prepare($this->{sql_insertnew}) || die $this->{DB}->errstr(); - - my ($topic, $note) = $this->get_topic($note); - - $note =~ s/'/\'/g; - $note =~ s/\\/\\\\/g; - $topic =~ s/\\/\\\\/g; - $statement->execute($num, $this->uen($note), $this->uen($date), $topic) || die $this->{DB}->errstr(); - $this->unlock; - $this->changed; -} - - -sub set_del -{ - my($this, $num) = @_; - my($note, $date, $T); - - $this->lock; - ($note, $date) = $this->get_single($num); - - return "ERROR" if ($date !~ /^\d/); - - # delete record! - my $statement = $this->{DB}->prepare($this->{sql_del}) || die $this->{DB}->errstr(); - $statement->execute($num) || die $this->{DB}->errstr(); - $this->unlock; - $this->changed; - return; -} - - -sub set_del_all -{ - my($this) = @_; - $this->lock; - my $statement = $this->{DB}->prepare($this->{sql_del_all}) || die $this->{DB}->errstr(); - $statement->execute() || die $this->{DB}->errstr(); - $this->unlock; - $this->changed; - return; -} - -sub set_recountnums { - my $this = shift; - - $this->lock; - - my(@count, $i, $num, $setnum, $pos); - $setnum = 1; - $pos=0; $i=0; @count = (); - - my $statement = $this->{DB}->prepare($this->{sql_incrnum}) || die $this->{DB}->errstr(); - $statement->execute || die $this->{DB}->errstr(); - $statement->bind_columns(undef, \($num)) || die $this->{DB}->errstr(); - # store real id's in an array! - while($statement->fetch) { - $count[$i] = $num; - $i++; - } - # now recount them! - my $sub_statement = $this->{DB}->prepare($this->{sql_setnum}) || die $this->{DB}->errstr(); - for($pos=0;$pos<$i;$pos++) { - $setnum = $pos +1; - $sub_statement->execute($setnum,$count[$pos]) || die $this->{DB}->errstr(); - } - $this->unlock; - $this->changed; -} - -sub import_data { - my ($this, $data) = @_; - foreach my $num (keys %{$data}) { - my $pos = $this->get_nextnum(); - $this->set_new($pos, $data->{$num}->{note}, $data->{$num}->{date}); - } -} - -sub uen -{ - my $this = shift; - my($T); - if($NOTEDB::crypt_supported == 1) { - eval { - $T = pack("u", $this->{cipher}->encrypt($_[0])); - }; - } - else { - $T = $_[0]; - } - chomp $T; - return $T; -} - -sub ude -{ - my $this = shift; - my($T); - if($NOTEDB::crypt_supported == 1) { - eval { - $T = $this->{cipher}->decrypt(unpack("u",$_[0])) - }; - return $T; - } - else { - return $_[0]; - } -} - -sub get_topic { - my ($this, $data) = @_; - if ($data =~ /^\//) { - my($topic, $note) = split /\n/, $data, 2; - return ($topic, $note); - } - else { - return ("", $data); - } -} - -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 returns hash like the one from get_search above - - # get the next noteid available - $next_num = $db->get_nextnum(); - - # recount all noteids starting by 1 (useful 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 web interface to -note... - -=head1 USAGE - -please see the section SYNOPSIS, it says it all. - -=head1 AUTHOR - -Thomas Linden . - - - -=cut diff --git a/lib/NOTEDB/pwsafe3.pm b/lib/NOTEDB/pwsafe3.pm deleted file mode 100644 index 013c798..0000000 --- a/lib/NOTEDB/pwsafe3.pm +++ /dev/null @@ -1,612 +0,0 @@ -# Perl module for note -# pwsafe3 backend. see docu: perldoc NOTEDB::pwsafe3 - -package NOTEDB::pwsafe3; - -$NOTEDB::pwsafe3::VERSION = "1.09"; -use strict; -use Data::Dumper; -use Time::Local; -use Crypt::PWSafe3; - -use NOTEDB; - -use Fcntl qw(LOCK_EX LOCK_UN); - -use Exporter (); -use vars qw(@ISA @EXPORT); -@ISA = qw(NOTEDB Exporter); - - - - - -sub new { - my($this, %param) = @_; - - my $class = ref($this) || $this; - my $self = {}; - bless($self,$class); - - $self->{dbname} = $param{dbname} || File::Spec->catfile($ENV{HOME}, ".notedb.psafe3"); - - $self->{mtime} = $self->get_stat(); - $self->{unread} = 1; - $self->{data} = {}; - $self->{LOCKFILE} = $param{dbname} . "~LOCK"; - $self->{keepkey} = 0; - - return $self; -} - - -sub DESTROY { - # clean the desk! -} - -sub version { - my $this = shift; - return $NOTEDB::pwsafe3::VERSION; -} - -sub get_stat { - my ($this) = @_; - if(-e $this->{dbname}) { - return (stat($this->{dbname}))[9]; - } - else { - return time; - } -} - -sub filechanged { - my ($this) = @_; - my $current = $this->get_stat(); - - if ($current > $this->{mtime}) { - $this->{mtime} = $current; - return $current; - } - else { - return 0; - } -} - -sub set_del_all { - my $this = shift; - unlink $this->{dbname}; - open(TT,">$this->{dbname}") or die "Could not create $this->{dbname}: $!\n"; - close (TT); -} - - -sub get_single { - my($this, $num) = @_; - my($address, $note, $date, $n, $t, $buffer, ); - - my %data = $this->get_all(); - - return ($data{$num}->{note}, $data{$num}->{date}); -} - - -sub get_all { - my $this = shift; - my($num, $note, $date, %res); - if ($this->unchanged) { - return %{$this->{cache}}; - } - - my %data = $this->_retrieve(); - - foreach my $num (keys %data) { - ($res{$num}->{date}, $res{$num}->{note}) = $this->_pwsafe3tonote($data{$num}->{note}); - } - - $this->cache(%res); - return %res; -} - -sub import_data { - my ($this, $data) = @_; - - my $fh; - - if (-s $this->{dbname}) { - $fh = new FileHandle "<$this->{dbname}" or die "could not open $this->{dbname}\n"; - flock $fh, LOCK_EX; - } - - my $key = $this->_getpass(); - - eval { - my $vault = new Crypt::PWSafe3(password => $key, file => $this->{dbname}); - - foreach my $num (keys %{$data}) { - my $checksum = $this->get_nextnum(); - my %record = $this->_notetopwsafe3($checksum, $data->{$num}->{note}, $data->{$num}->{date}); - - my $rec = new Crypt::PWSafe3::Record(); - $rec->uuid($record{uuid}); - $vault->addrecord($rec); - $vault->modifyrecord($record{uuid}, %record); - } - - $vault->save(); - }; - if ($@) { - print "Exception caught:\n$@\n"; - exit 1; - } - - eval { - flock $fh, LOCK_UN; - $fh->close(); - }; - - $this->{keepkey} = 0; - $this->{key} = 0; -} - -sub get_nextnum { - my $this = shift; - my($num, $te, $me, $buffer); - - my $ug = new Data::UUID; - - $this->{nextuuid} = unpack('H*', $ug->create()); - $num = $this->_uuid( $this->{nextuuid} ); - - return $num; -} - -sub get_search { - my($this, $searchstring) = @_; - my($buffer, $num, $note, $date, %res, $t, $n, $match); - - my $regex = $this->generate_search($searchstring); - eval $regex; - if ($@) { - print "invalid expression: \"$searchstring\"!\n"; - return; - } - $match = 0; - - if ($this->unchanged) { - foreach my $num (keys %{$this->{cache}}) { - $_ = $this->{cache}{$num}->{note}; - eval $regex; - if ($match) { - $res{$num}->{note} = $this->{cache}{$num}->{note}; - $res{$num}->{date} = $this->{cache}{$num}->{date} - } - $match = 0; - } - return %res; - } - - my %data = $this->get_all(); - - foreach my $num(sort keys %data) { - $_ = $data{$num}->{note}; - eval $regex; - if($match) - { - $res{$num}->{note} = $data{$num}->{note}; - $res{$num}->{date} = $data{$num}->{data}; - } - $match = 0; - } - - return %res; -} - - - - -sub set_edit { - my($this, $num, $note, $date) = @_; - - my %data = $this->_retrieve(); - - my %record = $this->_notetopwsafe3($num, $note, $date); - - if (exists $data{$num}) { - $data{$num}->{note} = \%record; - $this->_store(\%record); - } - else { - %record = $this->_store(\%record, 1); - } - - $this->changed; -} - - -sub set_new { - my($this, $num, $note, $date) = @_; - $this->set_edit($num, $note, $date); -} - - -sub set_del { - my($this, $num) = @_; - - my $uuid = $this->_getuuid($num); - if(! $uuid) { - print "Note $num does not exist!\n"; - return; - } - - my $fh = new FileHandle "<$this->{dbname}" or die "could not open $this->{dbname}\n"; - flock $fh, LOCK_EX; - - my $key = $this->_getpass(); - eval { - my $vault = new Crypt::PWSafe3(password => $key, file => $this->{dbname}); - delete $vault->{record}->{$uuid}; - $vault->markmodified(); - $vault->save(); - }; - if ($@) { - print "Exception caught:\n$@\n"; - exit 1; - } - - eval { - flock $fh, LOCK_UN; - $fh->close(); - }; - - # finally re-read the db, so that we always have the latest data - $this->_retrieve($key); - $this->changed; - return; -} - -sub set_recountnums { - my($this) = @_; - # unsupported - return; -} - - -sub _store { - my ($this, $record, $create) = @_; - - my $fh; - - if (-s $this->{dbname}) { - $fh = new FileHandle "<$this->{dbname}" or die "could not open $this->{dbname}\n"; - flock $fh, LOCK_EX; - } - - my $key; - my $prompt = "pwsafe password: "; - - foreach my $try (1..5) { - if($try > 1) { - $prompt = "pwsafe password ($try retry): "; - } - $key = $this->_getpass($prompt); - eval { - my $vault = new Crypt::PWSafe3(password => $key, file => $this->{dbname}); - if ($create) { - my $rec = new Crypt::PWSafe3::Record(); - $rec->uuid($record->{uuid}); - $vault->addrecord($rec); - $vault->modifyrecord($record->{uuid}, %{$record}); - } - else { - $vault->modifyrecord($record->{uuid}, %{$record}); - } - $vault->save(); - }; - if ($@) { - if($@ =~ /wrong pass/i) { - $key = ''; - next; - } - else { - print "Exception caught:\n$@\n"; - exit 1; - } - } - else { - last; - } - } - eval { - flock $fh, LOCK_UN; - $fh->close(); - }; - - if(!$key) { - print STDERR "Giving up after 5 failed password attempts.\n"; - exit 1; - } - - # finally re-read the db, so that we always have the latest data - $this->_retrieve($key); -} - -sub _retrieve { - my ($this, $key) = @_; - my $file = $this->{dbname}; - if (-s $file) { - if ($this->filechanged() || $this->{unread}) { - my %data; - if (! $key) { - $key = $this->_getpass(); - } - eval { - my $vault = new Crypt::PWSafe3(password => $key, file => $this->{dbname}); - - my @records = $vault->getrecords(); - - foreach my $record (sort { $a->ctime <=> $b->ctime } @records) { - my $num = $this->_uuid( $record->uuid ); - my %entry = ( - uuid => $record->uuid, - title => $record->title, - user => $record->user, - passwd => $record->passwd, - notes => $record->notes, - group => $record->group, - lastmod=> $record->lastmod, - ctime => $record->ctime, - ); - $data{$num}->{note} = \%entry; - } - }; - if ($@) { - print "Exception caught:\n$@\n"; - exit 1; - } - - $this->{unread} = 0; - $this->{data} = \%data; - return %data; - } - else { - return %{$this->{data}}; - } - } - else { - return (); - } -} - -sub _pwsafe3tonote { - # - # convert pwsafe3 record to note record - my ($this, $record) = @_; - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($record->{ctime}); - my $date = sprintf("%02d.%02d.%04d %02d:%02d:%02d", $mday, $mon+1, $year+1900, $hour, $min, $sec); - chomp $date; - my $note; - if ($record->{group}) { - my $group = $record->{group}; - # convert group separator - $group =~ s#\.#/#g; - $note = "/$group/\n"; - } - - # pwsafe3 uses windows newlines, so convert ours - $record->{notes} =~ s/\r\n/\n/gs; - - # - # we do NOT add user and password fields here extra - # because if it is contained in the note, from were - # it was extracted initially, where it remains anyway - $note .= "$record->{title}\n$record->{notes}"; - - return ($date, $note); -} - -sub _notetopwsafe3 { - # - # convert note record to pwsafe3 record - # only used on create or save - # - # this one is the critical part, because the two - # record types are fundamentally incompatible. - # we parse our record and try to guess the values - # required for pwsafe3 - # - # expected input for note: - # /path/ -> group, optional - # any text -> title - # User: xxx -> user - # Password: xxx -> passwd - # anything else -> notes - # - # expected input for date: - # 23.02.2010 07:56:27 - my ($this, $num, $text, $date) = @_; - my ($group, $title, $user, $passwd, $notes, $ts, $content); - if ($text =~ /^\//) { - ($group, $title, $content) = split /\n/, $text, 3; - } - else { - ($title, $content) = split /\n/, $text, 2; - } - - if(!defined $content) { $content = ""; } - if(!defined $group) { $group = ""; } - - $user = $passwd = ''; - if ($content =~ /(user|username|login|account|benutzer):\s*(.+)/i) { - $user = $2; - } - if ($content =~ /(password|pass|passwd|kennwort|pw):\s*(.+)/i) { - $passwd = $2; - } - - # 1 2 3 4 5 6 - if ($date =~ /^(\d\d)\.(\d\d)\.(\d{4}) (\d\d):(\d\d):(\d\d)$/) { - # timelocal($sec,$min,$hour,$mday,$mon,$year); - $ts = timelocal($6, $5, $4, $1, $2-1, $3-1900); - } - - # make our topics pwsafe3 compatible groups - $group =~ s#^/##; - $group =~ s#/$##; - $group =~ s#/#.#g; - - # pwsafe3 uses windows newlines, so convert ours - $content =~ s/\n/\r\n/gs; - my %record = ( - uuid => $this->_getuuid($num), - user => $user, - passwd => $passwd, - group => $group, - title => $title, - ctime => $ts, - lastmod=> $ts, - notes => $content, - ); - return %record; -} - -sub _uuid { - my ($this, $uuid) = @_; - if (exists $this->{uuidnum}->{$uuid}) { - return $this->{uuidnum}->{$uuid}; - } - - my $max = 0; - - if (exists $this->{numuuid}) { - $max = (sort { $b <=> $a } keys %{$this->{numuuid}})[0]; - } - - my $num = $max + 1; - - $this->{uuidnum}->{$uuid} = $num; - $this->{numuuid}->{$num} = $uuid; - - return $num; -} - -sub _getuuid { - my ($this, $num) = @_; - return $this->{numuuid}->{$num}; -} - -sub _getpass { - # - # We're doing this here ourselfes - # because the note way of handling encryption - # doesn't work with pwsafe3, we can't hold a cipher - # structure in memory, because pwsafe3 handles this - # itself. - # Instead we ask for the password everytime we want - # to fetch data from the actual file OR want to write - # to it. To minimize reads, we use caching by default. - my($this, $prompt) = @_; - - if ($this->{key}) { - return $this->{key}; - } - else { - my $key; - print STDERR $prompt ? $prompt : "pwsafe password: "; - eval { - local($|) = 1; - local(*TTY); - open(TTY,"/dev/tty") or die "No /dev/tty!"; - system ("stty -echo ); - print STDERR "\r\n"; - system ("stty echo ; - } - if ($this->{keepkey}) { - $this->{key} = $key; - } - return $key; - } -} - -1; # keep this! - -__END__ - -=head1 NAME - -NOTEDB::pwsafe3 - module lib for accessing a notedb from perl - -=head1 SYNOPSIS - - # include the module - use NOTEDB; - - # create a new NOTEDB object - $db = new NOTEDB("text", "/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 returns 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. This backend uses -a text file for storage and Config::General for accessing the file. - -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 web interface to -note... - -=head1 USAGE - -please see the section SYNOPSIS, it says it all. - -=head1 AUTHOR - -Thomas Linden - - -=cut - - diff --git a/lib/NOTEDB/text.pm b/lib/NOTEDB/text.pm deleted file mode 100644 index 354bfb7..0000000 --- a/lib/NOTEDB/text.pm +++ /dev/null @@ -1,352 +0,0 @@ -# Perl module for note -# text database backend. see docu: perldoc NOTEDB::text -# using Storable as backend. - -package NOTEDB::text; - -$NOTEDB::text::VERSION = "1.05"; - -use strict; -#use Data::Dumper; -use File::Spec; -use Storable qw(lock_nstore lock_retrieve); -use MIME::Base64; - -use NOTEDB; - -use Fcntl qw(LOCK_EX LOCK_UN); - -use Exporter (); -use vars qw(@ISA @EXPORT); -@ISA = qw(NOTEDB Exporter); - - - - -sub new { - my($this, %param) = @_; - - my $class = ref($this) || $this; - my $self = {}; - bless($self,$class); - - $self->{NOTEDB} = $self->{dbname} = $param{dbname} || File::Spec->catfile($ENV{HOME}, ".notedb.storable"); - - if(! -e $param{dbname}) { - open(TT,">$param{dbname}") or die "Could not create $param{dbname}: $!\n"; - close (TT); - } - elsif(! -w $param{dbname}) { - print "$param{dbname} is not writable!\n"; - exit(1); - } - - $self->{LOCKFILE} = $param{dbname} . "~LOCK"; - $self->{mtime} = $self->get_stat(); - $self->{unread} = 1; - $self->{data} = {}; - - return $self; -} - - -sub DESTROY -{ - # clean the desk! -} - -sub version { - my $this = shift; - return $NOTEDB::text::VERSION; -} - -sub get_stat { - my ($this) = @_; - my $mtime = (stat($this->{dbname}))[9]; - return $mtime; -} - - -sub set_del_all { - my $this = shift; - unlink $this->{NOTEDB}; - open(TT,">$this->{NOTEDB}") or die "Could not create $this->{NOTEDB}: $!\n"; - close (TT); -} - - -sub get_single { - my($this, $num) = @_; - my($address, $note, $date, $n, $t, $buffer, ); - - my %data = $this->get_all(); - - return ($data{$num}->{note}, $data{$num}->{date}); -} - - -sub get_all { - my $this = shift; - my($num, $note, $date, %res); - - if ($this->unchanged) { - return %{$this->{cache}}; - } - - my %data = $this->_retrieve(); - - foreach my $num (keys %data) { - $res{$num}->{note} = $this->ude($data{$num}->{note}); - $res{$num}->{date} = $this->ude($data{$num}->{date}); - } - - $this->cache(%res); - return %res; -} - -sub import_data { - my ($this, $data) = @_; - my %res = $this->_retrieve(); - my $pos = (scalar keys %res) + 1; - foreach my $num (keys %{$data}) { - $res{$pos}->{note} = $this->uen($data->{$num}->{note}); - $res{$pos}->{date} = $this->uen($data->{$num}->{date}); - $pos++; - } - $this->_store(\%res); -} - -sub get_nextnum { - my $this = shift; - my($num, $te, $me, $buffer); - - if ($this->unchanged) { - my @numbers = sort { $a <=> $b } keys %{$this->{cache}}; - $num = pop @numbers; - $num++; - return $num; - } - - my %data = $this->get_all(); - my @numbers = sort { $a <=> $b } keys %data; - $num = pop @numbers; - $num++; - return $num; -} - -sub get_search { - my($this, $searchstring) = @_; - my($buffer, $num, $note, $date, %res, $t, $n, $match); - - my $regex = $this->generate_search($searchstring); - eval $regex; - if ($@) { - print "invalid expression: \"$searchstring\"!\n"; - return; - } - $match = 0; - - if ($this->unchanged) { - foreach my $num (keys %{$this->{cache}}) { - $_ = $this->{cache}{$num}->{note}; - eval $regex; - if ($match) { - $res{$num}->{note} = $this->{cache}{$num}->{note}; - $res{$num}->{date} = $this->{cache}{$num}->{date} - } - $match = 0; - } - return %res; - } - - my %data = $this->get_all(); - - foreach my $num(sort keys %data) { - $_ = $data{$num}->{note}; - eval $regex; - if($match) - { - $res{$num}->{note} = $data{$num}->{note}; - $res{$num}->{date} = $data{$num}->{data}; - } - $match = 0; - } - - return %res; -} - - - - -sub set_edit { - my($this, $num, $note, $date) = @_; - - my %data = $this->_retrieve(); - - $data{$num} = { - note => $this->uen($note), - date => $this->uen($date) - }; - - $this->_store(\%data); - - $this->changed; -} - - -sub set_new { - my($this, $num, $note, $date) = @_; - $this->set_edit($num, $note, $date); -} - - -sub set_del { - my($this, $num) = @_; - my(%data, $note, $date, $T, $setnum, $buffer, $n, $N, $t); - - $setnum = 1; - - %data = $this->_retrieve(); - return "ERROR" if (! exists $data{$num}); - - delete $data{$num}; - - $this->_store(\%data); - - $this->changed; - - return; -} - -sub set_recountnums { - # not required here - return; -} - -sub uen { - my ($this, $raw) = @_; - my($crypted); - if($NOTEDB::crypt_supported == 1) { - eval { - $crypted = $this->{cipher}->encrypt($raw); - }; - } - else { - $crypted = $raw; - } - my $coded = encode_base64($crypted); - return $coded; -} - -sub ude { - my ($this, $crypted) = @_; - my($raw); - if($NOTEDB::crypt_supported == 1) { - eval { - $raw = $this->{cipher}->decrypt(decode_base64($crypted)); - }; - } - else { - $raw = decode_base64($crypted) - } - return $raw; -} - - -sub _store { - my ($this, $data) = @_; - lock_nstore($data, $this->{NOTEDB}); -} - -sub _retrieve { - my $this = shift; - if (-s $this->{NOTEDB}) { - if ($this->changed() || $this->{unread}) { - my $data = lock_retrieve($this->{NOTEDB}); - $this->{unread} = 0; - $this->{data} = $data; - return %{$data}; - } - } - else { - return (); - } -} - - -1; # keep this! - -__END__ - -=head1 NAME - -NOTEDB::text - module lib for accessing a notedb from perl - -=head1 SYNOPSIS - - # include the module - use NOTEDB; - - # create a new NOTEDB object - $db = new NOTEDB("text", "/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 returns 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. This backend uses -a text file for storage and Storable for accessing the file. - -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 web interface to -note... - -=head1 USAGE - -please see the section SYNOPSIS, it says it all. - -=head1 AUTHOR - -Thomas Linden . - - -=cut diff --git a/mysql/README b/mysql/README deleted file mode 100644 index 4303606..0000000 --- a/mysql/README +++ /dev/null @@ -1,74 +0,0 @@ -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. - -Manual Installation -=================== - - 1) create a mysql database - mysqladmin create $db - - 2) add the required GRANT to a user and database - echo "GRANT ALL PRIVILEGES ON $db TO $user@localhost IDENTIFIED BY '$password'" | mysql mysql - - 3) create the schema: - mysql $db < sql diff --git a/mysql/install.sh b/mysql/install.sh deleted file mode 100755 index deb3d03..0000000 --- a/mysql/install.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/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 [ $(id -ru) != 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 deleted file mode 100644 index 966d1bf..0000000 --- a/mysql/permissions +++ /dev/null @@ -1,2 +0,0 @@ -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 deleted file mode 100644 index 3454f9b..0000000 --- a/mysql/sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE note ( - number int(10) DEFAULT '0' NOT NULL auto_increment, - topic text, - note text, - date text, - PRIMARY KEY (number) -); -# sample grant statement: -#GRANT ALL PRIVILEGES ON tom_note TO tom@localhost IDENTIFIED BY 'password'; diff --git a/note.pod b/note.pod deleted file mode 100644 index 30adbbf..0000000 --- a/note.pod +++ /dev/null @@ -1,547 +0,0 @@ -# -*-perl-*- - -=head1 NAME - -note - a perl script for maintaining notes. - - -=head1 SYNPOPSIS - -note [options] [ number [,number...]] - - -=head1 DESCRIPTION - -B is a small console program written in perl, which allows you -to manage notes similar to programs like "knotes" but from the command -line. Note can use different database-backends for notes-storage. It -ships with a DBI-based mysql-module(which can also be used for other -by DBI supported DBMS), another module, which uses a binary file for -storage and a DBM module. There are also two modules available which -uses a text file. Note supports since version 1.0.0 encryption(IDEA -or DES)! And last but not least the PWSafe3 format is also supported -by the pwsafe3 backend, which is encrypted by default. - - -=head1 OPTIONS - - -=over - -=item I<-c, --config file> - -Use another config file than the default ~/.noterc. - -=item I<-n, --new> - -Create a new note entry. - -=item I<-l, --list [topic]> - -Lists all existing notes. If no topic were specified, -it will display a list of all existing topics. -See the section I for details about topics. - -=item I<-L, --longlist [topic]> - -The same as I<-l> but prints also the timestamp of the notes. - - -=item I<-t, --topic> - -Prints a list of all topics as a tree. - - -=item I<-T, --longtopic> - -Prints the topic-tree with the notes under each topic. - - -=item I<-s, --search string> - -Searches for trough the notes database. See the section -I for details about the search engine. - - -=item I<-e, --edit number> - -Edit the note with the number using your default editor -or the one you specified in the config file. - - -=item I<-d, --delete number> - -Delete the note with the number . You can delete multiple notes -with one command. "1-4" deletes the notes 1,2,3,4. And "1,5,7" deletes -the specified ones. - - -=item I<-D, --Dump [file | -]> - -Dumps all notes to the textfile . If is a "-" it will -be printed out to standard output (STDOUT). - -=item I<-j --json> - -Use JSON format for exports created using -D. The importer determines -the format to be used automatically. - -=item I<-I, --Import file | -> - -Imports a previously dumped textfile into the -note database. Data will be appended by default. -You can also specify a dash I instead of a , -which causes note, silently to read in a dump from STDIN. - - -=item I<-o, --overwrite> - -Only suitable for use with --Import. Overwrites an -existing notedb. Use with care. - - -=item I<-r, --raw> - -Raw mode, output will not be formatted. Works not in interactive -mode, only on cmd-line for list and display. That means, no colors -will be used and no lines or titles. - - -=item I<-i, --interactive> - -Start note in interactive mode. See the section I -for details on this mode. - - -=item I<--encrypt cleartext> - -Encrypt the given clear text string. You would need that if you want to -store the mysql password not in cleartext in the config (if you are using -the mysql backend!). - - -=item I<-h, --help> - -Display this help screen. - - -=item I<-v, --version> - -Display the version number. - - -=item B<-> - -If you run note just with one dash: B, then it will read in a new -note from STDIN until EOF. This makes it possible to pipe text into a new note, i.e.: - - cat sometextfile | note - - - -=back - - - - -=head1 USAGE - -=head2 GENERAL USAGE - -If you don't know, how to run note, try "note -h" first. -It will tell you all available command line 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, otherwise 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 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- -structure. You can use the command "-t" in this case, which -will display a tree-view of your topic-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". - - - -=head2 SEARCHING - -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 occurrence of this string and tell you the number and first- -line it has. - -You can extend the searchstring using B, B ( and ) and -shell-like wildcards: - - $ note -s "moses AND lenin" - -or: - - $ note -s "(mike OR arnold) AND (jackson OR schwarzenegger)" - -If note finds a note, which first line is a topic, then it will -display it's second line. - -These rules apply for the interactive search too. - -You need to know, that note searches for the expression in every -note. In other words, "moses AND lenin" searches for an occurrence -of "moses" and "lenin" in ONE note. Or, if you are looking for -"mike OR daniel", then it searches for an occurrence of "mike" or -daniel" in ONE note. Thus a note with the text "mike oldfield" will -match that search. - - -=head2 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: - - B - -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. - -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! - - - - -=head2 INTERACTIVE MODE - -If you start note with the command line flag B<-i>, then it starts -with an interactive interface. -It will start with a listing under the default top-topic ("/"). -You can enter the name of a topic to change to that topic. This works -similar to a filesystem structure. The current topic will be -displayed on the top of the screen. - -The following commands are available: - -=over - -=item B - -This command lists all notes with a timestamp. If you specify a topic, it -will only list the notes under this topic. If you are under a certain subtopic, -then it will only display the notes under this topic. - -=item B - -This commands behaves similar to B but it does not display the timestamp. -You can achieve the same result by simply pressing enter at any time. - - -=item B - -You can create a new note by simply pressing B or B. You favorite -editor will be started and you can enter your note text. If you are already -under a topic then this new note will automatically go to this topic. -note adds an additional line to the top of the note with the topic. But -you can, of course, specify your own topic. - -Note will tell you which number it has assigned to the newly created note. - -=item B - -By entering B or B and a note-number you can edit an existing note -using your favorite editor. This way you can also move an existing note -from one topic to another one by editing the first line of the note. - - -=item B - -B or B deletes one or more existing note(s). It requires a note number -or a set of note numbers. 1-5 and 1,7,9 are possible values. -After one or more notes has been deleted note will recount all remaining notes. -Say if you delete 1 and 2, then 3 will become 1, 4 will become 5 and so forth. - - -=item B - -You can search for the occurrence of a text in your notes-database with the -command B or B. If you omit an expression note will ask you for one. - -If your search criteria matches on exactly one entry, note will display -that note entry instead of displaying its number. - -=item B - -This prints a tree-view of your topic-structure. B displays the tree with -notes, B displays just the topics without notes. - -=item B - -It is possible to change note's behavior at runtime. Specify the parameter -you'd like to modify followed by equalsign and the new value. Use with -care! However, database related parameters cannot be changed at runtime. -Entering just "c" without parameters displays the customizable variables. - -=item B - -Change the actual topic under which you are. This works identical like just -entering the topic but it has some advantages. You can enter B if -you want to go one level up in the topic-structure. And you can enter B -to go to the top of the structure. You can always leave out the 'cd' keyword too. - -Additional it is possible to enter a note-number instead of a topic name. -For this feature to be active you need to set the config option B -to B<1> or B. If you use a number and the note with this number is -under a certain topic then you will "cd" to this topic. This allows you -to do kind of jumps over multiple levels of topics. - -If is possible to abbreviate a topic. This works only if the abbreviation -matches on one single topic. If it matches more than one topic then the -available ones will be suggested. - - -=item B - -Display a short help screen. - - -=item B - -Quit note. - -=back - - - - - -=head2 BACKUP - -You can also dump the contents of your note-database into a -ASCII-textfile(I<-D>). You can use this file later to import it into -your note-database(-I). This is useful, 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 which 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 this do?! Step by step: - -=over - -=item * - -B creates a note-database dump and prints it out -to standard output. - -=item * - -B<|> 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. - -=item * - -B imports a note-database dump from standard -input and overwrites an existing database. - -=back - -Before you use the B<-o> switch, I consider you to make a backup! - -=head3 BACKUP FILE FORMAT - -B: since version 1.3.8 note uses a new file format -for backups: YAML. The old format is only supported by the -B<-I> option to import old backups. New backups are always -created as YAML files. See L. - - - -=head2 FORMATING - -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 colorizing. 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 ends 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 "FormatText" 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}} - hidden: //word// - -The text will be formatted using the actually note-color. - -The hidden formatting will use blue foreground and blue background -to hide a string from the terminal, which is useful for passwords. - -If you set "FormatText" to I then the formatting can be -done this way instead: - - bold: *word* - underlined: _word_ - inverse: {word} - hidden: /word/ - -=head1 ENCRYPTION - -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 are 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 -every time it runs! It will *not* store this passphrase! -So, don't forget it! Be careful! - - - - -=head1 CONFIGURATION - -You can use a configuration file with note but it is not required. -Note will use default values if there is no config. - -The default config file is B<~/.noterc>. You may specify another -one with the command line flag I<--config>. - -Comments start with #, empty lines will be ignored. - -To turn on an option, set it to: B<1>, B or B. - -To turn off an option, set it to: B<0>, B or B. - -An option consists of an atribute-value pair separated -by minimum one space (more spaces and/or tabs are allowed) -and an optional equal sign in between. - -Variable names are case in-sensitive. - -For a detailed explanation of each possible parameter take a look -at the supplied sample configuration file in B. - - - - - -=head1 AUTHOR - -T.v.Dein - -=head1 VERSION - -1.4.0 - -=cut diff --git a/t/run.t b/t/run.t deleted file mode 100644 index 93d1687..0000000 --- a/t/run.t +++ /dev/null @@ -1,135 +0,0 @@ -# -*-perl-*- -#use Test::More tests => 8; -use Test::More qw(no_plan); -use Data::Dumper; - -my $expect = { - 1 => { - 'date' => '23.12.2000 10:33:02', - 'note' => 'any new text' - }, - 2 => { - 'date' => '03.02.2004 18:13:52', - 'note' => 'yet whatever you mean' - } - }; - - -BEGIN { use_ok "NOTEDB" }; -require_ok("NOTEDB"); -my $key = '01010101'; -my $alg = 'Rijndael'; - -foreach my $CR (1 .. 0) { - $NOTEDB::crypt_supported = $CR; - - SKIP: { - skip "no crypt", 1 if $CR; # FIXME: for some weird reason, crypto doesn't work with ::binary? - eval { require NOTEDB::binary; }; - skip "Fatal, skipping test for NOTEDB::binary", 1 if $@; - unlink "t/binary.out"; - my $db = new NOTEDB::binary(dbname => "t/binary.out"); - $db->use_crypt($key, $alg) if $CR; - ok(ref($db), "Database object loaded"); - &wrdb($db, "NOTEDB::binary"); - } - - SKIP: { - eval { require NOTEDB::general; }; - skip "Config::General not installed, skipping test for NOTEDB::general", 1 if $@; - unlink "t/general.out"; - my $db2 = NOTEDB::general->new(dbname => "t/general.out"); - $db2->use_crypt($key, $alg) if $CR; - ok(ref($db2), "Database object loaded"); - &wrdb($db2, "NOTEDB::general"); - } - - SKIP: { - eval { require NOTEDB::text; }; - skip "Storable not installed, skipping test for NOTEDB::text", 1 if $@; - unlink "t/test.out"; - my $db3 = NOTEDB::text->new(dbname => "t/text.out"); - $db3->use_crypt($key, $alg) if $CR; - ok(ref($db3), "Database object loaded"); - &wrdb($db3, "NOTEDB::text"); - } - - SKIP: { - eval { require NOTEDB::dumper; }; - skip "Data::Dumper not installed, skipping test for NOTEDB::dumper", 1 if $@; - unlink "t/dumper.out"; - my $db4 = NOTEDB::dumper->new(dbname => "t/dumper.out"); - $db4->use_crypt($key, $alg) if $CR; - ok(ref($db4), "Database object loaded"); - &wrdb($db4, "NOTEDB::dumper"); - } - - SKIP: { - eval { require NOTEDB::dbm; }; - skip "DB_File not installed, skipping test for NOTEDB::dbm", 1 if $@; - unlink "t/note.dbm"; - unlink "t/date.dbm"; - my $db5 = NOTEDB::dbm->new(dbname => "t"); - $db5->use_crypt($key, $alg) if $CR; - ok(ref($db5), "Database object loaded"); - &wrdb($db5, "NOTEDB::dbm"); - } -} - -SKIP: { - eval { require NOTEDB::pwsafe3; }; - skip "Crypt::PWSafe3 not installed, skipping test for NOTEDB::pwsafe3", 1 if $@; - unlink "t/pwsafe3.out"; - my $db6 = NOTEDB::pwsafe3->new(dbname => "t/pwsafe3.out"); - $db6->{key} = "01010101"; - ok(ref($db6), "Database object loaded"); - &wrdb3($db6, "NOTEDB::pwsafe3"); -} - -sub wrdb { - my ($db, $name) = @_; - is_deeply($db->{use_cache}, undef, "$name: Chache disabled"); - - $db->set_new(1, $expect->{1}->{note}, $expect->{1}->{date}); - my ($note, $date) = $db->get_single(1); - like($note, qr/any new text/, "$name: Retrieve newly written entry content"); - like($date, qr/^\d\d/, "$name: Retrieve newly written entry date"); - - $db->set_new(2, $expect->{2}->{note}, $expect->{2}->{date}); - - my $next = $db->get_nextnum(); - is_deeply($next, 3, "$name: Get next note id"); - - my %all = $db->get_all(); - is_deeply($expect, \%all, "$name: Get all notes hash") or diag(Dumper(\%all)); -} - -sub wrdb3 { - my ($db, $name) = @_; - is_deeply($db->{use_cache}, undef, "$name: Chache disabled"); - - my $ex3 = $expect; - my $n = $db->get_nextnum; - $db->set_new($n, $ex3->{1}->{note}, $ex3->{1}->{date}); - $ex3->{$n} = delete $ex3->{1}; - - my ($note, $date) = $db->get_single($n); - like($note, qr/any new text/, "$name: Retrieve newly written entry content"); - like($date, qr/^\d\d/, "$name: Retrieve newly written entry date"); - - $n = $db->get_nextnum; - $db->set_new($n, $ex3->{2}->{note}, $ex3->{2}->{date}); - $ex3->{$n} = delete $ex3->{2}; - - # hack db file mtime, since we're too fast here - $db->{mtime} = 0; - - my %all = $db->get_all(); - # hack %all to that it passes the next test - foreach my $n (keys %all) { - chomp $all{$n}->{note}; - } - - is_deeply($ex3, \%all, "$name: Get all notes hash") or diag(Dumper(\%all)); -} -