diff --git a/Changelog b/Changelog index 4544efa..fbed4c3 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,12 @@ +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 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a1598a5 --- /dev/null +++ b/Makefile @@ -0,0 +1,782 @@ +# This Makefile is for the NOTEDB extension to perl. +# +# It was generated automatically by MakeMaker version +# 6.17 (Revision: 1.133) from the contents of +# Makefile.PL. Don't edit this file, edit Makefile.PL instead. +# +# ANY CHANGES MADE HERE WILL BE LOST! +# +# MakeMaker ARGV: () +# +# MakeMaker Parameters: + +# EXE_FILES => [q[bin/note]] +# NAME => q[NOTEDB] +# VERSION_FROM => q[NOTEDB.pm] + +# --- MakeMaker post_initialize section: + + +# --- MakeMaker const_config section: + +# These definitions are from config.sh (via /usr/lib/perl/5.8/Config.pm) + +# They may have been overridden via Makefile.PL or on the command line +AR = ar +CC = cc +CCCDLFLAGS = -fPIC +CCDLFLAGS = -Wl,-E +DLEXT = so +DLSRC = dl_dlopen.xs +LD = cc +LDDLFLAGS = -shared -L/usr/local/lib +LDFLAGS = -L/usr/local/lib +LIBC = /lib/libc-2.3.2.so +LIB_EXT = .a +OBJ_EXT = .o +OSNAME = linux +OSVERS = 2.4.27-ti1211 +RANLIB = : +SITELIBEXP = /usr/local/share/perl/5.8.4 +SITEARCHEXP = /usr/local/lib/perl/5.8.4 +SO = so +EXE_EXT = +FULL_AR = /usr/bin/ar +VENDORARCHEXP = /usr/lib/perl5 +VENDORLIBEXP = /usr/share/perl5 + + +# --- MakeMaker constants section: +AR_STATIC_ARGS = cr +DIRFILESEP = / +NAME = NOTEDB +NAME_SYM = NOTEDB +VERSION = 1.31 +VERSION_MACRO = VERSION +VERSION_SYM = 1_31 +DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" +XS_VERSION = 1.31 +XS_VERSION_MACRO = XS_VERSION +XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" +INST_ARCHLIB = blib/arch +INST_SCRIPT = blib/script +INST_BIN = blib/bin +INST_LIB = blib/lib +INST_MAN1DIR = blib/man1 +INST_MAN3DIR = blib/man3 +MAN1EXT = 1p +MAN3EXT = 3pm +INSTALLDIRS = site +DESTDIR = +PREFIX = /usr +PERLPREFIX = $(PREFIX) +SITEPREFIX = $(PREFIX)/local +VENDORPREFIX = $(PREFIX) +INSTALLPRIVLIB = $(PERLPREFIX)/share/perl/5.8 +DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB) +INSTALLSITELIB = $(SITEPREFIX)/share/perl/5.8.4 +DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB) +INSTALLVENDORLIB = $(VENDORPREFIX)/share/perl5 +DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB) +INSTALLARCHLIB = $(PERLPREFIX)/lib/perl/5.8 +DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB) +INSTALLSITEARCH = $(SITEPREFIX)/lib/perl/5.8.4 +DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH) +INSTALLVENDORARCH = $(VENDORPREFIX)/lib/perl5 +DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH) +INSTALLBIN = $(PERLPREFIX)/bin +DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN) +INSTALLSITEBIN = $(SITEPREFIX)/bin +DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN) +INSTALLVENDORBIN = $(VENDORPREFIX)/bin +DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN) +INSTALLSCRIPT = $(PERLPREFIX)/bin +DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT) +INSTALLMAN1DIR = $(PERLPREFIX)/share/man/man1 +DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR) +INSTALLSITEMAN1DIR = $(SITEPREFIX)/man/man1 +DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR) +INSTALLVENDORMAN1DIR = $(VENDORPREFIX)/share/man/man1 +DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR) +INSTALLMAN3DIR = $(PERLPREFIX)/share/man/man3 +DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR) +INSTALLSITEMAN3DIR = $(SITEPREFIX)/man/man3 +DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR) +INSTALLVENDORMAN3DIR = $(VENDORPREFIX)/share/man/man3 +DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR) +PERL_LIB = /usr/share/perl/5.8 +PERL_ARCHLIB = /usr/lib/perl/5.8 +LIBPERL_A = libperl.a +FIRST_MAKEFILE = Makefile +MAKEFILE_OLD = $(FIRST_MAKEFILE).old +MAKE_APERL_FILE = $(FIRST_MAKEFILE).aperl +PERLMAINCC = $(CC) +PERL_INC = /usr/lib/perl/5.8/CORE +PERL = /usr/bin/perl +FULLPERL = /usr/bin/perl +ABSPERL = $(PERL) +PERLRUN = $(PERL) +FULLPERLRUN = $(FULLPERL) +ABSPERLRUN = $(ABSPERL) +PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +PERL_CORE = 0 +PERM_RW = 644 +PERM_RWX = 755 + +MAKEMAKER = /usr/share/perl/5.8/ExtUtils/MakeMaker.pm +MM_VERSION = 6.17 +MM_REVISION = 1.133 + +# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). +# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) +# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) +# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. +FULLEXT = NOTEDB +BASEEXT = NOTEDB +PARENT_NAME = +DLBASE = $(BASEEXT) +VERSION_FROM = NOTEDB.pm +OBJECT = +LDFROM = $(OBJECT) +LINKTYPE = dynamic + +# Handy lists of source code files: +XS_FILES = +C_FILES = +O_FILES = +H_FILES = +MAN1PODS = +MAN3PODS = NOTEDB/binary.pm \ + NOTEDB/dbm.pm \ + NOTEDB/dumper.pm \ + NOTEDB/general.pm \ + NOTEDB/mysql.pm \ + NOTEDB/text.pm \ + note.pod + +# Where is the Config information that we are using/depend on +CONFIGDEP = $(PERL_ARCHLIB)$(DIRFILESEP)Config.pm $(PERL_INC)$(DIRFILESEP)config.h + +# Where to build things +INST_LIBDIR = $(INST_LIB) +INST_ARCHLIBDIR = $(INST_ARCHLIB) + +INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) +INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) + +INST_STATIC = +INST_DYNAMIC = +INST_BOOT = + +# Extra linker info +EXPORT_LIST = +PERL_ARCHIVE = +PERL_ARCHIVE_AFTER = + + +TO_INST_PM = NOTEDB.pm \ + NOTEDB/README \ + NOTEDB/binary.pm \ + NOTEDB/dbm.pm \ + NOTEDB/dumper.pm \ + NOTEDB/general.pm \ + NOTEDB/mysql.pm \ + NOTEDB/text.pm \ + note.pod + +PM_TO_BLIB = NOTEDB/general.pm \ + $(INST_LIB)/NOTEDB/general.pm \ + NOTEDB/dbm.pm \ + $(INST_LIB)/NOTEDB/dbm.pm \ + NOTEDB/README \ + $(INST_LIB)/NOTEDB/README \ + NOTEDB.pm \ + $(INST_LIB)/NOTEDB.pm \ + NOTEDB/text.pm \ + $(INST_LIB)/NOTEDB/text.pm \ + NOTEDB/mysql.pm \ + $(INST_LIB)/NOTEDB/mysql.pm \ + NOTEDB/binary.pm \ + $(INST_LIB)/NOTEDB/binary.pm \ + NOTEDB/dumper.pm \ + $(INST_LIB)/NOTEDB/dumper.pm \ + note.pod \ + $(INST_LIB)/note.pod + + +# --- MakeMaker platform_constants section: +MM_Unix_VERSION = 1.42 +PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc + + +# --- MakeMaker tool_autosplit section: +# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto +AUTOSPLITFILE = $(PERLRUN) -e 'use AutoSplit; autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1)' + + + +# --- MakeMaker tool_xsubpp section: + + +# --- MakeMaker tools_other section: +SHELL = /bin/sh +CHMOD = chmod +CP = cp +MV = mv +NOOP = $(SHELL) -c true +NOECHO = @ +RM_F = rm -f +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 +MKPATH = $(PERLRUN) "-MExtUtils::Command" -e mkpath +EQUALIZE_TIMESTAMP = $(PERLRUN) "-MExtUtils::Command" -e eqtime +ECHO = echo +ECHO_N = echo -n +UNINST = 0 +VERBINST = 0 +MOD_INSTALL = $(PERLRUN) -MExtUtils::Install -e 'install({@ARGV}, '\''$(VERBINST)'\'', 0, '\''$(UNINST)'\'');' +DOC_INSTALL = $(PERLRUN) "-MExtUtils::Command::MM" -e perllocal_install +UNINSTALL = $(PERLRUN) "-MExtUtils::Command::MM" -e uninstall +WARN_IF_OLD_PACKLIST = $(PERLRUN) "-MExtUtils::Command::MM" -e warn_if_old_packlist + + +# --- MakeMaker makemakerdflt section: +makemakerdflt: all + $(NOECHO) $(NOOP) + + +# --- MakeMaker dist section: +TAR = tar +TARFLAGS = cvf +ZIP = zip +ZIPFLAGS = -r +COMPRESS = gzip --best +SUFFIX = .gz +SHAR = shar +PREOP = $(NOECHO) $(NOOP) +POSTOP = $(NOECHO) $(NOOP) +TO_UNIX = $(NOECHO) $(NOOP) +CI = ci -u +RCS_LABEL = rcs -Nv$(VERSION_SYM): -q +DIST_CP = best +DIST_DEFAULT = tardist +DISTNAME = NOTEDB +DISTVNAME = NOTEDB-1.31 + + +# --- MakeMaker macro section: + + +# --- MakeMaker depend section: + + +# --- MakeMaker cflags section: + + +# --- MakeMaker const_loadlibs section: + + +# --- MakeMaker const_cccmd section: + + +# --- MakeMaker post_constants section: + + +# --- MakeMaker pasthru section: + +PASTHRU = LIB="$(LIB)"\ + LIBPERL_A="$(LIBPERL_A)"\ + LINKTYPE="$(LINKTYPE)"\ + PREFIX="$(PREFIX)"\ + OPTIMIZE="$(OPTIMIZE)"\ + PASTHRU_DEFINE="$(PASTHRU_DEFINE)"\ + PASTHRU_INC="$(PASTHRU_INC)" + + +# --- MakeMaker special_targets section: +.SUFFIXES: .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT) + +.PHONY: all config static dynamic test linkext manifest + + + +# --- MakeMaker c_o section: + + +# --- MakeMaker xs_c section: + + +# --- MakeMaker xs_o section: + + +# --- MakeMaker top_targets section: +all :: pure_all manifypods + $(NOECHO) $(NOOP) + + +pure_all :: config pm_to_blib subdirs linkext + $(NOECHO) $(NOOP) + +subdirs :: $(MYEXTLIB) + $(NOECHO) $(NOOP) + +config :: $(FIRST_MAKEFILE) $(INST_LIBDIR)$(DIRFILESEP).exists + $(NOECHO) $(NOOP) + +config :: $(INST_ARCHAUTODIR)$(DIRFILESEP).exists + $(NOECHO) $(NOOP) + +config :: $(INST_AUTODIR)$(DIRFILESEP).exists + $(NOECHO) $(NOOP) + +$(INST_AUTODIR)/.exists :: /usr/lib/perl/5.8/CORE/perl.h + $(NOECHO) $(MKPATH) $(INST_AUTODIR) + $(NOECHO) $(EQUALIZE_TIMESTAMP) /usr/lib/perl/5.8/CORE/perl.h $(INST_AUTODIR)/.exists + + -$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_AUTODIR) + +$(INST_LIBDIR)/.exists :: /usr/lib/perl/5.8/CORE/perl.h + $(NOECHO) $(MKPATH) $(INST_LIBDIR) + $(NOECHO) $(EQUALIZE_TIMESTAMP) /usr/lib/perl/5.8/CORE/perl.h $(INST_LIBDIR)/.exists + + -$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_LIBDIR) + +$(INST_ARCHAUTODIR)/.exists :: /usr/lib/perl/5.8/CORE/perl.h + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) $(EQUALIZE_TIMESTAMP) /usr/lib/perl/5.8/CORE/perl.h $(INST_ARCHAUTODIR)/.exists + + -$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_ARCHAUTODIR) + +config :: $(INST_MAN3DIR)$(DIRFILESEP).exists + $(NOECHO) $(NOOP) + + +$(INST_MAN3DIR)/.exists :: /usr/lib/perl/5.8/CORE/perl.h + $(NOECHO) $(MKPATH) $(INST_MAN3DIR) + $(NOECHO) $(EQUALIZE_TIMESTAMP) /usr/lib/perl/5.8/CORE/perl.h $(INST_MAN3DIR)/.exists + + -$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_MAN3DIR) + +help: + perldoc ExtUtils::MakeMaker + + +# --- MakeMaker linkext section: + +linkext :: $(LINKTYPE) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dlsyms section: + + +# --- MakeMaker dynamic section: + +dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dynamic_bs section: + +BOOTSTRAP = + + +# --- MakeMaker dynamic_lib section: + + +# --- MakeMaker static section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make static" +static :: $(FIRST_MAKEFILE) $(INST_STATIC) + $(NOECHO) $(NOOP) + + +# --- MakeMaker static_lib section: + + +# --- MakeMaker manifypods section: + +POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--" +POD2MAN = $(POD2MAN_EXE) + + +manifypods : pure_all \ + NOTEDB/general.pm \ + NOTEDB/text.pm \ + NOTEDB/dbm.pm \ + NOTEDB/mysql.pm \ + NOTEDB/binary.pm \ + NOTEDB/dumper.pm \ + note.pod \ + NOTEDB/general.pm \ + NOTEDB/text.pm \ + NOTEDB/dbm.pm \ + NOTEDB/mysql.pm \ + NOTEDB/binary.pm \ + NOTEDB/dumper.pm \ + note.pod + $(NOECHO) $(POD2MAN) --section=$(MAN3EXT) --perm_rw=$(PERM_RW)\ + NOTEDB/general.pm $(INST_MAN3DIR)/NOTEDB::general.$(MAN3EXT) \ + NOTEDB/text.pm $(INST_MAN3DIR)/NOTEDB::text.$(MAN3EXT) \ + NOTEDB/dbm.pm $(INST_MAN3DIR)/NOTEDB::dbm.$(MAN3EXT) \ + NOTEDB/mysql.pm $(INST_MAN3DIR)/NOTEDB::mysql.$(MAN3EXT) \ + NOTEDB/binary.pm $(INST_MAN3DIR)/NOTEDB::binary.$(MAN3EXT) \ + NOTEDB/dumper.pm $(INST_MAN3DIR)/NOTEDB::dumper.$(MAN3EXT) \ + note.pod $(INST_MAN3DIR)/note.$(MAN3EXT) + + + + +# --- MakeMaker processPL section: + + +# --- MakeMaker installbin section: + +$(INST_SCRIPT)/.exists :: /usr/lib/perl/5.8/CORE/perl.h + $(NOECHO) $(MKPATH) $(INST_SCRIPT) + $(NOECHO) $(EQUALIZE_TIMESTAMP) /usr/lib/perl/5.8/CORE/perl.h $(INST_SCRIPT)/.exists + + -$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_SCRIPT) + +EXE_FILES = bin/note + +FIXIN = $(PERLRUN) "-MExtUtils::MY" -e "MY->fixin(shift)" + +pure_all :: $(INST_SCRIPT)/note + $(NOECHO) $(NOOP) + +realclean :: + $(RM_F) $(INST_SCRIPT)/note + +$(INST_SCRIPT)/note: bin/note $(FIRST_MAKEFILE) $(INST_SCRIPT)/.exists + $(NOECHO) $(RM_F) $(INST_SCRIPT)/note + $(CP) bin/note $(INST_SCRIPT)/note + $(FIXIN) $(INST_SCRIPT)/note + -$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_SCRIPT)/note + + +# --- MakeMaker subdirs section: + +# none + +# --- MakeMaker clean_subdirs section: +clean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker clean section: + +# Delete temporary files but do not touch installed files. We don't delete +# the Makefile here so a later make realclean still has a makefile to use. + +clean :: clean_subdirs + -$(RM_RF) ./blib $(MAKE_APERL_FILE) $(INST_ARCHAUTODIR)/extralibs.all $(INST_ARCHAUTODIR)/extralibs.ld perlmain.c tmon.out mon.out so_locations pm_to_blib *$(OBJ_EXT) *$(LIB_EXT) perl.exe perl perl$(EXE_EXT) $(BOOTSTRAP) $(BASEEXT).bso $(BASEEXT).def lib$(BASEEXT).def $(BASEEXT).exp $(BASEEXT).x core core.*perl.*.? *perl.core core.[0-9] core.[0-9][0-9] core.[0-9][0-9][0-9] core.[0-9][0-9][0-9][0-9] core.[0-9][0-9][0-9][0-9][0-9] + -$(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL) + + +# --- MakeMaker realclean_subdirs section: +realclean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker realclean section: + +# Delete temporary files (via clean) and also delete installed files +realclean purge :: clean realclean_subdirs + $(RM_RF) $(INST_AUTODIR) $(INST_ARCHAUTODIR) + $(RM_RF) $(DISTVNAME) + $(RM_F) $(INST_LIB)/NOTEDB/dumper.pm $(INST_LIB)/NOTEDB/mysql.pm $(INST_LIB)/NOTEDB/binary.pm $(MAKEFILE_OLD) $(INST_LIB)/NOTEDB/text.pm $(INST_LIB)/NOTEDB/general.pm $(INST_LIB)/NOTEDB.pm + $(RM_F) $(INST_LIB)/note.pod $(INST_LIB)/NOTEDB/dbm.pm $(INST_LIB)/NOTEDB/README $(FIRST_MAKEFILE) + + +# --- MakeMaker metafile section: +metafile : + $(NOECHO) $(ECHO) '# http://module-build.sourceforge.net/META-spec.html' > META.yml + $(NOECHO) $(ECHO) '#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#' >> META.yml + $(NOECHO) $(ECHO) 'name: NOTEDB' >> META.yml + $(NOECHO) $(ECHO) 'version: 1.31' >> META.yml + $(NOECHO) $(ECHO) 'version_from: NOTEDB.pm' >> META.yml + $(NOECHO) $(ECHO) 'installdirs: site' >> META.yml + $(NOECHO) $(ECHO) 'requires:' >> META.yml + $(NOECHO) $(ECHO) '' >> META.yml + $(NOECHO) $(ECHO) 'distribution_type: module' >> META.yml + $(NOECHO) $(ECHO) 'generated_by: ExtUtils::MakeMaker version 6.17' >> META.yml + + +# --- MakeMaker metafile_addtomanifest section: +metafile_addtomanifest: + $(NOECHO) $(PERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{META.yml} => q{Module meta-data (added by MakeMaker)}}) } ' \ + -e ' or print "Could not add META.yml to MANIFEST: $${'\''@'\''}\n"' + + +# --- MakeMaker dist_basics section: +distclean :: realclean distcheck + $(NOECHO) $(NOOP) + +distcheck : + $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck + +skipcheck : + $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck + +manifest : + $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest + +veryclean : realclean + $(RM_F) *~ *.orig */*~ */*.orig + + + +# --- MakeMaker dist_core section: + +dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE) + $(NOECHO) $(PERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \ + -e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' + +tardist : $(DISTVNAME).tar$(SUFFIX) + $(NOECHO) $(NOOP) + +uutardist : $(DISTVNAME).tar$(SUFFIX) + uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu + +$(DISTVNAME).tar$(SUFFIX) : distdir + $(PREOP) + $(TO_UNIX) + $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(COMPRESS) $(DISTVNAME).tar + $(POSTOP) + +zipdist : $(DISTVNAME).zip + $(NOECHO) $(NOOP) + +$(DISTVNAME).zip : distdir + $(PREOP) + $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(POSTOP) + +shdist : distdir + $(PREOP) + $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar + $(RM_RF) $(DISTVNAME) + $(POSTOP) + + +# --- MakeMaker distdir section: +distdir : metafile metafile_addtomanifest + $(RM_RF) $(DISTVNAME) + $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \ + -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" + + + +# --- MakeMaker dist_test section: + +disttest : distdir + cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL + cd $(DISTVNAME) && $(MAKE) $(PASTHRU) + cd $(DISTVNAME) && $(MAKE) test $(PASTHRU) + + +# --- MakeMaker dist_ci section: + +ci : + $(PERLRUN) "-MExtUtils::Manifest=maniread" \ + -e "@all = keys %{ maniread() };" \ + -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \ + -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});" + + +# --- MakeMaker install section: + +install :: all pure_install doc_install + +install_perl :: all pure_perl_install doc_perl_install + +install_site :: all pure_site_install doc_site_install + +install_vendor :: all pure_vendor_install doc_vendor_install + +pure_install :: pure_$(INSTALLDIRS)_install + +doc_install :: doc_$(INSTALLDIRS)_install + +pure__install : pure_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +doc__install : doc_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_perl_install :: + $(NOECHO) umask 022; $(MOD_INSTALL) \ + $(INST_LIB) $(DESTINSTALLPRIVLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLARCHLIB) \ + $(INST_BIN) $(DESTINSTALLBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(SITEARCHEXP)/auto/$(FULLEXT) + + +pure_site_install :: + $(NOECHO) umask 02; $(MOD_INSTALL) \ + read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \ + write $(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(DESTINSTALLSITELIB) \ + $(INST_ARCHLIB) $(DESTINSTALLSITEARCH) \ + $(INST_BIN) $(DESTINSTALLSITEBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(PERL_ARCHLIB)/auto/$(FULLEXT) + +pure_vendor_install :: + $(NOECHO) umask 022; $(MOD_INSTALL) \ + $(INST_LIB) $(DESTINSTALLVENDORLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) \ + $(INST_BIN) $(DESTINSTALLVENDORBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR) + +doc_perl_install :: + +doc_site_install :: + $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLSITEARCH)/perllocal.pod + -$(NOECHO) umask 02; $(MKPATH) $(DESTINSTALLSITEARCH) + -$(NOECHO) umask 02; $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLSITELIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(DESTINSTALLSITEARCH)/perllocal.pod + +doc_vendor_install :: + + +uninstall :: uninstall_from_$(INSTALLDIRS)dirs + +uninstall_from_perldirs :: + $(NOECHO) $(UNINSTALL) $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist + +uninstall_from_sitedirs :: + $(NOECHO) $(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist + +uninstall_from_vendordirs :: + $(NOECHO) $(UNINSTALL) $(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist + + +# --- MakeMaker force section: +# Phony target to force checking subdirectories. +FORCE: + $(NOECHO) $(NOOP) + + +# --- MakeMaker perldepend section: + + +# --- MakeMaker makefile section: + +# We take a very conservative approach here, but it's worth it. +# We move Makefile to Makefile.old here to avoid gnu make looping. +$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) + $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?" + $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..." + $(NOECHO) $(RM_F) $(MAKEFILE_OLD) + $(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) + -$(MAKE) -f $(MAKEFILE_OLD) clean $(DEV_NULL) || $(NOOP) + $(PERLRUN) Makefile.PL + $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <==" + $(NOECHO) $(ECHO) "==> Please rerun the make command. <==" + false + + + +# --- MakeMaker staticmake section: + +# --- MakeMaker makeaperl section --- +MAP_TARGET = perl +FULLPERL = /usr/bin/perl + +$(MAP_TARGET) :: static $(MAKE_APERL_FILE) + $(MAKE) -f $(MAKE_APERL_FILE) $@ + +$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) + $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) + $(NOECHO) $(PERLRUNINST) \ + Makefile.PL DIR= \ + MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ + MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= + + +# --- MakeMaker test section: + +TEST_VERBOSE=0 +TEST_TYPE=test_$(LINKTYPE) +TEST_FILE = test.pl +TEST_FILES = +TESTDB_SW = -d + +testdb :: testdb_$(LINKTYPE) + +test :: $(TEST_TYPE) + $(NOECHO) $(ECHO) 'No tests defined for $(NAME) extension.' + +test_dynamic :: pure_all + +testdb_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +test_ : test_dynamic + +test_static :: test_dynamic +testdb_static :: testdb_dynamic + + +# --- MakeMaker ppd section: +# Creates a PPD (Perl Package Description) for a binary distribution. +ppd: + $(NOECHO) $(ECHO) '' > $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' $(DISTNAME)' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) '' >> $(DISTNAME).ppd + + +# --- MakeMaker pm_to_blib section: + +pm_to_blib: $(TO_INST_PM) + $(NOECHO) $(PERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', '\''$(PM_FILTER)'\'')'\ + NOTEDB/general.pm $(INST_LIB)/NOTEDB/general.pm \ + NOTEDB/dbm.pm $(INST_LIB)/NOTEDB/dbm.pm \ + NOTEDB/README $(INST_LIB)/NOTEDB/README \ + NOTEDB.pm $(INST_LIB)/NOTEDB.pm \ + NOTEDB/text.pm $(INST_LIB)/NOTEDB/text.pm \ + NOTEDB/mysql.pm $(INST_LIB)/NOTEDB/mysql.pm \ + NOTEDB/binary.pm $(INST_LIB)/NOTEDB/binary.pm \ + NOTEDB/dumper.pm $(INST_LIB)/NOTEDB/dumper.pm \ + note.pod $(INST_LIB)/note.pod + $(NOECHO) $(TOUCH) $@ + +# --- MakeMaker selfdocument section: + + +# --- MakeMaker postamble section: + + +# End. diff --git a/README b/README index a7186ed..b2375f9 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -note 1.3.1 by Thomas Linden, 12/01/2005 +note 1.3.3 by Thomas Linden, 02/12/2005 ======================================= Introduction @@ -214,4 +214,4 @@ and I'll add you. Last changed ============ -11/01/2005 +02/12/2005 diff --git a/VERSION b/VERSION index 3a3cd8c..31e5c84 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.1 +1.3.3 diff --git a/bin/note b/bin/note index 010b112..79dcf4a 100755 --- a/bin/note +++ b/bin/note @@ -123,7 +123,7 @@ $CONF = File::Spec->catfile($ENV{HOME}, ".noterc"); $USER = getlogin || getpwuid($<); chomp $USER; $TOPIC = 1; -$version = "1.3.1"; +$version = "1.3.3"; $CurDepth = 1; # the current depth inside the topic "directory" structure... $maxlen = "auto"; $timelen = 22; @@ -1271,9 +1271,11 @@ sub output { $SSS = "-" x ($maxlen + 30); $nlen = length("$num"); $LINE = "$BORDERC $SSS $_BORDERC\n"; - $L = $BORDERC . "[" . $_BORDERC; $LONGSPC = " " x (25 - $nlen); - $R = $BORDERC . "]" . $_BORDERC; + if ($conf{printlines}) { + $L = $BORDERC . "[" . $_BORDERC; + $R = $BORDERC . "]" . $_BORDERC; + } $PathLen = length($PATH); # will be ZERO, if not in TOPIC mode! $VersionLen = length($version) + 7; @@ -1284,13 +1286,13 @@ sub output { $SP = " " x ($maxlen - 2 - $PathLen - $VersionLen); if (!$Raw) { # no title in raw-mode! - print C $LINE; + print C $LINE if ($conf{printlines}); print C "$L $NUMC#$_NUMC "; if ($ListType eq "LONG") { print C " $TIMEC" . "creation date$_TIMEC "; } else { - print $LONGSPC; + print $LONGSPC if ($conf{printlines}); } if ($TOPIC) { print C $TOPICC . "$PATH $_TOPICC$SP" . " note $version $R\n"; @@ -1298,7 +1300,7 @@ sub output { else { print C $NOTEC . "note$_NOTEC$SP" . " note $version $R\n"; } - print C $LINE; + print C $LINE if ($conf{printlines}); } $SetTitle = 1; } @@ -1328,7 +1330,7 @@ sub output { else { $title = substr($note,0,($txtlen - 2 - $nlen)); if (!$Raw) { - $title = $BORDERC . $NOTEC . $title . "... $_NOTEC$_BORDERC"; + $title = $BORDERC . $NOTEC . $title . " $_NOTEC$_BORDERC"; } } if ($Raw) { @@ -1346,18 +1348,18 @@ sub output { print C "$L$TIMEC" . $time . " $_TIMEC$R"; } print C "$L $NOTEC" . $title . "$_NOTEC $R\n"; - print C $LINE; + 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); - print C $LINE; + print C $LINE if ($conf{printlines}); print C "$L $NUMC$num$_NUMC $R$L$TIMEC$time$_TIMEC $Space$R\n"; print "\n"; print C $NOTEC . $note . $_NOTEC . "\n"; - print C $LINE if ($count == 1); + print C $LINE if ($count == 1 && $conf{printlines}); } } diff --git a/blib/arch/auto/NOTEDB/.exists b/blib/arch/auto/NOTEDB/.exists new file mode 100644 index 0000000..e69de29 diff --git a/blib/lib/.exists b/blib/lib/.exists new file mode 100644 index 0000000..e69de29 diff --git a/blib/lib/NOTEDB.pm b/blib/lib/NOTEDB.pm new file mode 100644 index 0000000..c561e3c --- /dev/null +++ b/blib/lib/NOTEDB.pm @@ -0,0 +1,305 @@ +# +# this is a generic module, used by note database +# backend modules. +# +# Copyright (c) 2000-2004 Thomas Linden + + +package NOTEDB; + +use Exporter (); +use vars qw(@ISA @EXPORT $crypt_supported); + +$NOTEDB::VERSION = "1.31"; + +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; +} + + +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/blib/lib/NOTEDB/README b/blib/lib/NOTEDB/README new file mode 100644 index 0000000..447198c --- /dev/null +++ b/blib/lib/NOTEDB/README @@ -0,0 +1,7 @@ +perl modules for note used as database backends. +the install.sh script will install both of them, +although you may only need one backend. Perhaps +other users on your system have oter ideas in mind... + +Therefore, please ignore these file. There is nothing +to edit or to do. Simply leave this directory :-) diff --git a/blib/lib/NOTEDB/binary.pm b/blib/lib/NOTEDB/binary.pm new file mode 100644 index 0000000..8ddabb9 --- /dev/null +++ b/blib/lib/NOTEDB/binary.pm @@ -0,0 +1,487 @@ +#!/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.10"; + +use strict; +#use Data::Dumper; +use IO::Seekable; +use File::Spec; +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} = $param{dbname} || File::Spec->catfile($ENV{HOME}, ".notedb"); + my $MAX_NOTE = $param{max_note} || 4096; + my $MAX_TIME = $param{max_time} || 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, $buffer, $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 (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}) { + 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::binary - module lib for accessing a notedb from perl + +=head1 SYNOPSIS + + # include the module + use NOTEDB; + + # create a new NOTEDB object + $db = new NOTEDB("binary", "/home/tom/.notedb", 4096, 24); + + # decide to use encryption + # $key is the cipher to use for encryption + # $method must be either Crypt::IDEA or Crypt::DES + # you need Crypt::CBC, Crypt::IDEA and Crypt::DES to have installed. + $db->use_crypt($key,$method); + + # do not use encryption + # this is the default + $db->no_crypt; + + # get a single note + ($note, $date) = $db->get_single(1); + + # search for a certain note + %matching_notes = $db->get_search("somewhat"); + # format of returned hash: + #$matching_notes{$numberofnote}->{'note' => 'something', 'date' => '23.12.2000 10:33:02'} + + # get all existing notes + %all_notes = $db->get_all(); + # format of returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + + # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH + $db->use_crypt("passphrase", "CryptMethod"); + + # turn off encryption. This is the default. + $db->no_crypt(); + + +=head1 DESCRIPTION + +You can use this module for accessing a note database. There are currently +two versions of this module, one version for a SQL database and one for a +binary file (note's own database-format). +However, both versions provides identical interfaces, which means, you do +not need to change your code, if you want to switch to another database format. + +Currently, NOTEDB module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + +=cut diff --git a/blib/lib/NOTEDB/dbm.pm b/blib/lib/NOTEDB/dbm.pm new file mode 100644 index 0000000..7f6724f --- /dev/null +++ b/blib/lib/NOTEDB/dbm.pm @@ -0,0 +1,269 @@ +#!/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.40"; + +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 = $param{directory} || File::Spec->catfile($ENV{HOME}, ".note_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 returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # recount all noteids starting by 1 (usefull after deleting one!) + $db->set_recountnums(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + +=head1 DESCRIPTION + +You can use this module for accessing a note database. This is the dbm module. +It uses the DB_FILE module to store it's data and it uses DBM files for tis purpose. + +Currently, NOTEDB module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + + +=cut diff --git a/blib/lib/NOTEDB/dumper.pm b/blib/lib/NOTEDB/dumper.pm new file mode 100644 index 0000000..3ae1ffb --- /dev/null +++ b/blib/lib/NOTEDB/dumper.pm @@ -0,0 +1,371 @@ +# Perl module for note +# text database backend. see docu: perldoc NOTEDB::text +# using Storable as backend. + +package NOTEDB::dumper; + +$NOTEDB::text::VERSION = "1.00"; + +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} = $param{dbname} || File::Spec->catfile($ENV{HOME}, ".notedb"); + + 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, $buffer, $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 returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + + # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH + $db->use_crypt("passphrase", "CryptMethod"); + + # turn off encryption. This is the default. + $db->no_crypt(); + + +=head1 DESCRIPTION + +You can use this module for accessing a note database. 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 webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + +=cut diff --git a/blib/lib/NOTEDB/general.pm b/blib/lib/NOTEDB/general.pm new file mode 100644 index 0000000..31671d6 --- /dev/null +++ b/blib/lib/NOTEDB/general.pm @@ -0,0 +1,408 @@ +# Perl module for note +# general database backend. see docu: perldoc NOTEDB::general +# using Config::General as backend. + +package NOTEDB::general; + +$NOTEDB::general::VERSION = "1.01"; + +use strict; +#use Data::Dumper; +use File::Spec; +use Config::General; +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"); + + 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->{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, $buffer, $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); + }; + print $@; + } + 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) = @_; + 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 returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + + # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH + $db->use_crypt("passphrase", "CryptMethod"); + + # turn off encryption. This is the default. + $db->no_crypt(); + + +=head1 DESCRIPTION + +You can use this module for accessing a note database. 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 webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + +=cut diff --git a/blib/lib/NOTEDB/mysql.pm b/blib/lib/NOTEDB/mysql.pm new file mode 100644 index 0000000..f17478c --- /dev/null +++ b/blib/lib/NOTEDB/mysql.pm @@ -0,0 +1,425 @@ +# +# 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 returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # recount all noteids starting by 1 (usefull after deleting one!) + $db->set_recountnums(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + + # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH + $db->use_crypt("passphrase", "CryptMethod"); + + # turn off encryption. This is the default. + $db->no_crypt(); + +=head1 DESCRIPTION + +You can use this module for accessing a note database. There are currently +two versions of this module, one version for a SQL database and one for a +binary file (note's own database-format). +However, both versions provides identical interfaces, which means, you do +not need to change your code, if you want to switch to another database format. + +Currently, NOTEDB module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + + +=cut diff --git a/blib/lib/NOTEDB/text.pm b/blib/lib/NOTEDB/text.pm new file mode 100644 index 0000000..b06edee --- /dev/null +++ b/blib/lib/NOTEDB/text.pm @@ -0,0 +1,358 @@ +# Perl module for note +# text database backend. see docu: perldoc NOTEDB::text +# using Storable as backend. + +package NOTEDB::text; + +$NOTEDB::text::VERSION = "1.03"; + +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} = $param{dbname} || File::Spec->catfile($ENV{HOME}, ".notedb"); + + 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, $buffer, $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++; + #$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++; + #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 { + # 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 returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + + # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH + $db->use_crypt("passphrase", "CryptMethod"); + + # turn off encryption. This is the default. + $db->no_crypt(); + + +=head1 DESCRIPTION + +You can use this module for accessing a note database. 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 webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + +=cut diff --git a/blib/lib/auto/NOTEDB/.exists b/blib/lib/auto/NOTEDB/.exists new file mode 100644 index 0000000..e69de29 diff --git a/blib/lib/note.pod b/blib/lib/note.pod new file mode 100644 index 0000000..a16d2a3 --- /dev/null +++ b/blib/lib/note.pod @@ -0,0 +1,528 @@ +# -*-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 commandline. 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)! + + +=head1 OPTIONS + + +=over + +=item I<-c, --config file> + +Use another config file than the default ~/.noterc. + + +=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<-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 commandline options. + +To create a new note, simply run "note". You can enter +the note (the length is by default limited to 4096 bytes, +which you can change from your config file if you are using +the binary backend, 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 occurence 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 occurence +of "moses" and "lenin" in ONE note. Or, if you are looking for +"mike OR daniel", then it searches for an occurence 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 commandline 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 aditional 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 occurence 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 + +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 usefull, if you want quickly trans- +fer your notes from one host to another (i.e. you could mail +your note-dump form your office to home and import it there +for further use). + +The dumps from the two versions of note are in the same format. +Using dumps it is also possible to reinitialize your database. You +can use the "-o" switch whcih causes note to overwrite your existing +database. This is very handy if you changed heavily your config. And +it is required, if you changed: encryption, db-driver, (binary-format) +and the password. You can use the following command for reinitializing: + + $ note -D - | note -o -I - + +What the hell, does this do?! Step by step: + +=over + +=item * + +B creates a note-database dump and prints it out +to stantdard 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! + + + + + +=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 forground and blue background +to hide a string from the terminal, which is usefull 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 +everytime 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 commandline 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 + +Thomas Linden + + +=head1 VERSION + +1.3.1 (12/01/2005) + +=cut diff --git a/blib/man3/.exists b/blib/man3/.exists new file mode 100644 index 0000000..e69de29 diff --git a/blib/man3/NOTEDB::binary.3pm b/blib/man3/NOTEDB::binary.3pm new file mode 100644 index 0000000..f728e94 --- /dev/null +++ b/blib/man3/NOTEDB::binary.3pm @@ -0,0 +1,224 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "NOTEDB::binary 3pm" +.TH NOTEDB::binary 3pm "2005-10-25" "perl v5.8.4" "User Contributed Perl Documentation" +.SH "NAME" +NOTEDB::binary \- module lib for accessing a notedb from perl +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& # include the module +\& use NOTEDB; +.Ve +.PP +.Vb 2 +\& # create a new NOTEDB object +\& $db = new NOTEDB("binary", "/home/tom/.notedb", 4096, 24); +.Ve +.PP +.Vb 5 +\& # 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); +.Ve +.PP +.Vb 3 +\& # do not use encryption +\& # this is the default +\& $db\->no_crypt; +.Ve +.PP +.Vb 2 +\& # get a single note +\& ($note, $date) = $db\->get_single(1); +.Ve +.PP +.Vb 4 +\& # 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'} +.Ve +.PP +.Vb 3 +\& # get all existing notes +\& %all_notes = $db\->get_all(); +\& # format of returnes hash like the one from get_search above +.Ve +.PP +.Vb 2 +\& # get the next noteid available +\& $next_num = $db\->get_nextnum(); +.Ve +.PP +.Vb 2 +\& # modify a certain note +\& $db\->set_edit(1, "any text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # create a new note +\& $db\->set_new(5, "any new text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # delete a certain note +\& $db\->set_del(5); +.Ve +.PP +.Vb 2 +\& # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH +\& $db\->use_crypt("passphrase", "CryptMethod"); +.Ve +.PP +.Vb 2 +\& # turn off encryption. This is the default. +\& $db\->no_crypt(); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +You can use this module for accessing a note database. There are currently +two versions of this module, one version for a \s-1SQL\s0 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. +.PP +Currently, \s-1NOTEDB\s0 module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... +.SH "USAGE" +.IX Header "USAGE" +please see the section \s-1SYNOPSIS\s0, it says it all. +.SH "AUTHOR" +.IX Header "AUTHOR" +Thomas Linden . diff --git a/blib/man3/NOTEDB::dbm.3pm b/blib/man3/NOTEDB::dbm.3pm new file mode 100644 index 0000000..8ea3047 --- /dev/null +++ b/blib/man3/NOTEDB::dbm.3pm @@ -0,0 +1,202 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "NOTEDB::dbm 3pm" +.TH NOTEDB::dbm 3pm "2005-10-25" "perl v5.8.4" "User Contributed Perl Documentation" +.SH "NAME" +NOTEDB::dbm \- module lib for accessing a notedb from perl +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& # include the module +\& use NOTEDB; +.Ve +.PP +.Vb 2 +\& # create a new NOTEDB object (the last 4 params are db table/field names) +\& $db = new NOTEDB("mysql","note","/home/user/.notedb/"); +.Ve +.PP +.Vb 2 +\& # get a single note +\& ($note, $date) = $db\->get_single(1); +.Ve +.PP +.Vb 4 +\& # 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'} +.Ve +.PP +.Vb 3 +\& # get all existing notes +\& %all_notes = $db\->get_all(); +\& # format of returnes hash like the one from get_search above +.Ve +.PP +.Vb 2 +\& # get the next noteid available +\& $next_num = $db\->get_nextnum(); +.Ve +.PP +.Vb 2 +\& # recount all noteids starting by 1 (usefull after deleting one!) +\& $db\->set_recountnums(); +.Ve +.PP +.Vb 2 +\& # modify a certain note +\& $db\->set_edit(1, "any text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # create a new note +\& $db\->set_new(5, "any new text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # delete a certain note +\& $db\->set_del(5); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +You can use this module for accessing a note database. This is the dbm module. +It uses the \s-1DB_FILE\s0 module to store it's data and it uses \s-1DBM\s0 files for tis purpose. +.PP +Currently, \s-1NOTEDB\s0 module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... +.SH "USAGE" +.IX Header "USAGE" +please see the section \s-1SYNOPSIS\s0, it says it all. +.SH "AUTHOR" +.IX Header "AUTHOR" +Thomas Linden . diff --git a/blib/man3/NOTEDB::dumper.3pm b/blib/man3/NOTEDB::dumper.3pm new file mode 100644 index 0000000..117089c --- /dev/null +++ b/blib/man3/NOTEDB::dumper.3pm @@ -0,0 +1,221 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "NOTEDB::dumper 3pm" +.TH NOTEDB::dumper 3pm "2005-10-25" "perl v5.8.4" "User Contributed Perl Documentation" +.SH "NAME" +NOTEDB::text \- module lib for accessing a notedb from perl +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& # include the module +\& use NOTEDB; +.Ve +.PP +.Vb 2 +\& # create a new NOTEDB object +\& $db = new NOTEDB("text", "/home/tom/.notedb", 4096, 24); +.Ve +.PP +.Vb 5 +\& # 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); +.Ve +.PP +.Vb 3 +\& # do not use encryption +\& # this is the default +\& $db\->no_crypt; +.Ve +.PP +.Vb 2 +\& # get a single note +\& ($note, $date) = $db\->get_single(1); +.Ve +.PP +.Vb 4 +\& # 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'} +.Ve +.PP +.Vb 3 +\& # get all existing notes +\& %all_notes = $db\->get_all(); +\& # format of returnes hash like the one from get_search above +.Ve +.PP +.Vb 2 +\& # get the next noteid available +\& $next_num = $db\->get_nextnum(); +.Ve +.PP +.Vb 2 +\& # modify a certain note +\& $db\->set_edit(1, "any text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # create a new note +\& $db\->set_new(5, "any new text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # delete a certain note +\& $db\->set_del(5); +.Ve +.PP +.Vb 2 +\& # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH +\& $db\->use_crypt("passphrase", "CryptMethod"); +.Ve +.PP +.Vb 2 +\& # turn off encryption. This is the default. +\& $db\->no_crypt(); +.Ve +.SH "DESCRIPTION" +.IX Header "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. +.PP +Currently, \s-1NOTEDB\s0 module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... +.SH "USAGE" +.IX Header "USAGE" +please see the section \s-1SYNOPSIS\s0, it says it all. +.SH "AUTHOR" +.IX Header "AUTHOR" +Thomas Linden . diff --git a/blib/man3/NOTEDB::general.3pm b/blib/man3/NOTEDB::general.3pm new file mode 100644 index 0000000..aed44c1 --- /dev/null +++ b/blib/man3/NOTEDB::general.3pm @@ -0,0 +1,221 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "NOTEDB::general 3pm" +.TH NOTEDB::general 3pm "2005-10-25" "perl v5.8.4" "User Contributed Perl Documentation" +.SH "NAME" +NOTEDB::general \- module lib for accessing a notedb from perl +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& # include the module +\& use NOTEDB; +.Ve +.PP +.Vb 2 +\& # create a new NOTEDB object +\& $db = new NOTEDB("text", "/home/tom/.notedb", 4096, 24); +.Ve +.PP +.Vb 5 +\& # 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); +.Ve +.PP +.Vb 3 +\& # do not use encryption +\& # this is the default +\& $db\->no_crypt; +.Ve +.PP +.Vb 2 +\& # get a single note +\& ($note, $date) = $db\->get_single(1); +.Ve +.PP +.Vb 4 +\& # 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'} +.Ve +.PP +.Vb 3 +\& # get all existing notes +\& %all_notes = $db\->get_all(); +\& # format of returnes hash like the one from get_search above +.Ve +.PP +.Vb 2 +\& # get the next noteid available +\& $next_num = $db\->get_nextnum(); +.Ve +.PP +.Vb 2 +\& # modify a certain note +\& $db\->set_edit(1, "any text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # create a new note +\& $db\->set_new(5, "any new text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # delete a certain note +\& $db\->set_del(5); +.Ve +.PP +.Vb 2 +\& # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH +\& $db\->use_crypt("passphrase", "CryptMethod"); +.Ve +.PP +.Vb 2 +\& # turn off encryption. This is the default. +\& $db\->no_crypt(); +.Ve +.SH "DESCRIPTION" +.IX Header "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. +.PP +Currently, \s-1NOTEDB\s0 module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... +.SH "USAGE" +.IX Header "USAGE" +please see the section \s-1SYNOPSIS\s0, it says it all. +.SH "AUTHOR" +.IX Header "AUTHOR" +Thomas Linden . diff --git a/blib/man3/NOTEDB::mysql.3pm b/blib/man3/NOTEDB::mysql.3pm new file mode 100644 index 0000000..3c13afb --- /dev/null +++ b/blib/man3/NOTEDB::mysql.3pm @@ -0,0 +1,215 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "NOTEDB::mysql 3pm" +.TH NOTEDB::mysql 3pm "2005-10-25" "perl v5.8.4" "User Contributed Perl Documentation" +.SH "NAME" +NOTEDB::mysql \- module lib for accessing a notedb from perl +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& # include the module +\& use NOTEDB; +.Ve +.PP +.Vb 2 +\& # 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"); +.Ve +.PP +.Vb 2 +\& # get a single note +\& ($note, $date) = $db\->get_single(1); +.Ve +.PP +.Vb 4 +\& # 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'} +.Ve +.PP +.Vb 3 +\& # get all existing notes +\& %all_notes = $db\->get_all(); +\& # format of returnes hash like the one from get_search above +.Ve +.PP +.Vb 2 +\& # get the next noteid available +\& $next_num = $db\->get_nextnum(); +.Ve +.PP +.Vb 2 +\& # recount all noteids starting by 1 (usefull after deleting one!) +\& $db\->set_recountnums(); +.Ve +.PP +.Vb 2 +\& # modify a certain note +\& $db\->set_edit(1, "any text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # create a new note +\& $db\->set_new(5, "any new text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # delete a certain note +\& $db\->set_del(5); +.Ve +.PP +.Vb 2 +\& # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH +\& $db\->use_crypt("passphrase", "CryptMethod"); +.Ve +.PP +.Vb 2 +\& # turn off encryption. This is the default. +\& $db\->no_crypt(); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +You can use this module for accessing a note database. There are currently +two versions of this module, one version for a \s-1SQL\s0 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. +.PP +Currently, \s-1NOTEDB\s0 module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... +.SH "USAGE" +.IX Header "USAGE" +please see the section \s-1SYNOPSIS\s0, it says it all. +.SH "AUTHOR" +.IX Header "AUTHOR" +Thomas Linden . diff --git a/blib/man3/NOTEDB::text.3pm b/blib/man3/NOTEDB::text.3pm new file mode 100644 index 0000000..b1168b1 --- /dev/null +++ b/blib/man3/NOTEDB::text.3pm @@ -0,0 +1,221 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "NOTEDB::text 3pm" +.TH NOTEDB::text 3pm "2005-10-25" "perl v5.8.4" "User Contributed Perl Documentation" +.SH "NAME" +NOTEDB::text \- module lib for accessing a notedb from perl +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& # include the module +\& use NOTEDB; +.Ve +.PP +.Vb 2 +\& # create a new NOTEDB object +\& $db = new NOTEDB("text", "/home/tom/.notedb", 4096, 24); +.Ve +.PP +.Vb 5 +\& # 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); +.Ve +.PP +.Vb 3 +\& # do not use encryption +\& # this is the default +\& $db\->no_crypt; +.Ve +.PP +.Vb 2 +\& # get a single note +\& ($note, $date) = $db\->get_single(1); +.Ve +.PP +.Vb 4 +\& # 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'} +.Ve +.PP +.Vb 3 +\& # get all existing notes +\& %all_notes = $db\->get_all(); +\& # format of returnes hash like the one from get_search above +.Ve +.PP +.Vb 2 +\& # get the next noteid available +\& $next_num = $db\->get_nextnum(); +.Ve +.PP +.Vb 2 +\& # modify a certain note +\& $db\->set_edit(1, "any text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # create a new note +\& $db\->set_new(5, "any new text", "23.12.2000 10:33:02"); +.Ve +.PP +.Vb 2 +\& # delete a certain note +\& $db\->set_del(5); +.Ve +.PP +.Vb 2 +\& # turn on encryption. CryptMethod must be IDEA, DES or BLOWFISH +\& $db\->use_crypt("passphrase", "CryptMethod"); +.Ve +.PP +.Vb 2 +\& # turn off encryption. This is the default. +\& $db\->no_crypt(); +.Ve +.SH "DESCRIPTION" +.IX Header "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. +.PP +Currently, \s-1NOTEDB\s0 module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... +.SH "USAGE" +.IX Header "USAGE" +please see the section \s-1SYNOPSIS\s0, it says it all. +.SH "AUTHOR" +.IX Header "AUTHOR" +Thomas Linden . diff --git a/blib/man3/note.3pm b/blib/man3/note.3pm new file mode 100644 index 0000000..d28a460 --- /dev/null +++ b/blib/man3/note.3pm @@ -0,0 +1,566 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "note 3pm" +.TH note 3pm "2005-10-25" "perl v5.8.4" "User Contributed Perl Documentation" +.SH "NAME" +note \- a perl script for maintaining notes. +.SH "SYNPOPSIS" +.IX Header "SYNPOPSIS" +note [options] [ number [,number...]] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBnote\fR is a small console program written in perl, which allows +you to manage notes similar to programs like \*(L"knotes\*(R" but from +the commandline. 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 \s-1DBI\s0 supported \s-1DBMS\s0), another +module, which uses a binary file for storage and a \s-1DBM\s0 module. +There are also two modules available which uses a text file. +Note supports since version 1.0.0 encryption(\s-1IDEA\s0 or \s-1DES\s0)! +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fI\-c, \-\-config file\fR" 4 +.IX Item "-c, --config file" +Use another config file than the default ~/.noterc. +.IP "\fI\-l, \-\-list [topic]\fR" 4 +.IX Item "-l, --list [topic]" +Lists all existing notes. If no topic were specified, +it will display a list of all existing topics. +See the section \fI\s-1TOPICS\s0\fR for details about topics. +.IP "\fI\-L, \-\-longlist [topic]\fR" 4 +.IX Item "-L, --longlist [topic]" +The same as \fI\-l\fR but prints also the timestamp of the notes. +.IP "\fI\-t, \-\-topic\fR" 4 +.IX Item "-t, --topic" +Prints a list of all topics as a tree. +.IP "\fI\-T, \-\-longtopic\fR" 4 +.IX Item "-T, --longtopic" +Prints the topic-tree with the notes under each topic. +.IP "\fI\-s, \-\-search string\fR" 4 +.IX Item "-s, --search string" +Searches for trough the notes database. See the section +\&\fI\s-1SEARCHING\s0\fR for details about the search engine. +.IP "\fI\-e, \-\-edit number\fR" 4 +.IX Item "-e, --edit number" +Edit the note with the number using your default editor +or the one you specified in the config file. +.IP "\fI\-d, \-\-delete number\fR" 4 +.IX Item "-d, --delete number" +Delete the note with the number . You can delete multiple notes +with one command. \*(L"1\-4\*(R" deletes the notes 1,2,3,4. And \*(L"1,5,7\*(R" deletes +the specified ones. +.IP "\fI\-D, \-\-Dump [file | \-]\fR" 4 +.IX Item "-D, --Dump [file | -]" +Dumps all notes to the textfile . If is a \*(L"\-\*(R" it will +be printed out to standard output (\s-1STDOUT\s0). +.IP "\fI\-I, \-\-Import file | \-\fR" 4 +.IX Item "-I, --Import file | -" +Imports a previously dumped textfile into the +note database. Data will be appended by default. +You can also specify a dash \fInote \-I \-\fR instead of a , +which causes note, silently to read in a dump from \s-1STDIN\s0. +.IP "\fI\-o, \-\-overwrite\fR" 4 +.IX Item "-o, --overwrite" +Only suitable for use with \-\-Import. Overwrites an +existing notedb. Use with care. +.IP "\fI\-r, \-\-raw\fR" 4 +.IX Item "-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. +.IP "\fI\-i, \-\-interactive\fR" 4 +.IX Item "-i, --interactive" +Start note in interactive mode. See the section \fI\s-1INTERACTIVE\s0 \s-1MODE\s0\fR +for details on this mode. +.IP "\fI\-\-encrypt cleartext\fR" 4 +.IX Item "--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!). +.IP "\fI\-h, \-\-help\fR" 4 +.IX Item "-h, --help" +Display this help screen. +.IP "\fI\-v, \-\-version\fR" 4 +.IX Item "-v, --version" +Display the version number. +.IP "\fB\-\fR" 4 +.IX Item "-" +If you run note just with one dash: \fBnote \-\fR, then it will read in a new +note from \s-1STDIN\s0 until \s-1EOF\s0. This makes it possible to pipe text into a new note, i.e.: +.Sp +.Vb 1 +\& cat sometextfile | note \- +.Ve +.SH "USAGE" +.IX Header "USAGE" +.Sh "\s-1GENERAL\s0 \s-1USAGE\s0" +.IX Subsection "GENERAL USAGE" +If you don't know, how to run note, try \*(L"note \-h\*(R" first. +It will tell you all available commandline options. +.PP +To create a new note, simply run \*(L"note\*(R". 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. +.PP +If you want to view the note, type \*(L"note 1\*(R", if the notenumber +was 1. +.PP +If you want to get an overview of all notes, type \*(L"note \-l\*(R". +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"\-L\*(R" instead of \*(L"\-l\*(R". +Read more about topics below in the section \*(L"Topics\*(R". +You can also specify the topic which notes you want to see: +\&\*(L"\-l mytopic\*(R" does the trick. +Additional, you might want to get an overview of your topic\- +structure. You can use the command \*(L"\-t\*(R" in this case, which +will display a tree-view of your topic\-structure. You can +use the command \*(L"\-T\*(R" if you want to see the notes under each +topic too. \*(L"\-T\*(R" will also show the number of each note. +.PP +To edit a certain note, type \*(L"note \-e 1\*(R". It will invoke your +editor (vi or pico). You can edit it, after saving, note +will store the changed note to the database. +.PP +Of course you can drop a certain note: \*(L"note \-d 1\*(R" 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 \*(L"\-d 1,2\*(R" +To delete note 1,2 and 3, use \*(L"\-d 1\-3\*(R". +.Sh "\s-1SEARCHING\s0" +.IX Subsection "SEARCHING" +If you cannot remember, which note you are looking for, you +can use the search capability of note: \*(L"note \-s \*(R". +note will search the whole note database case insensitive for +an occurence of this string and tell you the number and first\- +line it has. +.PP +You can extend the searchstring using \fB\s-1AND\s0\fR, \fB\s-1OR\s0\fR ( and ) and +shell-like wildcards: +.PP +.Vb 1 +\& $ note \-s "moses AND lenin" +.Ve +.PP +or: +.PP +.Vb 1 +\& $ note \-s "(mike OR arnold) AND (jackson OR schwarzenegger)" +.Ve +.PP +If note finds a note, which first line is a topic, then it will +display it's second line. +.PP +These rules apply for the interactive search too. +.PP +You need to know, that note searches for the expression in every +note. In other words, \*(L"moses \s-1AND\s0 lenin\*(R" searches for an occurence +of \*(L"moses\*(R" and \*(L"lenin\*(R" in \s-1ONE\s0 note. Or, if you are looking for +\&\*(L"mike \s-1OR\s0 daniel\*(R", then it searches for an occurence of \*(L"mike\*(R" or +daniel\*(L" in \s-1ONE\s0 note. Thus a note with the text \*(R"mike oldfield" will +match that search. +.Sh "\s-1TOPICS\s0" +.IX Subsection "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 \*(L"TopicSeparator\*(R" in your config! default +is slash), then note will consider it as the topic of this certain +note. For examle: +.PP +.Vb 1 +\& B +.Ve +.PP +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. +.PP +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 \*(L"/topicname/\*(R" to the text of your +note). +.PP +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. +.PP +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: +.PP +.Vb 10 +\& (root \- top level) +\& | +\& |\-\-\-\-test +\& | |\-\-\-\-subtopic +\& | | |\-\-note 1 +\& | | |\-\-note 2 +\& | | +\& | |\-\-note 4 +\& | +\& |\-\-note 3 +.Ve +.PP +Then you may create those 4 new notes: +.PP +.Vb 12 +\& \-\-\- snip \-\-\- +\& /test/subtopic/ +\& note 1 +\& \-\-\- snip \-\-\- +\& /test/subtopic/ +\& note 2 +\& \-\-\- snip \-\-\- +\& note 3 +\& \-\-\- snip \-\-\- +\& /test/ +\& note 4 +\& \-\-\- snip \-\-\- +.Ve +.PP +I hope, you got the point ;\-) +.PP +If a note does not contain the \*(L"magic\*(R" /topic/ construction on the first +line, it will be listed under the \*(L"root\*(R" of note, that is the point +you are at the startup of note. +.PP +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. +.PP +Note: Please don't forget the prepending and appending a slash of a +topic. You will get strange results without it! +.Sh "\s-1INTERACTIVE\s0 \s-1MODE\s0" +.IX Subsection "INTERACTIVE MODE" +If you start note with the commandline flag \fB\-i\fR, then it starts +with an interactive interface. +It will start with a listing under the default top-topic (\*(L"/\*(R"). +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. +.PP +The following commands are available: +.IP "\fBL [topic]\fR" 4 +.IX Item "L [topic]" +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. +.IP "\fBl [topic]\fR" 4 +.IX Item "l [topic]" +This commands behaves similar to \fBL\fR but it does not display the timestamp. +You can achieve the same result by simply pressing enter at any time. +.IP "\fBN\fR" 4 +.IX Item "N" +You can create a new note by simply pressing \fBN\fR or \fBn\fR. 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 aditional line to the top of the note with the topic. But +you can of course specify your own topic. +.Sp +Note will tell you which number it has assigned to the newly created note. +.IP "\fBE number\fR" 4 +.IX Item "E number" +By entering \fBE\fR or \fBe\fR 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. +.IP "\fBD number\fR" 4 +.IX Item "D number" +\&\fBE\fR or \fBe\fR 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. +.IP "\fBS [expression]\fR" 4 +.IX Item "S [expression]" +You can search for the occurence of a text in your notes-database with the +command \fBS\fR or \fBs\fR. If you omit an expression note will ask you for one. +.Sp +If your search criteria matches on exactly one entry, note will display +that note entry instead of displaying its number. +.IP "\fBT\fR" 4 +.IX Item "T" +This prints a tree-view of your topic\-structure. \fBT\fR displays the tree with +notes, \fBt\fR displays just the topics without notes. +.IP "\fBcd topic\fR" 4 +.IX Item "cd topic" +Change the actual topic under which you are. This works identical like just +entering the topic but it has some advantages. You can enter \fBcd ..\fR if +you want to go one level up in the topic\-structure. And you can enter \fBcd /\fR +to go to the top of the structure. You can always leave out the 'cd' keyword too. +.Sp +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 \fBShortCd\fR +to \fB1\fR or \fByes\fR. If you use a number and the note with this number is +under a certain topic then you will \*(L"cd\*(R" to this topic. This allows you +to do kind of jumps over multiple levels of topics. +.Sp +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. +.IP "\fB? or h\fR" 4 +.IX Item "? or h" +Display a short help screen. +.IP "\fBQ\fR" 4 +.IX Item "Q" +Quit note. +.Sh "\s-1BACKUP\s0" +.IX Subsection "BACKUP" +You can also dump the contents of your note-database into a +ASCII\-textfile(\fI\-D\fR). You can use this file later to import it into +your note\-database(\-I). This is usefull, if you want quickly trans\- +fer your notes from one host to another (i.e. you could mail +your note-dump form your office to home and import it there +for further use). +.PP +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 \*(L"\-o\*(R" switch whcih causes note to overwrite your existing +database. This is very handy if you changed heavily your config. And +it is required, if you changed: encryption, db\-driver, (binary\-format) +and the password. You can use the following command for reinitializing: +.PP +.Vb 1 +\& $ note \-D \- | note \-o \-I \- +.Ve +.PP +What the hell, does this do?! Step by step: +.IP "\(bu" 4 +\&\fBnote \-D \-\fR creates a note-database dump and prints it out +to stantdard output. +.IP "\(bu" 4 +\&\fB|\fR 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. +.IP "\(bu" 4 +\&\fBnote \-o \-I \-\fR imports a note-database dump from standard +input and overwrites an existing database. +.PP +Before you use the \fB\-o\fR switch, I consider you to make a backup! +.Sh "\s-1FORMATING\s0" +.IX Subsection "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 +\&\*(L"magic\-strings\*(R" for colorizing. Those strings looks much like \s-1HTML:\s0 +\&\*(L"here is a green line of text no more green.\*(R" +As you see, the beginning of another color starts with a tag(kinda) of +the color and ends with an end tag . +.PP +The following colors are available: +black, red, green, yellow, blue, magenta, cyan and white. +.PP +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 \*(L"FormatText\*(R" 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: +.PP +.Vb 4 +\& bold: **word** +\& underlined: __word__ +\& inverse: {{word}} +\& hidden: //word// +.Ve +.PP +The text will be formatted using the actually note\-color. +.PP +The hidden formatting will use blue forground and blue background +to hide a string from the terminal, which is usefull for passwords. +.PP +If you set \*(L"FormatText\*(R" to \fIsimple\fR then the formatting can be +done this way instead: +.PP +.Vb 4 +\& bold: *word* +\& underlined: _word_ +\& inverse: {word} +\& hidden: /word/ +.Ve +.SH "ENCRYPTION" +.IX Header "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 \*(L"migrate\*(R" +to encryption, I suggest you to follow the directions in the +file \s-1UPGRADE\s0! +.PP +You can choose from different encryption algorythms. The default +is \s-1IDEA\s0, but \s-1DES\s0 or \s-1BLOWFISH\s0 are also possible. You need to have +installed the following additional perl-modules on your system: +\&\s-1MD5\s0 +Crypt::IDEA +Crypt::DES +Crypt::CBC +.PP +After turning on encryption, note will ask you for a passphrase +everytime it runs! It will *not* store this passphrase! +So, don't forget it! Be careful! +.SH "CONFIGURATION" +.IX Header "CONFIGURATION" +You can use a configuration file with note but it is not required. +Note will use default values if there is no config. +.PP +The default config file is \fB~/.noterc\fR. You may specify another +one with the commandline flag \fI\-\-config\fR. +.PP +Comments start with #, empty lines will be ignored. +.PP +To turn on an option, set it to: \fB1\fR, \fBon\fR or \fByes\fR. +.PP +To turn off an option, set it to: \fB0\fR, \fBoff\fR or \fBno\fR. +.PP +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. +.PP +Variable names are case in\-sensitive. +.PP +For a detailed explanation of each possible parameter take a look +at the supplied sample configuration file in \fBconfig/noterc\fR. +.SH "AUTHOR" +.IX Header "AUTHOR" +Thomas Linden +.SH "VERSION" +.IX Header "VERSION" +1.3.1 (12/01/2005) diff --git a/blib/script/.exists b/blib/script/.exists new file mode 100644 index 0000000..e69de29 diff --git a/blib/script/note b/blib/script/note new file mode 100755 index 0000000..b842a6a --- /dev/null +++ b/blib/script/note @@ -0,0 +1,1671 @@ +#!/usr/bin/perl + +eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' + if 0; # not running under some shell +# +# note - console notes management with database and encryption support. +# Copyright (C) 1999-2004 Thomas Linden (see README for details!) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# - Thomas Linden +# +# latest version on: +# http://www.daemon.de/note/ +# + +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 Data::Dumper; + + +# +# prototypes +# +sub usage; # print usage message for us thumb userz :-) +sub find_editor; # returns an external editor for use +sub output; # used by &list and &display +sub C; # print colourized +sub num_bereich; # returns array from "1-4" (1,2,3,4) +sub getdate; # return pretty formatted day +sub new; # crate new note +sub edit; # edit a note +sub del; # delete a note +sub display; # display one or more notes +sub list; # note-listing +sub help; # interactive help screen +sub import; # import from notedb-dump +sub display_tree; # show nice tree-view +sub tree; # build the tree +sub print_tree; # print the tree, contributed by Jens Heunemann . THX! + + +# +# globals +# +my ( + # + # commandline options + # + $opt_, $opt_i, $opt_r, $opt_e, $opt_d, $opt_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, + + # + # set from commandline (or interactive) + # + $number, $searchstring, $dump_file, $ImportType, $NewType, $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, + ); + + +# +# DEFAULTS, allows one to use note without a config +# don't change them, instead use the config file! +# + +$conf{dbdriver} = "binary"; +$conf{usecolors} = 1; +$conf{bordercolor} = "bold"; +$conf{numbercolor} = "blue"; +$conf{notecolor} = "green"; +$conf{timecolor} = "blue"; +$conf{topiccolor} = "bold"; +$conf{topicseparator} = '/'; +$conf{useencryption} = 0; +$conf{tempdirectory} = File::Spec->tmpdir(); +$conf{alwaysinteractive} = 1; +$conf{alwayseditor} = 1; +$conf{autoclear} = 1; + +$CONF = File::Spec->catfile($ENV{HOME}, ".noterc"); +$USER = getlogin || getpwuid($<); +chomp $USER; +$TOPIC = 1; +$version = "1.3.3"; +$CurDepth = 1; # the current depth inside the topic "directory" structure... +$maxlen = "auto"; +$timelen = 22; + + +# 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"; + $NewType = 1; # read from STDIN until EOF + shift; + undef $has_nothing; +} +else { + Getopt::Long::Configure( qw(no_ignore_case)); + GetOptions ( + "interactive|i!" => \$opt_i, # no arg + "config|c=s" => \$opt_c, # string, required + "raw|r!" => \$opt_r, # no arg + "edit|e=i" => \$opt_e, # integer, required + "delete|d=s" => \$opt_d, # integer, required + "search|s=s" => \$opt_s, # string, required + "tree|topic|t!" => \$opt_t, # no arg + "longtopic|T!" => \$opt_T, # no arg + "list|l:s" => \$opt_l, # string, optional + "longlist|L:s" => \$opt_L, # string, optional + "dump||Dump|D:s" => \$opt_D, # string, optional + "import|Import|I:s" => \$opt_I, # string, optional + "overwrite|o!" => \$opt_o, # no arg + "help|h|?!" => \$opt_h, # no arg + "version|v!" => \$opt_v, # no arg + "encrypt=s" => \$opt_enc, # string, required + ); + $opt_n = shift; # after that @ARGV contains eventually + # a note-number + # $opt_ is a single dash, in case of existence! + # + # determine mode + # + if ($opt_i) { + $mode = "interactive"; + } + elsif (defined $opt_l || defined $opt_L) { + $mode = "list"; + if (defined $opt_l) { + @ArgTopics = split /$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"; + $TreeType = "LONG" if($opt_T); + } + elsif (defined $opt_s) { + $mode = "search"; + $searchstring = $opt_s; + } + elsif ($opt_e) { + $mode = "edit"; + $number = $opt_e; + } + elsif ($opt_d) { + $mode = "delete"; + $number = $opt_d; + } + elsif ($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 + } + } + elsif (defined $opt_I) { + $mode = "import"; + if (!$opt_) { + if ($opt_I ne "") { + $dump_file = $opt_I; + } + else { + print "Import-error! No dump_file specified!\n"; + exit(1); + } + } + else { + $dump_file = "-"; + } + } + elsif ($opt_v) { + print "This is note $version by Thomas Linden .\n"; + exit(0); + } + elsif ($opt_h) { + &usage; + } + else { + if ($opt_c && $mode eq "" && !$opt_n) { + $mode = "new"; + } + elsif ($opt_c && $mode eq "") { + $mode = ""; # huh?! + } + else { + $has_nothing = 1; + } + } + ### determine generic options + if ($opt_n =~ /^[\d+\-?\,*]+$/) { + # first arg is a digit! + if ($mode eq "") { + $number = $opt_n; + $mode = "display"; + undef $has_nothing; + } + else { + print "mode <$mode> does not take a numerical argument!\n"; + exit(1); + } + } + elsif ($opt_n ne "") { + print "Unknown option: $opt_n\n"; + &usage; + } + if ($opt_r) { + $Raw = 1; + } + if ($opt_o) { + $ImportType = "overwrite"; + if (!$opt_I) { + print "--overwrite is only suitable for use with --import!\n"; + exit(1); + } + } + ##### +} +if ($has_nothing && $mode eq "") { + &usage; +} + + +# read the configfile. +$CONF = $opt_c if($opt_c); # if given by commandline, use this. +if (-e $CONF) { + &getconfig($CONF); +} +elsif ($opt_c) { + # only wrong, if specified by commandline! else use default values! + print STDERR "Could not open \"$CONF\": file does not exist or permission denied!\n"; + exit(1); +} + +# directly jump to encrypt, 'cause this sub does +# not require a database connection +if ($mode eq "encrypt_passwd") { + &encrypt_passwd; + exit; +} + +# Always interactive? +if ($conf{alwaysinteractive} && $mode ne "dump" && $mode ne "import") { + $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 "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 do 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! +} +else { + &load_driver(); + $db->no_crypt; + + # does: NOTEDB::crypt_supported = 0; + my ($cnote, $cdate) = $db->get_single(1); + if ($cdate ne "") { + if ($cdate !~ /^\d+\.\d+?/) { + print "notedb seems to be encrypted!\n"; + exit(1); + } + } +} + + +# 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"; + } +} + + +############################### 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; + 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; + return if $db->lock(); + if ($conf{alwayseditor}) { + $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 { + $note = ""; + $line = ""; + # create a new note + if ($NewType) { + # be silent! read from STDIN until EOF. + while () { + $note .= $_; + } + } + else { + print "enter the text of the note, end with 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"; + } + } + $db->set_new($number,$note,$date); + # everything ok until here! + print "note stored. it has been assigned the number $number.\n\n"; + $db->unlock(); + } + + +############################### 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(); + foreach $num (sort { $a <=> $b } keys %res) { + print STDOUT "dumping note number $num to $dump_file\n" if($dump_file ne "-"); + print "Number: $num\n" + ."Timestamp: $res{$num}->{'date'}\n" + ."$res{$num}->{'note'}\n"; + } + print "\n"; + close(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; + } + + $complete = $start = 0; + $number = 1; + while (<$DUMP>) { + chomp $_; + if ($_ =~ /^Number:\s\d+/) { + if ($start == 0) { + # we have no previous record + $start = 1; + } + else { + # we got a complete record, save it! + $data{$number} = { + date => $date, + note => $note + }; + print "fetched note number $number from $dump_file from $date.\n" if(!$stdin); + $complete = 0; + $note = ""; + $date = ""; + $number++; + } + } + elsif ($_ =~ /^Timestamp:\s\d+/ && $complete == 0) { + ($dummi,$date,$time) = split(/\s/,$_); + $date = "$date $time"; + $complete = 1; + } + else { + $note .= $_ . "\n"; + } + } + + if ($note ne "" && $date ne "") { + # the last record, if existent + $data{$number} = { + data => $date, + note => $note + }; + print "fetched note number $number from $dump_file from $date.\n" if(!$stdin); + } + + $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" : ""; + &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 . ">"; + } + + # 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 =~ /^\.\.$/ || $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 Thomas Linden (c) 1999-2003. +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...]] +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); + print C $LINE if ($conf{printlines}); + print C "$L $NUMC$num$_NUMC $R$L$TIMEC$time$_TIMEC $Space$R\n"; + print "\n"; + print C $NOTEC . $note . $_NOTEC . "\n"; + print C $LINE if ($count == 1 && $conf{printlines}); + } + } + + + +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); + $L = $B . "L" . $BB . $NOTEC; + $T = $B . "T" . $BB . $NOTEC; + $Q = $B . "Q" . $BB . $NOTEC; + $H = $B . "?" . $BB . $NOTEC; + $N = $B . "N" . $BB . $NOTEC; + $D = $B . "D" . $BB . $NOTEC; + $E = $B . "E" . $BB . $NOTEC; + $S = $B . "S" . $BB . $NOTEC; + + print C qq~$BORDERC +----------------------------------------------------------------------$_BORDERC $TOPICC +HELP for interactive note $version +$_TOPICC $NOTEC +The following commands are available: +$L List notes. L=long, with timestamp and l=short without timestamp. + You can also just hit for short list. + If you specify a subtopic, then list will display it's contents, + i.e.: "l mytopic" will dislpay notes under mytopic. +$N Create a new note. +$D Delete a note. You can either hit "d 1" or "d 1-4" or just hit "d". + If you don't specify a number, you will be asked for. +$S Search trough the notes database. Usage is similar to Delete, use + a string instead of a number to search for. +$E Edit a note. Usage is similar to Delete but you can only edit note + a time. +$H This help screen. +$Q Exit the program.~; + if ($TOPIC) { + print C qq~ +$T print a list of all existing topics as a tree. T prints the tree + with all notes under each topic.~; + } + 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; + } + &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}}}); + } + } +} + + +__END__ diff --git a/config/noterc b/config/noterc index 4bc7226..e306ca0 100644 --- a/config/noterc +++ b/config/noterc @@ -1,4 +1,4 @@ - # note 1.3.1 -*- sh -*- + # note 1.3.3 -*- sh -*- # # This is a sample config for the note script # There are useful defaults set in note itself. @@ -232,6 +232,13 @@ ReadOnly = NO + # + # Note separates titles and topics using horizontal lines when + # listing them. You can turn off this behavior by setting + # PrintLines to NO. + # The default is: YES +PrintLines = YES + # # diff --git a/pm_to_blib b/pm_to_blib new file mode 100644 index 0000000..e69de29