- merge branches/py-lib, revisions 265-325 to trunk
git-svn-id: https://svn.ibp.de/svn/capisuite/trunk/capisuite@328 4ebea2bb-67d4-0310-8558-a5799e421b66
This commit is contained in:
parent
b75a6e0f54
commit
a22481c4fc
1
AUTHORS
1
AUTHORS
|
@ -1 +1,2 @@
|
||||||
Gernot Hillier <gernot@hillier.de>
|
Gernot Hillier <gernot@hillier.de>
|
||||||
|
Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
|
|
119
ChangeLog
119
ChangeLog
|
@ -1,9 +1,32 @@
|
||||||
|
2004-10-25 Gernot Hillier <gernot@hillier.de>
|
||||||
|
* src/capisuite-py/config.py.in: minor documentation changes
|
||||||
|
* src/capisuite-py/__init__.py: Likewise.
|
||||||
|
* src/capisuite-py/config.py.in (class NoGlobalSectionError): moved
|
||||||
|
to exceptions.py
|
||||||
|
* src/capisuite-py/exceptions.py: Likewise.
|
||||||
|
|
||||||
|
2004-09-04 Gernot Hillier <gernot@hillier.de>
|
||||||
|
* scripts/cs_helpers.pyin (__sendmail, __call, sff2tif, cff2ps,
|
||||||
|
la2wav, sendMIMEMail): fix several bugs, answering machine now seems
|
||||||
|
to work basically
|
||||||
|
* scripts/answering_machine.confin: update description of parameter
|
||||||
|
voice_email to new behaviour (empty string not allowed any more)
|
||||||
|
* NEWS: Likewise.
|
||||||
|
|
||||||
2004-07-15 Gernot Hillier <gernot@hillier.de>
|
2004-07-15 Gernot Hillier <gernot@hillier.de>
|
||||||
* configure.in: support new parameter in ALERT_REQ of newer capi4linux
|
* configure.in: support new parameter in ALERT_REQ of newer capi4linux
|
||||||
versions, thx to Steffen Barszus for reporting and the fix
|
versions, thx to Steffen Barszus for reporting and the fix
|
||||||
* src/backend/capi.cpp (Capi::alert_req): Likewise.
|
* src/backend/capi.cpp (Capi::alert_req): Likewise.
|
||||||
* acinclude.m4 (CS_TEST_CAPI4LINUX): Likewise.
|
* acinclude.m4 (CS_TEST_CAPI4LINUX): Likewise.
|
||||||
|
|
||||||
|
2004-06-12 Gernot Hillier <gernot@hillier.de>
|
||||||
|
* scripts/incoming.py (voiceIncoming): create file in received queue
|
||||||
|
only if necessary (i.e. as late as possible)
|
||||||
|
* src/capisuite-py/fileutils.py (_releaseLock): ignore insignificant
|
||||||
|
error resulting from race condition
|
||||||
|
* src/capisuite-py/voice.py (createReceivedJob): fix argument passing
|
||||||
|
* scripts/cs_helpers.pyin (sendMIMEMail): stringify exception instance
|
||||||
|
|
||||||
2004-06-10 Gernot Hillier <gernot@hillier.de>
|
2004-06-10 Gernot Hillier <gernot@hillier.de>
|
||||||
* src/backend/connection.cpp (info_ind_called_party_nr): prevent
|
* src/backend/connection.cpp (info_ind_called_party_nr): prevent
|
||||||
CapiSuite from crashing when a too high DDIBaseLength was configured,
|
CapiSuite from crashing when a too high DDIBaseLength was configured,
|
||||||
|
@ -17,9 +40,33 @@
|
||||||
to avoid using phony targets in man page creation
|
to avoid using phony targets in man page creation
|
||||||
* docs/manual.docbook.in: see above.
|
* docs/manual.docbook.in: see above.
|
||||||
|
|
||||||
|
2004-05-10 Gernot Hillier <gernot@hillier.de>
|
||||||
|
* src/capisuite-py/core.py (Call.log,Call.__init__,Call.reject,
|
||||||
|
Call.disconnect): fix minor bugs in function calls, import some
|
||||||
|
additional symbols from _capisuite to our namespace, rename call_from
|
||||||
|
and call_to attributes of class Call to from_nr and to_nr, don't set
|
||||||
|
_handle to None after disconnect/reject
|
||||||
|
* scripts/incoming.py (callIncoming,faxIncoming,voiceIncoming): rename
|
||||||
|
call_from and call_to attributes of class Call to from_nr and to_nr;
|
||||||
|
use them everywhere instead of old global variables
|
||||||
|
* src/application/capisuitemodule.cpp (convertConnRef,convertCapiRef):
|
||||||
|
improve misleading error message
|
||||||
|
|
||||||
2004-04-18 Gernot Hillier <gernot@hillier.de>
|
2004-04-18 Gernot Hillier <gernot@hillier.de>
|
||||||
* scripts/capisuitefax.in: allow * and # in destination numbers
|
* scripts/capisuitefax.in: allow * and # in destination numbers
|
||||||
|
|
||||||
|
2004-04-09 Gernot Hillier <gernot@hillier.de>
|
||||||
|
* src/capisuite-py/core.py (Capi.call_voice,Capi.call_faxG3): fix
|
||||||
|
some namespace problems and typos
|
||||||
|
|
||||||
|
2004-04-04 Gernot Hillier <gernot@hillier.de>
|
||||||
|
* configure.in: add support to install new capisuite Python module
|
||||||
|
* src/Makefile.am: Likewise
|
||||||
|
* src/capisuite-py/Makefile.am: Likewise (new file)
|
||||||
|
* src/capisuite-py/core.py (class Call): new method Call.log
|
||||||
|
* scripts/incoming.py (callIncoming,faxIncoming,voiceIncoming): use
|
||||||
|
Call.log instead of core.log where appropriate
|
||||||
|
|
||||||
2004-03-24 Gernot Hillier <gernot@hillier.de>
|
2004-03-24 Gernot Hillier <gernot@hillier.de>
|
||||||
* docs/Makefile.am: change pathes to Docbook stylesheets to reflect
|
* docs/Makefile.am: change pathes to Docbook stylesheets to reflect
|
||||||
changes in SUSE 9.1
|
changes in SUSE 9.1
|
||||||
|
@ -31,16 +78,72 @@
|
||||||
2004-03-23 Gernot Hillier <gernot@hillier.de>
|
2004-03-23 Gernot Hillier <gernot@hillier.de>
|
||||||
* docs/manual-de.docbook (capicodes_protocol): fix small typo
|
* docs/manual-de.docbook (capicodes_protocol): fix small typo
|
||||||
|
|
||||||
|
2004-03-21 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
|
* scripts/fax.confin: Removed spaces from section names "Mail ...".
|
||||||
|
* scripts/answering_machine.confin: Likewise.
|
||||||
|
* scripts/incoming.py: Likewise.
|
||||||
|
* scripts/idle.py: Likewise.
|
||||||
|
* rc.capisuite.in: Likewise within a comment.
|
||||||
|
* scripts/incoming.py: Removed some outdated comments.
|
||||||
|
|
||||||
2004-03-20 Gernot Hillier <gernot@hillier.de>
|
2004-03-20 Gernot Hillier <gernot@hillier.de>
|
||||||
* src/application/pythonscript.h: extend prefix() so that it can create
|
* src/application/pythonscript.h (prefix): add support for short
|
||||||
a short prefix, too; use short prefix for Python traceback (fixes bug
|
logging prefixes; use them for Python tracebacks (fixes bug
|
||||||
#63, reported anonymously)
|
#63, reported anonymously)
|
||||||
* src/application/pythonscript.cpp: Likewise.
|
* src/application/pythonscript.cpp (prefix,run): Likewise.
|
||||||
* scripts/incoming.py: Fix typo.
|
* scripts/incoming.py: Fix typo.
|
||||||
|
|
||||||
|
2004-03-19 Gernot Hillier <gernot@hillier.de>
|
||||||
|
* scripts/idle.py: Remove old CVS history
|
||||||
|
* scripts/incoming.py: Likewise.
|
||||||
|
* scripts/incoming.py: changed some comments, moved connection
|
||||||
|
accept code to voiceIncoming
|
||||||
|
|
||||||
|
2004-03-14 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
|
* scripts/incoming.py: Use capisuite.core instead of _capisuite.
|
||||||
|
* src/capisuite-py/fax.py: Removed faxInfo2dict.
|
||||||
|
* src/capisuite-py/core.py: Added OO layer for _capisuite
|
||||||
|
functions and classes Capi and Call.
|
||||||
|
* src/capisuite-py/core.py: New class FaxInfo.
|
||||||
|
|
||||||
2004-03-09 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
2004-03-09 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
* src/application/idlescript.cpp: Reduced delay until
|
* SConstruct: new file for building with SCons build-system.
|
||||||
|
* SConscript: Likewise.
|
||||||
|
* SConscript-Config: Likewise.
|
||||||
|
* SConscript-Options: Likewise.
|
||||||
|
* docs/SConscript: Likewise.
|
||||||
|
* scripts/SConscript: Likewise.
|
||||||
|
* scripts/waves/SConscript: Likewise.
|
||||||
|
* src/SConscript: Likewise.
|
||||||
|
* src/application/SConscript: Likewise.
|
||||||
|
* src/backend/SConscript: Likewise.
|
||||||
|
* src/modules/SConscript: Likewise.
|
||||||
|
* src/application/capisuitemodule.cpp (capisuitemodule_init): Renamed
|
||||||
|
built-in module to '_capisuite'
|
||||||
|
* src/application/idlescript.cpp (run): Reduced delay until
|
||||||
idlescript.py is called the first time after startup.
|
idlescript.py is called the first time after startup.
|
||||||
|
* src/capisuite-py: Added python library modules.
|
||||||
|
* src/capisuite-py/SConscript: Likewise.
|
||||||
|
* src/capisuite-py/__init__.py: Likewise.
|
||||||
|
* src/capisuite-py/config.py.in: Likewise.
|
||||||
|
* src/capisuite-py/consts.py: Likewise.
|
||||||
|
* src/capisuite-py/core.py: Likewise.
|
||||||
|
* src/capisuite-py/exceptions.py: Likewise.
|
||||||
|
* src/capisuite-py/fax.py: Likewise.
|
||||||
|
* src/capisuite-py/fileutils.py: Likewise.
|
||||||
|
* src/capisuite-py/pychecker.rc: Likewise.
|
||||||
|
* src/capisuite-py/voice.py: Likewise.
|
||||||
|
* scripts/fax.confin: Added sections 'Mail Fax|Voice ...'.
|
||||||
|
* scripts/answering_machine.confin: Likewise.
|
||||||
|
* rc.capisuite.in: Added 'todo' note.
|
||||||
|
* scripts/capisuite-checkconfig: new file (thx to
|
||||||
|
carsten@capimin.cbclass.net for the idea and a first version).
|
||||||
|
* scripts/cs_helper.pyin: Changed to use new python library.
|
||||||
|
* scripts/capisuitefax.in: Reworked to use new python library.
|
||||||
|
* scripts/idle.py: Likewise.
|
||||||
|
* scripts/incoming.py: Likewise.
|
||||||
|
* scripts/remote-connect.py: Likewise.
|
||||||
|
* ChangeLog, TODO, AUTHORS: updated.
|
||||||
|
|
||||||
2004-03-07 Gernot Hillier <gernot@hillier.de>
|
2004-03-07 Gernot Hillier <gernot@hillier.de>
|
||||||
* docs/manual.docbook: update links to new web site structure
|
* docs/manual.docbook: update links to new web site structure
|
||||||
|
@ -69,7 +172,7 @@
|
||||||
confused the config file parser when not deleted by the user
|
confused the config file parser when not deleted by the user
|
||||||
* scripts/fax.confin: Likewise.
|
* scripts/fax.confin: Likewise.
|
||||||
|
|
||||||
2004-02-20 Hartmut Goebel <h.goeben@goebel-consult.de>
|
2004-02-20 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
* docs/Doxyfile.in: modified variable replacement for possible
|
* docs/Doxyfile.in: modified variable replacement for possible
|
||||||
change of build system
|
change of build system
|
||||||
* docs/Makefile.am: Likewise.
|
* docs/Makefile.am: Likewise.
|
||||||
|
@ -216,13 +319,13 @@
|
||||||
2003-10-19 Gernot Hillier <gernot@hillier.de>
|
2003-10-19 Gernot Hillier <gernot@hillier.de>
|
||||||
|
|
||||||
* docs/manual.docbook (creating_alaw): add note how to convert vbox
|
* docs/manual.docbook (creating_alaw): add note how to convert vbox
|
||||||
to inversed A-Law files (thx to Thomas Niesel)
|
to inversed A-Law files (thx to Thomas Niesel)
|
||||||
* docs/manual-de.docbook (creating_alaw): see above
|
* docs/manual-de.docbook (creating_alaw): see above
|
||||||
* docs/manual.docbook (require_soft): updated link to jpeg2ps (thx to
|
* docs/manual.docbook (require_soft): updated link to jpeg2ps (thx to
|
||||||
Achim Bohnet)
|
Achim Bohnet)
|
||||||
* docs/manual-de.docbook (require_soft): see above
|
* docs/manual-de.docbook (require_soft): see above
|
||||||
* scripts/cs_helpers.pyin (sendMIMEMail): better wording for some error
|
* scripts/cs_helpers.pyin (sendMIMEMail): better wording for some error
|
||||||
messages
|
messages
|
||||||
|
|
||||||
2003-10-05 Gernot Hillier <gernot@hillier.de>
|
2003-10-05 Gernot Hillier <gernot@hillier.de>
|
||||||
|
|
||||||
|
|
58
Makefile.in
58
Makefile.in
|
@ -1,4 +1,4 @@
|
||||||
# Makefile.in generated by automake 1.8.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.1 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
@ -38,7 +38,7 @@ subdir = .
|
||||||
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
||||||
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||||
$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
|
$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
|
||||||
TODO depcomp install-sh missing mkinstalldirs
|
TODO depcomp install-sh missing mkinstalldirs py-compile
|
||||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||||
$(top_srcdir)/configure.in
|
$(top_srcdir)/configure.in
|
||||||
|
@ -57,6 +57,12 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||||
install-recursive installcheck-recursive installdirs-recursive \
|
install-recursive installcheck-recursive installdirs-recursive \
|
||||||
pdf-recursive ps-recursive uninstall-info-recursive \
|
pdf-recursive ps-recursive uninstall-info-recursive \
|
||||||
uninstall-recursive
|
uninstall-recursive
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||||
am__installdirs = "$(DESTDIR)$(docdir)"
|
am__installdirs = "$(DESTDIR)$(docdir)"
|
||||||
docDATA_INSTALL = $(INSTALL_DATA)
|
docDATA_INSTALL = $(INSTALL_DATA)
|
||||||
DATA = $(doc_DATA)
|
DATA = $(doc_DATA)
|
||||||
|
@ -136,6 +142,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
am__leading_dot = @am__leading_dot@
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
bindir = @bindir@
|
bindir = @bindir@
|
||||||
build_alias = @build_alias@
|
build_alias = @build_alias@
|
||||||
datadir = @datadir@
|
datadir = @datadir@
|
||||||
|
@ -235,7 +243,7 @@ install-docDATA: $(doc_DATA)
|
||||||
test -z "$(docdir)" || $(mkdir_p) "$(DESTDIR)$(docdir)"
|
test -z "$(docdir)" || $(mkdir_p) "$(DESTDIR)$(docdir)"
|
||||||
@list='$(doc_DATA)'; for p in $$list; do \
|
@list='$(doc_DATA)'; for p in $$list; do \
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " $(docDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(docdir)/$$f'"; \
|
echo " $(docDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(docdir)/$$f'"; \
|
||||||
$(docDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(docdir)/$$f"; \
|
$(docDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(docdir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -243,7 +251,7 @@ install-docDATA: $(doc_DATA)
|
||||||
uninstall-docDATA:
|
uninstall-docDATA:
|
||||||
@$(NORMAL_UNINSTALL)
|
@$(NORMAL_UNINSTALL)
|
||||||
@list='$(doc_DATA)'; for p in $$list; do \
|
@list='$(doc_DATA)'; for p in $$list; do \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " rm -f '$(DESTDIR)$(docdir)/$$f'"; \
|
echo " rm -f '$(DESTDIR)$(docdir)/$$f'"; \
|
||||||
rm -f "$(DESTDIR)$(docdir)/$$f"; \
|
rm -f "$(DESTDIR)$(docdir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -321,14 +329,16 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
tags=; \
|
tags=; \
|
||||||
here=`pwd`; \
|
here=`pwd`; \
|
||||||
if (etags --etags-include --version) >/dev/null 2>&1; then \
|
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||||
include_option=--etags-include; \
|
include_option=--etags-include; \
|
||||||
|
empty_fix=.; \
|
||||||
else \
|
else \
|
||||||
include_option=--include; \
|
include_option=--include; \
|
||||||
|
empty_fix=; \
|
||||||
fi; \
|
fi; \
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
if test "$$subdir" = .; then :; else \
|
if test "$$subdir" = .; then :; else \
|
||||||
test -f $$subdir/TAGS && \
|
test ! -f $$subdir/TAGS || \
|
||||||
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
||||||
fi; \
|
fi; \
|
||||||
done; \
|
done; \
|
||||||
|
@ -338,9 +348,11 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
||||||
done | \
|
done | \
|
||||||
$(AWK) ' { files[$$0] = 1; } \
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
END { for (i in files) print i; }'`; \
|
END { for (i in files) print i; }'`; \
|
||||||
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||||
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
$$tags $$unique
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$tags $$unique; \
|
||||||
|
fi
|
||||||
ctags: CTAGS
|
ctags: CTAGS
|
||||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
|
@ -393,15 +405,17 @@ distdir: $(DISTFILES)
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
done
|
done
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||||
if test "$$subdir" = .; then :; else \
|
if test "$$subdir" = .; then :; else \
|
||||||
test -d "$(distdir)/$$subdir" \
|
test -d "$(distdir)/$$subdir" \
|
||||||
|| mkdir "$(distdir)/$$subdir" \
|
|| $(mkdir_p) "$(distdir)/$$subdir" \
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
|
distdir=`$(am__cd) $(distdir) && pwd`; \
|
||||||
|
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
|
||||||
(cd $$subdir && \
|
(cd $$subdir && \
|
||||||
$(MAKE) $(AM_MAKEFLAGS) \
|
$(MAKE) $(AM_MAKEFLAGS) \
|
||||||
top_distdir="../$(top_distdir)" \
|
top_distdir="$$top_distdir" \
|
||||||
distdir="../$(distdir)/$$subdir" \
|
distdir="$$distdir/$$subdir" \
|
||||||
distdir) \
|
distdir) \
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
|
@ -412,15 +426,15 @@ distdir: $(DISTFILES)
|
||||||
! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
|
! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
|
||||||
|| chmod -R a+r $(distdir)
|
|| chmod -R a+r $(distdir)
|
||||||
dist-gzip: distdir
|
dist-gzip: distdir
|
||||||
$(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||||
$(am__remove_distdir)
|
$(am__remove_distdir)
|
||||||
|
|
||||||
dist-bzip2: distdir
|
dist-bzip2: distdir
|
||||||
$(AMTAR) chof - $(distdir) | bzip2 -9 -c >$(distdir).tar.bz2
|
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
|
||||||
$(am__remove_distdir)
|
$(am__remove_distdir)
|
||||||
|
|
||||||
dist-tarZ: distdir
|
dist-tarZ: distdir
|
||||||
$(AMTAR) chof - $(distdir) | compress -c >$(distdir).tar.Z
|
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||||
$(am__remove_distdir)
|
$(am__remove_distdir)
|
||||||
|
|
||||||
dist-shar: distdir
|
dist-shar: distdir
|
||||||
|
@ -433,7 +447,7 @@ dist-zip: distdir
|
||||||
$(am__remove_distdir)
|
$(am__remove_distdir)
|
||||||
|
|
||||||
dist dist-all: distdir
|
dist dist-all: distdir
|
||||||
$(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||||
$(am__remove_distdir)
|
$(am__remove_distdir)
|
||||||
|
|
||||||
# This target untars the dist file and tries a VPATH configuration. Then
|
# This target untars the dist file and tries a VPATH configuration. Then
|
||||||
|
@ -442,13 +456,13 @@ dist dist-all: distdir
|
||||||
distcheck: dist
|
distcheck: dist
|
||||||
case '$(DIST_ARCHIVES)' in \
|
case '$(DIST_ARCHIVES)' in \
|
||||||
*.tar.gz*) \
|
*.tar.gz*) \
|
||||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - ;;\
|
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
|
||||||
*.tar.bz2*) \
|
*.tar.bz2*) \
|
||||||
bunzip2 -c $(distdir).tar.bz2 | $(AMTAR) xf - ;;\
|
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||||
*.tar.Z*) \
|
*.tar.Z*) \
|
||||||
uncompress -c $(distdir).tar.Z | $(AMTAR) xf - ;;\
|
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||||
*.shar.gz*) \
|
*.shar.gz*) \
|
||||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | unshar ;;\
|
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
|
||||||
*.zip*) \
|
*.zip*) \
|
||||||
unzip $(distdir).zip ;;\
|
unzip $(distdir).zip ;;\
|
||||||
esac
|
esac
|
||||||
|
@ -530,7 +544,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
|
25
NEWS
25
NEWS
|
@ -1,6 +1,11 @@
|
||||||
0.5 (CVS nn):
|
0.5 (CVS nn):
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
* scripts: removed the special support for giving an empty voice_email/
|
||||||
|
fax_email parameter. This is NOT allowed any more and will result in
|
||||||
|
an error when sending the mail. Simply don't set these parameters
|
||||||
|
any more if you don't need them!
|
||||||
|
|
||||||
* core: use shorter, more readable format for Python traceback logging
|
* core: use shorter, more readable format for Python traceback logging
|
||||||
|
|
||||||
* documentation: 5 man pages are now also created: capisuite(8),
|
* documentation: 5 man pages are now also created: capisuite(8),
|
||||||
|
@ -13,6 +18,22 @@
|
||||||
* scripts: capisuitefax now also accepts PDF files (thx to Jochen Meyer
|
* scripts: capisuitefax now also accepts PDF files (thx to Jochen Meyer
|
||||||
and Eckhard Rüggeberg for reporting)
|
and Eckhard Rüggeberg for reporting)
|
||||||
|
|
||||||
|
* scripts: capisuitefax now submits a single job if several
|
||||||
|
files are given (implemented by Hartmut Goebel, fixes bug #38)
|
||||||
|
|
||||||
|
* scripts: New script capisuite-checkconfig for checking the
|
||||||
|
configuration (thx to carsten@capimin.cbclass.net for the
|
||||||
|
idea and a first version, improved by Hartmut Goebel).
|
||||||
|
|
||||||
|
* core: major refactoring of the Python based interface has
|
||||||
|
been done. Now a complete new Python module library
|
||||||
|
implements a lot of useful functions and offers handy
|
||||||
|
abstractions. (planned and implemented by Hartmut Goebel)
|
||||||
|
|
||||||
|
* scripts: the mails sent can now be configured in the special sections
|
||||||
|
MailFaxReceived, MailFaxSent, MailFaxFailed and MailVoiceReceived in
|
||||||
|
answering_machine.conf and fax.conf (implemented by Hartmut Goebel)
|
||||||
|
|
||||||
* core: fixed a bug which could lead to a crash when some unexpected
|
* core: fixed a bug which could lead to a crash when some unexpected
|
||||||
CAPI messages arrived (thx to Karsten Keil for analyzing)
|
CAPI messages arrived (thx to Karsten Keil for analyzing)
|
||||||
|
|
||||||
|
@ -42,8 +63,8 @@
|
||||||
should only contain important changes from a user's point of view, while
|
should only contain important changes from a user's point of view, while
|
||||||
ChangeLog records all changes in detail.
|
ChangeLog records all changes in detail.
|
||||||
|
|
||||||
0.4.4 (CVS tag NN):
|
0.4.4
|
||||||
===================
|
=====
|
||||||
|
|
||||||
* Makefiles: fixed "make" to not trying to create directories any more -
|
* Makefiles: fixed "make" to not trying to create directories any more -
|
||||||
this prevented normal users to call "make" sometimes (thx to Steffen
|
this prevented normal users to call "make" sometimes (thx to Steffen
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
# build top level files
|
||||||
|
# this is a SConscript, too, to support really build-dirs
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
cronfile = env.FileSubst('capisuite.cron', 'capisuite.cronin')
|
||||||
|
rcfile = env.FileSubst('rc.capisuite', 'rc.capisuite.in')
|
||||||
|
env.AddPostAction([cronfile, rcfile], 'chmod gu+x $TARGET')
|
||||||
|
|
||||||
|
Alias('install',
|
||||||
|
env.Install('$docdir', Split('COPYING NEWS README')),
|
||||||
|
env.Install('$sysconfdir/init.d/capisuite', rcfile),
|
||||||
|
env.InstallAs('$sysconfdir/cron.daily/capisuite', cronfile),
|
||||||
|
env.InstallAs('$pkgsysconfdir/cronjob.conf','cronjob.conf'),
|
||||||
|
)
|
|
@ -0,0 +1,192 @@
|
||||||
|
# -*- python -*-
|
||||||
|
"""
|
||||||
|
Check the build environment for CapiSuite
|
||||||
|
|
||||||
|
(c) Copyright 2004 by Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
|
"""
|
||||||
|
|
||||||
|
Import(['env'])
|
||||||
|
|
||||||
|
headerfilename = 'config.h'
|
||||||
|
havedict = {}
|
||||||
|
|
||||||
|
open(headerfilename, 'w') # clear file contents
|
||||||
|
|
||||||
|
###--- hack SCons.SConftest ---###
|
||||||
|
|
||||||
|
import SCons.Conftest, string
|
||||||
|
from types import IntType
|
||||||
|
def _Have(context, key, have):
|
||||||
|
"""
|
||||||
|
Slightly modified version of SCons.Conftest._Have which uses
|
||||||
|
global havedict and headerfilename instead of context.*. This is
|
||||||
|
necessary until SCons support a way to actually use this feature.
|
||||||
|
In addition this writes '#define ... 1'.
|
||||||
|
"""
|
||||||
|
key_up = string.upper(key)
|
||||||
|
key_up = string.replace(key_up, ':', '_')
|
||||||
|
key_up = string.replace(key_up, '.', '_')
|
||||||
|
key_up = string.replace(key_up, '/', '_')
|
||||||
|
key_up = string.replace(key_up, ' ', '_')
|
||||||
|
havedict[key_up] = have
|
||||||
|
if headerfilename:
|
||||||
|
f = open(headerfilename, "a")
|
||||||
|
if have == 1:
|
||||||
|
f.write("#define %s 1\n" % key_up)
|
||||||
|
elif have == 0:
|
||||||
|
f.write("/* #undef %s */\n" % key_up)
|
||||||
|
elif type(have) == IntType:
|
||||||
|
f.write("#define %s %d\n" % (key_up, have))
|
||||||
|
else:
|
||||||
|
f.write('#define %s "%s"\n' % (key_up, str(have)))
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# need to monkey-patch it into SCons.Conftest :-(
|
||||||
|
SCons.Conftest._Have = _Have
|
||||||
|
|
||||||
|
_Have(None, 'PACKAGE', env['PACKAGE'])
|
||||||
|
_Have(None, 'VERSION', env['VERSION'])
|
||||||
|
|
||||||
|
## these were defined by auto-rools but are unused:
|
||||||
|
## #define PACKAGE_BUGREPORT ""
|
||||||
|
## #define PACKAGE_NAME ""
|
||||||
|
## #define PACKAGE_STRING ""
|
||||||
|
## #define PACKAGE_TARNAME ""
|
||||||
|
## #define PACKAGE_VERSION ""
|
||||||
|
|
||||||
|
###--- autoconf-like checks ---###
|
||||||
|
### these tests are build like the corresponding autoconf tests
|
||||||
|
|
||||||
|
def CheckHeadersStdC(context):
|
||||||
|
context.Message("Checking for ANSI C header files ... ")
|
||||||
|
text = """
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <float.h>
|
||||||
|
\n"""
|
||||||
|
# Some tests for SunOS 4.x, ISC 2.0.2 and Irix-4.0.5 skipped here,
|
||||||
|
# since CapiSuite requires Linux anway.
|
||||||
|
ret = context.CompileProg(text, '.cpp')
|
||||||
|
SCons.Conftest._YesNoResult(context, ret, "STDC_HEADERS", text)
|
||||||
|
context.did_show_result = 1
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def CheckHeaderTime(context):
|
||||||
|
context.Display("Checking whether time.h and sys/time.h may both be "
|
||||||
|
"included ... ")
|
||||||
|
text = """
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
if ((struct tm *) 0) return 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
\n"""
|
||||||
|
ret = context.CompileProg(text, '.cpp')
|
||||||
|
SCons.Conftest._YesNoResult(context, ret, "TIME_WITH_SYS_TIME", text)
|
||||||
|
context.did_show_result = 1
|
||||||
|
return ret
|
||||||
|
|
||||||
|
###--- custom checks for CapiSuite ---###
|
||||||
|
|
||||||
|
def CheckStringClear(context):
|
||||||
|
context.Display('Checking for string::clear method ... ')
|
||||||
|
text = """
|
||||||
|
#include <string>
|
||||||
|
int main() {
|
||||||
|
std::string a; a.clear();
|
||||||
|
}
|
||||||
|
\n"""
|
||||||
|
ret = context.CompileProg(text, '.cpp')
|
||||||
|
SCons.Conftest._YesNoResult(context, ret, "HAVE_STRING_CLEAR", text)
|
||||||
|
context.did_show_result = 1
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
conf = Configure(env,
|
||||||
|
custom_tests = {'CheckHeadersStdC': CheckHeadersStdC,
|
||||||
|
'CheckHeaderTime': CheckHeaderTime,
|
||||||
|
'CheckStringClear': CheckStringClear,
|
||||||
|
},
|
||||||
|
conf_dir = '.sconf_temp', # no '#' to build in build-dir
|
||||||
|
log_file = 'config.log' # no '#' to build in build-dir
|
||||||
|
)
|
||||||
|
|
||||||
|
conf.CheckHeadersStdC()
|
||||||
|
|
||||||
|
missing = 0
|
||||||
|
for h in Split("sys/types.h sys/stat.h stdlib.h string.h "
|
||||||
|
"memory.h strings.h inttypes.h stdint.h unistd.h"):
|
||||||
|
missing += not conf.CheckHeader(h, language='C++')
|
||||||
|
if missing:
|
||||||
|
print 'Required headers missing - aborting.'
|
||||||
|
Exit(5)
|
||||||
|
|
||||||
|
conf.CheckFunc('gettimeofday', language='C++')
|
||||||
|
conf.CheckHeader('sys/time.h', language='C++')
|
||||||
|
conf.CheckHeaderTime()
|
||||||
|
|
||||||
|
###--- CapiSuite specials ---###
|
||||||
|
|
||||||
|
# new gcc3 feature: we can #include<ostream> instead of ostream.h
|
||||||
|
conf.CheckHeader('ostream', language='C++')
|
||||||
|
conf.CheckStringClear() # checking for string::clear method
|
||||||
|
|
||||||
|
|
||||||
|
###--- libs required by CapiSuite ---###
|
||||||
|
|
||||||
|
# checking for capi20_register in -lcapi20... yes
|
||||||
|
if not conf.CheckLib('capi20', 'capi20_register', language='C++'):
|
||||||
|
print 'libcapi not found - aborting'
|
||||||
|
Exit(5)
|
||||||
|
|
||||||
|
# checking for pthread_create in -lpthread... yes
|
||||||
|
if not conf.CheckLib('pthread', 'pthread_create', language='C++'):
|
||||||
|
print 'lipthread not found - aborting'
|
||||||
|
Exit(5)
|
||||||
|
|
||||||
|
# todo
|
||||||
|
# Which(doxygen)
|
||||||
|
# Which(pychecker)
|
||||||
|
|
||||||
|
conf.Finish()
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
These are the checks 'configure' does
|
||||||
|
|
||||||
|
Legende:
|
||||||
|
- not neccessary
|
||||||
|
+ Scons build-in
|
||||||
|
? unsure
|
||||||
|
~ implemented in SConscript/SConstruct
|
||||||
|
|
||||||
|
-checking for a BSD-compatible install... /usr//bin/install -c
|
||||||
|
-checking whether build environment is sane... yes
|
||||||
|
-checking for gawk... gawk
|
||||||
|
-checking whether make sets $(MAKE)... yes
|
||||||
|
+checking for gcc... gcc
|
||||||
|
+checking for C compiler default output... a.out
|
||||||
|
+checking whether the C compiler works... yes
|
||||||
|
?checking whether we are cross compiling... no
|
||||||
|
+checking for suffix of executables...
|
||||||
|
+checking for suffix of object files... o
|
||||||
|
?checking whether we are using the GNU C compiler... yes
|
||||||
|
?checking whether gcc accepts -g... yes
|
||||||
|
?checking for gcc option to accept ANSI C... none needed
|
||||||
|
-checking for style of include used by make... GNU
|
||||||
|
-checking dependency style of gcc... gcc3
|
||||||
|
|
||||||
|
+checking for g++... g++
|
||||||
|
checking whether we are using the GNU C++ compiler... yes
|
||||||
|
checking whether g++ accepts -g... yes
|
||||||
|
-checking dependency style of g++... gcc3
|
||||||
|
-checking for a BSD-compatible install... /usr//bin/install -c
|
||||||
|
+checking for ranlib... ranlib
|
||||||
|
-checking whether make sets $(MAKE)... (cached) yes
|
||||||
|
+checking how to run the C++ preprocessor... g++ -E
|
||||||
|
-checking for egrep... grep -E
|
||||||
|
"""
|
|
@ -0,0 +1,43 @@
|
||||||
|
# -*- python -*-
|
||||||
|
"""
|
||||||
|
Options for building CapiSuite
|
||||||
|
|
||||||
|
(c) Copyright 2004 by Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
|
"""
|
||||||
|
|
||||||
|
# default prefix
|
||||||
|
prefix = '/usr/local'
|
||||||
|
oldincludedir = '/usr/include'
|
||||||
|
|
||||||
|
opts = Options('options.cache', ARGUMENTS)
|
||||||
|
opts.AddOptions(
|
||||||
|
# Installation directories:
|
||||||
|
('prefix', 'install architecture-independent files in prefix', prefix),
|
||||||
|
('execprefix','install architecture-dependent files in execprefix','$prefix'),
|
||||||
|
|
||||||
|
# Fine tuning of the installation directories:
|
||||||
|
('bindir', 'user executables', '$execprefix/bin'),
|
||||||
|
('sbindir', 'system admin executables', '$execprefix/sbin'),
|
||||||
|
('libexecdir', 'program executables', '$execprefix/libexec'),
|
||||||
|
('datadir', 'read-only architecture-independent data','$prefix/share'),
|
||||||
|
('sysconfdir', 'read-only single-machine data', '$prefix/etc',),
|
||||||
|
('sharedstatedir','modifiable architecture-independent data','$prefix/com',),
|
||||||
|
('localstatedir', 'modifiable single-machine data', '$prefix/var'),
|
||||||
|
('libdir', 'object code libraries', '$execprefix/lib'),
|
||||||
|
('includedir', 'C header files', '$prefix/include'),
|
||||||
|
('oldincludedir', 'C header files for non-gcc', oldincludedir),
|
||||||
|
('infodir', 'info documentation', '$prefix/info'),
|
||||||
|
('mandir', 'man documentation', '$prefix/man'),
|
||||||
|
|
||||||
|
# install into another filesystem base
|
||||||
|
('INSTALL_BASE', 'base dir for installation (userfull for RPMs)',
|
||||||
|
'#/dist'),
|
||||||
|
|
||||||
|
# this is a capisuite-special
|
||||||
|
('docdir', 'other documentation', '$datadir/doc/capisuite'),
|
||||||
|
)
|
||||||
|
|
||||||
|
Import(['env', '__targets__'])
|
||||||
|
opts.Update(env)
|
||||||
|
Help(opts.GenerateHelpText(env) + __targets__)
|
||||||
|
opts.Save('options.cache', env)
|
|
@ -0,0 +1,246 @@
|
||||||
|
# -*- python -*-
|
||||||
|
"""
|
||||||
|
Main SCons build script for CapiSuite
|
||||||
|
|
||||||
|
(c) Copyright 2004 by Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
|
|
||||||
|
CapiSuite is (c) Copyright by Gernot Hiller <gernot@hiller.de>
|
||||||
|
|
||||||
|
Use 'scons --help' for a list of available options.
|
||||||
|
|
||||||
|
Options have only to be given once, since they are cached in a file
|
||||||
|
'options.cache'. To change an option, simply pass it again with a
|
||||||
|
different value.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
scons prefix=/ # build for prefix=/
|
||||||
|
scons # prefix=/ is taken from 'options.cache'
|
||||||
|
scons prefix=/usr/local # build for prefix=/usr/local
|
||||||
|
# since this is the default, the entry in options.cache
|
||||||
|
# will be renmoved
|
||||||
|
scons # default prefix is used
|
||||||
|
"""
|
||||||
|
|
||||||
|
__targets__ = """
|
||||||
|
Additional targets:
|
||||||
|
configure : build the 'configure' script
|
||||||
|
(this is automatically done if 'config.h' is missing)
|
||||||
|
pycheck : check Python sources with PyChecker (not yet implemented)
|
||||||
|
|
||||||
|
install : install all files
|
||||||
|
install-pylib : install only the python library
|
||||||
|
install-scripts : install only the python scripts
|
||||||
|
install-exec : install only the executables
|
||||||
|
|
||||||
|
For all install-targets base may be set with INSTALL_BASE=...
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
# File-Content Substitution will (hopefully ) be part of SCons 0.95
|
||||||
|
def _file_subst(target, source, env):
|
||||||
|
import os, re
|
||||||
|
import SCons.Util
|
||||||
|
|
||||||
|
def _substitute(matchobj, env=env):
|
||||||
|
sym = matchobj.group(1)
|
||||||
|
try:
|
||||||
|
return env.subst(str(env[sym]))
|
||||||
|
except: # TypeError: # sym not a string
|
||||||
|
print 'Not substituting', sym
|
||||||
|
return matchobj.group(0) # matched
|
||||||
|
|
||||||
|
delim = re.escape(env.get('SUBST_DELIM', '@'))
|
||||||
|
subst_pattern = re.compile('%s(.*?)%s' % (delim, delim))
|
||||||
|
for t, s in zip(target, source):
|
||||||
|
t = str(t)
|
||||||
|
s = s.rstr()
|
||||||
|
text = open(s, 'rb').read()
|
||||||
|
text = subst_pattern.sub(_substitute, text)
|
||||||
|
open(t, 'wb').write(text)
|
||||||
|
os.chmod(t, os.stat(s)[0])
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _fs_strfunc(target, source, env):
|
||||||
|
return "generating '%s' from '%s'" % (target[0], source[0])
|
||||||
|
|
||||||
|
_fs_builder = Builder(action = Action(_file_subst, strfunction = _fs_strfunc))
|
||||||
|
|
||||||
|
import sys, os, os.path
|
||||||
|
import SCons.Util
|
||||||
|
import SCons.Node.FS
|
||||||
|
|
||||||
|
EnsurePythonVersion(2,2) # capisuite requires this
|
||||||
|
#EnsureSConsVersion(0,94)
|
||||||
|
|
||||||
|
build_dir = Dir('#/build')
|
||||||
|
|
||||||
|
class InstallableEnv(Environment):
|
||||||
|
def Install(self, dir, source):
|
||||||
|
"""Install specified files in the given directory."""
|
||||||
|
if self.has_key('INSTALL_BASE'):
|
||||||
|
def _Dir(name):
|
||||||
|
return SCons.Node.FS.Dir(name, parent, self.fs)
|
||||||
|
parent = self['INSTALL_BASE']
|
||||||
|
dir = self.arg2nodes(dir, _Dir)
|
||||||
|
return Environment.Install(self, dir, source)
|
||||||
|
|
||||||
|
def InstallAs(self, target, source):
|
||||||
|
"""Install sources as targets."""
|
||||||
|
def _File(name):
|
||||||
|
return SCons.Node.FS.File(name, dir, self.fs)
|
||||||
|
|
||||||
|
if self.has_key('INSTALL_BASE'):
|
||||||
|
dir = self['INSTALL_BASE']
|
||||||
|
targets = self.arg2nodes(target, _File)
|
||||||
|
return Environment.InstallAs(self, target, source)
|
||||||
|
|
||||||
|
env = InstallableEnv()
|
||||||
|
env.Append(
|
||||||
|
BUILDERS={'FileSubst' : _fs_builder},
|
||||||
|
PACKAGE = 'capisuite',
|
||||||
|
VERSION = '0.5.cvs',
|
||||||
|
srcdir = build_dir,
|
||||||
|
|
||||||
|
pkgdatadir = '${datadir}/${PACKAGE}',
|
||||||
|
pkglibdir = '${libdir}/${PACKAGE}',
|
||||||
|
pkgincludedir = '${includedir}/${PACKAGE}',
|
||||||
|
|
||||||
|
pkgbindir = '${bindir}',
|
||||||
|
pkgsbindir = '${sbindir}',
|
||||||
|
pkgsysconfdir = '${sysconfdir}/${PACKAGE}',
|
||||||
|
#pkglibdir = '${prefix}/lib',
|
||||||
|
spooldir = '${localstatedir}/spool/${PACKAGE}',
|
||||||
|
docdir = '${pkgdatadir}/doc/${PACKAGE}',
|
||||||
|
)
|
||||||
|
env.SConscript('SConscript-Options', exports=['env', '__targets__'])
|
||||||
|
|
||||||
|
if env.has_key('INSTALL_BASE'):
|
||||||
|
env.Replace(INSTALL_BASE=env.Dir('$INSTALL_BASE'))
|
||||||
|
Export('env')
|
||||||
|
|
||||||
|
env.BuildDir(build_dir=build_dir, src_dir='.')
|
||||||
|
|
||||||
|
|
||||||
|
###---####---###---####---###---####---###---####---###---####---###---###
|
||||||
|
# call configure if required
|
||||||
|
|
||||||
|
# if config.h does not exist, build it using Scons' conftest
|
||||||
|
if not os.path.exists(str(File('config.h', build_dir))) \
|
||||||
|
or 'configure' in COMMAND_LINE_TARGETS:
|
||||||
|
env.SConscript('SConscript-Config', build_dir=build_dir)
|
||||||
|
|
||||||
|
###---####---###---####---###---####---###---####---###---####---###---###
|
||||||
|
|
||||||
|
def GetPythonModuleSetup(env):
|
||||||
|
"""
|
||||||
|
Get configuration for linking with the Python library.
|
||||||
|
"""
|
||||||
|
import distutils.sysconfig
|
||||||
|
from distutils.sysconfig import get_python_lib, get_config_vars, \
|
||||||
|
get_config_var
|
||||||
|
env.Append(
|
||||||
|
python_version = distutils.sysconfig.get_python_version(),
|
||||||
|
python_prefix = distutils.sysconfig.PREFIX,
|
||||||
|
python_execprefix = distutils.sysconfig.EXEC_PREFIX,
|
||||||
|
python_libdir = get_python_lib(plat_specific=1, standard_lib=1),
|
||||||
|
python_moduledir = get_python_lib(plat_specific=0, standard_lib=0),
|
||||||
|
python_moduleexecdir = get_python_lib(plat_specific=1, standard_lib=0),
|
||||||
|
python_includespec = get_config_vars('INCLUDEPY', 'CONFINCLUDEPY'),
|
||||||
|
python_linkforshared = get_config_var('LINKFORSHARED'),
|
||||||
|
|
||||||
|
pkgpython_moduledir = '${python_moduledir}/${PACKAGE}',
|
||||||
|
pkgpython_moduleexecdir = '${python_moduleexecdir}/${PACKAGE}',
|
||||||
|
|
||||||
|
LINKFLAGS = ['${python_linkforshared}'],
|
||||||
|
LIBS = ['python${python_version}'],
|
||||||
|
)
|
||||||
|
env.Append(
|
||||||
|
CPPPATH = env['python_includespec'],
|
||||||
|
PYTHON = sys.executable,
|
||||||
|
)
|
||||||
|
|
||||||
|
def GetPythonEmbeddedSetup(env):
|
||||||
|
"""
|
||||||
|
Get configuration for linking an embedded Python application.
|
||||||
|
"""
|
||||||
|
# Base idea on which variable to check are from the INN 2.3.1 package
|
||||||
|
import distutils.sysconfig
|
||||||
|
print 'Checking how to link an embedded Python application:',
|
||||||
|
libvars = Split("LIBS LIBC LIBM LOCALMODLIBS BASEMODLIBS")
|
||||||
|
python_libspec = []
|
||||||
|
for libvar in distutils.sysconfig.get_config_vars(*libvars):
|
||||||
|
libvar = libvar.split()
|
||||||
|
for lib in libvar:
|
||||||
|
# sanity check
|
||||||
|
if not lib.startswith('-l'):
|
||||||
|
print "Error in Python Makefile: shared lib spec does ", \
|
||||||
|
"not start with '-l':", lib
|
||||||
|
python_libspec.append(lib[2:])
|
||||||
|
env.Append(python_libspec = python_libspec,
|
||||||
|
python_configdir = distutils.sysconfig.get_config_var('LIBPL'),
|
||||||
|
# preferable these should be '$python..', but SCons
|
||||||
|
# doe not yet support this (SCons 0.94)
|
||||||
|
LIBS = python_libspec,
|
||||||
|
LIBPATH = ['${python_configdir}'],
|
||||||
|
)
|
||||||
|
print ' '.join(python_libspec)
|
||||||
|
#print '>>>', env['LIBS']
|
||||||
|
|
||||||
|
GetPythonModuleSetup(env)
|
||||||
|
GetPythonEmbeddedSetup(env)
|
||||||
|
|
||||||
|
env.Append(
|
||||||
|
CCFLAGS = Split('-g -O2'),
|
||||||
|
LIBS = Split('pthread capi20'),
|
||||||
|
CPPDEFINES={'LOCALSTATEDIR': r'\"${localstatedir}\"',
|
||||||
|
'PKGDATADIR' : r'\"${pkgdatadir}\"',
|
||||||
|
'PKGSYSCONFDIR': r'\"${pkgsysconfdir}\"',
|
||||||
|
'PKGLIBDIR' : r'\"${pkglibdir}\"',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
## # build debug?
|
||||||
|
## if ARGUMENTS.get('debug', 0):
|
||||||
|
## env.Append(CXXFLAGS = ['-g', '-DDEBUG'])
|
||||||
|
## else:
|
||||||
|
## env.Append(CXXFLAGS = ['-O2'])
|
||||||
|
##
|
||||||
|
## if env['CXX'] in ('g++', 'c++'):
|
||||||
|
## env.Append(CXXFLAGS = ['-Wall', '-Wno-non-virtual-dtor'])
|
||||||
|
|
||||||
|
|
||||||
|
###---####---###---####---###---####---###---####---###---####---###---###
|
||||||
|
|
||||||
|
# snippet for unittest
|
||||||
|
#mytest = env.program(...)
|
||||||
|
#Alias( 'unittest', mytest )
|
||||||
|
#Alias( 'all', 'unittest' )
|
||||||
|
#unittetsInstall = env.Install(...)
|
||||||
|
#Alias('unittest', unitteststInstall)
|
||||||
|
|
||||||
|
# now build the subdirectories' stuff
|
||||||
|
env.SConscript(dirs=[Dir('.', build_dir),
|
||||||
|
Dir('src', build_dir),
|
||||||
|
Dir('scripts', build_dir),
|
||||||
|
Dir('scripts/waves', build_dir),
|
||||||
|
Dir('docs', build_dir),
|
||||||
|
])
|
||||||
|
|
||||||
|
#env.SourceCode('.',
|
||||||
|
# env.CVS('pserver:anonymous@cvs.capisuite.berlios.de:/cvsroot/capisuite',
|
||||||
|
# 'capisuite'))
|
||||||
|
|
||||||
|
"""
|
||||||
|
make DESTDIR=$RPM_BUILD_ROOT install
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/usr/sbin
|
||||||
|
|
||||||
|
ln -sf ../../etc/init.d/capisuite $RPM_BUILD_ROOT/usr/sbin/rccapisuite
|
||||||
|
"""
|
||||||
|
#EXTRA_DIST = rc.capisuite.in capisuite.cronin cronjob.conf
|
||||||
|
#install-data-local:
|
||||||
|
# mkdir -p $(DESTDIR)$(localstatedir)/log
|
||||||
|
# $(mkinstalldirs) $(DESTDIR)$(spooldir)/sendq
|
||||||
|
# $(mkinstalldirs) $(DESTDIR)$(spooldir)/done
|
||||||
|
# $(mkinstalldirs) $(DESTDIR)$(spooldir)/failed
|
||||||
|
# $(mkinstalldirs) $(DESTDIR)$(spooldir)/users
|
15
TODO
15
TODO
|
@ -1,4 +1,18 @@
|
||||||
|
Important for 0.5.0/capisuite-py:
|
||||||
|
* Check and fix all 'todo:'s in the python library and scripts.
|
||||||
|
* Update documentation to include
|
||||||
|
- capisuite-checkconfig
|
||||||
|
- the python library modules.
|
||||||
|
- 'Mail Fax|Voice ...' sections in config files
|
||||||
|
* Add update instructions for 0.5.0/capisuite-py
|
||||||
|
- 'Mail Fax|Voice ...' sections in config files
|
||||||
|
- new modulename '_capisuite' (but use capisuite.core instead)
|
||||||
|
* Add option '--is-configured' to capisuite-checkconfig to be used
|
||||||
|
by rc-file.
|
||||||
|
* Add 'scons-local' to distribution.
|
||||||
|
|
||||||
NICE:
|
NICE:
|
||||||
|
- more checks/options for capisuite-checkconfig
|
||||||
- ?valgrind-clean the used libs and Python?
|
- ?valgrind-clean the used libs and Python?
|
||||||
- support more than one send_controller
|
- support more than one send_controller
|
||||||
- don't use 34xx codes, define constants instead and print meaningful messages
|
- don't use 34xx codes, define constants instead and print meaningful messages
|
||||||
|
@ -7,4 +21,3 @@ FUTURE PLANS:
|
||||||
- setuid away from root (problem: chown of recorded file to user)
|
- setuid away from root (problem: chown of recorded file to user)
|
||||||
- test-implement the whole application part in Python
|
- test-implement the whole application part in Python
|
||||||
- rewrite capisuitefax and idle.py to use named socket communication
|
- rewrite capisuitefax and idle.py to use named socket communication
|
||||||
|
|
||||||
|
|
|
@ -309,7 +309,7 @@ ac_includes_default="\
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif"
|
#endif"
|
||||||
|
|
||||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE RANLIB ac_ct_RANLIB doxygen CXXCPP EGREP docdir PYTHON PYTHON_VERSION PYTHON_PREFIX PYTHON_EXEC_PREFIX PYTHON_PLATFORM pythondir pkgpythondir pyexecdir pkgpyexecdir python_version python_prefix python_execprefix python_configdir python_moduledir python_moduleexecdir python_includespec python_linkforshared LIBOBJS LTLIBOBJS'
|
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE RANLIB ac_ct_RANLIB doxygen CXXCPP EGREP docdir PYTHON PYTHON_VERSION PYTHON_PREFIX PYTHON_EXEC_PREFIX PYTHON_PLATFORM pythondir pkgpythondir pyexecdir pkgpyexecdir python_version python_prefix python_execprefix python_configdir python_moduledir python_moduleexecdir python_includespec python_linkforshared LIBOBJS LTLIBOBJS'
|
||||||
ac_subst_files=''
|
ac_subst_files=''
|
||||||
|
|
||||||
# Initialize some variables set by options.
|
# Initialize some variables set by options.
|
||||||
|
@ -1311,7 +1311,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
am__api_version="1.8"
|
am__api_version="1.9"
|
||||||
ac_aux_dir=
|
ac_aux_dir=
|
||||||
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
|
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
|
||||||
if test -f $ac_dir/install-sh; then
|
if test -f $ac_dir/install-sh; then
|
||||||
|
@ -1488,13 +1488,21 @@ echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
|
if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
|
||||||
# Keeping the `.' argument allows $(mkdir_p) to be used without
|
# We used to keeping the `.' as first argument, in order to
|
||||||
# argument. Indeed, we sometimes output rules like
|
# allow $(mkdir_p) to be used without argument. As in
|
||||||
# $(mkdir_p) $(somedir)
|
# $(mkdir_p) $(somedir)
|
||||||
# where $(somedir) is conditionally defined.
|
# where $(somedir) is conditionally defined. However this is wrong
|
||||||
# (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more
|
# for two reasons:
|
||||||
# expensive solution, as it forces Make to start a sub-shell.)
|
# 1. if the package is installed by a user who cannot write `.'
|
||||||
mkdir_p='mkdir -p -- .'
|
# make install will fail,
|
||||||
|
# 2. the above comment should most certainly read
|
||||||
|
# $(mkdir_p) $(DESTDIR)$(somedir)
|
||||||
|
# so it does not work when $(somedir) is undefined and
|
||||||
|
# $(DESTDIR) is not.
|
||||||
|
# To support the latter case, we have to write
|
||||||
|
# test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
|
||||||
|
# so the `.' trick is pointless.
|
||||||
|
mkdir_p='mkdir -p --'
|
||||||
else
|
else
|
||||||
# On NextStep and OpenStep, the `mkdir' command does not
|
# On NextStep and OpenStep, the `mkdir' command does not
|
||||||
# recognize any option. It will interpret all options as
|
# recognize any option. It will interpret all options as
|
||||||
|
@ -1638,9 +1646,6 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
|
||||||
|
|
||||||
MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
|
MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
|
||||||
|
|
||||||
|
|
||||||
AMTAR=${AMTAR-"${am_missing_run}tar"}
|
|
||||||
|
|
||||||
install_sh=${install_sh-"$am_aux_dir/install-sh"}
|
install_sh=${install_sh-"$am_aux_dir/install-sh"}
|
||||||
|
|
||||||
# Installed binaries are usually stripped using `strip' when the user
|
# Installed binaries are usually stripped using `strip' when the user
|
||||||
|
@ -1733,6 +1738,13 @@ INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
|
||||||
|
|
||||||
# We need awk for the "check" target. The system "awk" is bad on
|
# We need awk for the "check" target. The system "awk" is bad on
|
||||||
# some platforms.
|
# some platforms.
|
||||||
|
# Always define AMTAR for backward compatibility.
|
||||||
|
|
||||||
|
AMTAR=${AMTAR-"${am_missing_run}tar"}
|
||||||
|
|
||||||
|
am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2811,9 +2823,14 @@ else
|
||||||
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
|
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
|
||||||
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
||||||
# icc doesn't choke on unknown options, it will just issue warnings
|
# icc doesn't choke on unknown options, it will just issue warnings
|
||||||
# (even with -Werror). So we grep stderr for any message
|
# or remarks (even with -Werror). So we grep stderr for any message
|
||||||
# that says an option was ignored.
|
# that says an option was ignored or not supported.
|
||||||
if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else
|
# When given -MP, icc 7.0 and 7.1 complain thusly:
|
||||||
|
# icc: Command line warning: ignoring option '-M'; no argument required
|
||||||
|
# The diagnosis changed in icc 8.0:
|
||||||
|
# icc: Command line remark: option '-MP' not supported
|
||||||
|
if (grep 'ignoring option' conftest.err ||
|
||||||
|
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
|
||||||
am_cv_CC_dependencies_compiler_type=$depmode
|
am_cv_CC_dependencies_compiler_type=$depmode
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
@ -3270,9 +3287,14 @@ else
|
||||||
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
|
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
|
||||||
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
||||||
# icc doesn't choke on unknown options, it will just issue warnings
|
# icc doesn't choke on unknown options, it will just issue warnings
|
||||||
# (even with -Werror). So we grep stderr for any message
|
# or remarks (even with -Werror). So we grep stderr for any message
|
||||||
# that says an option was ignored.
|
# that says an option was ignored or not supported.
|
||||||
if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else
|
# When given -MP, icc 7.0 and 7.1 complain thusly:
|
||||||
|
# icc: Command line warning: ignoring option '-M'; no argument required
|
||||||
|
# The diagnosis changed in icc 8.0:
|
||||||
|
# icc: Command line remark: option '-MP' not supported
|
||||||
|
if (grep 'ignoring option' conftest.err ||
|
||||||
|
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
|
||||||
am_cv_CXX_dependencies_compiler_type=$depmode
|
am_cv_CXX_dependencies_compiler_type=$depmode
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
@ -4692,6 +4714,7 @@ echo "$as_me: error: too old" >&2;}
|
||||||
{ (exit 1); exit 1; }; }
|
{ (exit 1); exit 1; }; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
am_display_PYTHON=$PYTHON
|
||||||
else
|
else
|
||||||
# Otherwise, try each interpreter until we find one that satisfies
|
# Otherwise, try each interpreter until we find one that satisfies
|
||||||
# VERSION.
|
# VERSION.
|
||||||
|
@ -4902,7 +4925,7 @@ echo "${ECHO_T}${python_libspec}" >&6
|
||||||
|
|
||||||
CPPFLAGS='-DLOCALSTATEDIR=\"$(localstatedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" -DPKGSYSCONFDIR=\"$(sysconfdir)/capisuite\" -DPKGLIBDIR=\"$(pkglibdir)\" $(python_includespec)'
|
CPPFLAGS='-DLOCALSTATEDIR=\"$(localstatedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" -DPKGSYSCONFDIR=\"$(sysconfdir)/capisuite\" -DPKGLIBDIR=\"$(pkglibdir)\" $(python_includespec)'
|
||||||
|
|
||||||
ac_config_files="$ac_config_files Makefile src/Makefile src/backend/Makefile src/modules/Makefile src/application/Makefile scripts/Makefile scripts/waves/Makefile docs/Makefile"
|
ac_config_files="$ac_config_files Makefile src/Makefile src/backend/Makefile src/modules/Makefile src/application/Makefile src/capisuite-py/Makefile scripts/Makefile scripts/waves/Makefile docs/Makefile"
|
||||||
cat >confcache <<\_ACEOF
|
cat >confcache <<\_ACEOF
|
||||||
# This file is a shell script that caches the results of configure
|
# This file is a shell script that caches the results of configure
|
||||||
# tests run on this system so they can be shared between configure
|
# tests run on this system so they can be shared between configure
|
||||||
|
@ -5464,6 +5487,7 @@ do
|
||||||
"src/backend/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/backend/Makefile" ;;
|
"src/backend/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/backend/Makefile" ;;
|
||||||
"src/modules/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/modules/Makefile" ;;
|
"src/modules/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/modules/Makefile" ;;
|
||||||
"src/application/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/application/Makefile" ;;
|
"src/application/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/application/Makefile" ;;
|
||||||
|
"src/capisuite-py/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/capisuite-py/Makefile" ;;
|
||||||
"scripts/Makefile" ) CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
|
"scripts/Makefile" ) CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
|
||||||
"scripts/waves/Makefile" ) CONFIG_FILES="$CONFIG_FILES scripts/waves/Makefile" ;;
|
"scripts/waves/Makefile" ) CONFIG_FILES="$CONFIG_FILES scripts/waves/Makefile" ;;
|
||||||
"docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;;
|
"docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;;
|
||||||
|
@ -5565,7 +5589,6 @@ s,@AUTOCONF@,$AUTOCONF,;t t
|
||||||
s,@AUTOMAKE@,$AUTOMAKE,;t t
|
s,@AUTOMAKE@,$AUTOMAKE,;t t
|
||||||
s,@AUTOHEADER@,$AUTOHEADER,;t t
|
s,@AUTOHEADER@,$AUTOHEADER,;t t
|
||||||
s,@MAKEINFO@,$MAKEINFO,;t t
|
s,@MAKEINFO@,$MAKEINFO,;t t
|
||||||
s,@AMTAR@,$AMTAR,;t t
|
|
||||||
s,@install_sh@,$install_sh,;t t
|
s,@install_sh@,$install_sh,;t t
|
||||||
s,@STRIP@,$STRIP,;t t
|
s,@STRIP@,$STRIP,;t t
|
||||||
s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
|
s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
|
||||||
|
@ -5574,6 +5597,9 @@ s,@mkdir_p@,$mkdir_p,;t t
|
||||||
s,@AWK@,$AWK,;t t
|
s,@AWK@,$AWK,;t t
|
||||||
s,@SET_MAKE@,$SET_MAKE,;t t
|
s,@SET_MAKE@,$SET_MAKE,;t t
|
||||||
s,@am__leading_dot@,$am__leading_dot,;t t
|
s,@am__leading_dot@,$am__leading_dot,;t t
|
||||||
|
s,@AMTAR@,$AMTAR,;t t
|
||||||
|
s,@am__tar@,$am__tar,;t t
|
||||||
|
s,@am__untar@,$am__untar,;t t
|
||||||
s,@CC@,$CC,;t t
|
s,@CC@,$CC,;t t
|
||||||
s,@CFLAGS@,$CFLAGS,;t t
|
s,@CFLAGS@,$CFLAGS,;t t
|
||||||
s,@LDFLAGS@,$LDFLAGS,;t t
|
s,@LDFLAGS@,$LDFLAGS,;t t
|
||||||
|
@ -6243,27 +6269,21 @@ echo X"$mf" |
|
||||||
else
|
else
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue
|
# Extract the definition of DEPDIR, am__include, and am__quote
|
||||||
# Extract the definition of DEP_FILES from the Makefile without
|
# from the Makefile without running `make'.
|
||||||
# running `make'.
|
|
||||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
||||||
test -z "$DEPDIR" && continue
|
test -z "$DEPDIR" && continue
|
||||||
|
am__include=`sed -n 's/^am__include = //p' < "$mf"`
|
||||||
|
test -z "am__include" && continue
|
||||||
|
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
|
||||||
# When using ansi2knr, U may be empty or an underscore; expand it
|
# When using ansi2knr, U may be empty or an underscore; expand it
|
||||||
U=`sed -n 's/^U = //p' < "$mf"`
|
U=`sed -n 's/^U = //p' < "$mf"`
|
||||||
test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR"
|
# Find all dependency output files, they are included files with
|
||||||
# We invoke sed twice because it is the simplest approach to
|
# $(DEPDIR) in their names. We invoke sed twice because it is the
|
||||||
# changing $(DEPDIR) to its actual value in the expansion.
|
# simplest approach to changing $(DEPDIR) to its actual value in the
|
||||||
for file in `sed -n '
|
# expansion.
|
||||||
/^DEP_FILES = .*\\\\$/ {
|
for file in `sed -n "
|
||||||
s/^DEP_FILES = //
|
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
|
||||||
:loop
|
|
||||||
s/\\\\$//
|
|
||||||
p
|
|
||||||
n
|
|
||||||
/\\\\$/ b loop
|
|
||||||
p
|
|
||||||
}
|
|
||||||
/^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \
|
|
||||||
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
|
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
|
||||||
# Make sure the directory exists.
|
# Make sure the directory exists.
|
||||||
test -f "$dirpart/$file" && continue
|
test -f "$dirpart/$file" && continue
|
||||||
|
|
|
@ -26,4 +26,4 @@ AM_PATH_PYTHON(2.2)
|
||||||
PGAC_CHECK_PYTHON_EMBED_SETUP
|
PGAC_CHECK_PYTHON_EMBED_SETUP
|
||||||
CPPFLAGS='-DLOCALSTATEDIR=\"$(localstatedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" -DPKGSYSCONFDIR=\"$(sysconfdir)/capisuite\" -DPKGLIBDIR=\"$(pkglibdir)\" $(python_includespec)'
|
CPPFLAGS='-DLOCALSTATEDIR=\"$(localstatedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" -DPKGSYSCONFDIR=\"$(sysconfdir)/capisuite\" -DPKGLIBDIR=\"$(pkglibdir)\" $(python_includespec)'
|
||||||
|
|
||||||
AC_OUTPUT(Makefile src/Makefile src/backend/Makefile src/modules/Makefile src/application/Makefile scripts/Makefile scripts/waves/Makefile docs/Makefile)
|
AC_OUTPUT(Makefile src/Makefile src/backend/Makefile src/modules/Makefile src/application/Makefile src/capisuite-py/Makefile scripts/Makefile scripts/waves/Makefile docs/Makefile)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Makefile.in generated by automake 1.8.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.1 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
@ -46,7 +46,8 @@ CONFIG_CLEAN_FILES =
|
||||||
SOURCES =
|
SOURCES =
|
||||||
DIST_SOURCES =
|
DIST_SOURCES =
|
||||||
man1dir = $(mandir)/man1
|
man1dir = $(mandir)/man1
|
||||||
am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"
|
am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \
|
||||||
|
"$(DESTDIR)$(man8dir)"
|
||||||
man5dir = $(mandir)/man5
|
man5dir = $(mandir)/man5
|
||||||
man8dir = $(mandir)/man8
|
man8dir = $(mandir)/man8
|
||||||
NROFF = nroff
|
NROFF = nroff
|
||||||
|
@ -114,6 +115,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
am__leading_dot = @am__leading_dot@
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
bindir = @bindir@
|
bindir = @bindir@
|
||||||
build_alias = @build_alias@
|
build_alias = @build_alias@
|
||||||
datadir = @datadir@
|
datadir = @datadir@
|
||||||
|
@ -381,7 +384,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@ -435,9 +438,9 @@ uninstall-am: uninstall-info-am uninstall-local uninstall-man
|
||||||
|
|
||||||
uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8
|
uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8
|
||||||
|
|
||||||
.PHONY: all all-am check check-am clean clean-generic distclean \
|
.PHONY: all all-am check check-am clean clean-generic dist-hook \
|
||||||
distclean-generic distdir dvi dvi-am html html-am info info-am \
|
distclean distclean-generic distdir dvi dvi-am html html-am \
|
||||||
install install-am install-data install-data-am \
|
info info-am install install-am install-data install-data-am \
|
||||||
install-data-local install-exec install-exec-am install-info \
|
install-data-local install-exec install-exec-am install-info \
|
||||||
install-info-am install-man install-man1 install-man5 \
|
install-info-am install-man install-man1 install-man5 \
|
||||||
install-man8 install-strip installcheck installcheck-am \
|
install-man8 install-strip installcheck installcheck-am \
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
#EXTRA_DIST = Doxyfile.in mainpage.doxy manual.docbook manual.README
|
||||||
|
|
||||||
|
|
||||||
|
## dist-hook: manual-html manual-pdf reference-html
|
||||||
|
## mkdir $(distdir)/manual
|
||||||
|
## cp -r $(srcdir)/manual/* $(distdir)/manual/
|
||||||
|
## mkdir $(distdir)/reference
|
||||||
|
## cp $(srcdir)/reference/* $(distdir)/reference/
|
||||||
|
## cp manual.pdf $(distdir)/
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
def patch_version(target, source, env):
|
||||||
|
"""
|
||||||
|
Change version contained in the <title> tag.
|
||||||
|
This is done in-place to avoid yet another .in file.
|
||||||
|
"""
|
||||||
|
text = source[0].get_contents()
|
||||||
|
text = re.sub(r'<title>CapiSuite [\w.]*</title>',
|
||||||
|
r'<title>CapiSuite %s</title>' % env['VERSION'],
|
||||||
|
text)
|
||||||
|
open(source[0].abspath, 'w').write(text)
|
||||||
|
|
||||||
|
|
||||||
|
env.Append(docbuilddir=Dir('.'))
|
||||||
|
|
||||||
|
manualdir = Dir('manual')
|
||||||
|
stylesheetdir = Dir('/usr/share/sgml/docbook/xsl-stylesheets')
|
||||||
|
|
||||||
|
#images = Install(Dir('images', manualdir), images)
|
||||||
|
|
||||||
|
# create HTML manual
|
||||||
|
manual_html = env.Command(File('index.html', manualdir),
|
||||||
|
'manual.docbook', [
|
||||||
|
patch_version,
|
||||||
|
['xmllint', '--noout', '--valid', '$SOURCE'],
|
||||||
|
['xsltproc', '-o', '${TARGET.dir}/',
|
||||||
|
File('xhtml/chunk.xsl', stylesheetdir), '$SOURCE']
|
||||||
|
])
|
||||||
|
#env.Depends(manual_html, images)
|
||||||
|
|
||||||
|
# copy missing images
|
||||||
|
env.AddPostAction(manual_html, [ \
|
||||||
|
['rm', '-fr', Dir('images', manualdir)],
|
||||||
|
['cp', '-r', Dir('images', stylesheetdir), Dir(manualdir)]
|
||||||
|
])
|
||||||
|
|
||||||
|
# create PDF manual
|
||||||
|
manual_pdf = env.Command('manual.pdf', 'manual.docbook',
|
||||||
|
'db2pdf -o ${TARGET.dir} $SOURCE'
|
||||||
|
)
|
||||||
|
|
||||||
|
# substitute version, capisuite_sources, srcdir
|
||||||
|
doxyfile = env.FileSubst('Doxyfile', 'Doxyfile.in')
|
||||||
|
ref_html = env.Command('reference/index.html', doxyfile, [ \
|
||||||
|
['doxygen', doxyfile]
|
||||||
|
])
|
||||||
|
|
||||||
|
Alias('install',
|
||||||
|
env.Install('$docdir', manual_pdf),
|
||||||
|
#env.Install('$docdir', 'manual'),
|
||||||
|
#env.Install('$docdir', 'reference'),
|
||||||
|
)
|
|
@ -82,6 +82,8 @@ case "$1" in
|
||||||
# answering machine. Otherwise exit.
|
# answering machine. Otherwise exit.
|
||||||
# IMPORTANT: Change this or comment it out if you want to use
|
# IMPORTANT: Change this or comment it out if you want to use
|
||||||
# your own CapiSuite scripts.
|
# your own CapiSuite scripts.
|
||||||
|
# todo: change these tests since they are not longer valid due to
|
||||||
|
# [Mail...] sections. Consider using capisuite-checkconfig!
|
||||||
while read -r sec rest ; do
|
while read -r sec rest ; do
|
||||||
if [ "${sec:0:1}" = "[" -a "$sec" != "[GLOBAL]" ]; then
|
if [ "${sec:0:1}" = "[" -a "$sec" != "[GLOBAL]" ]; then
|
||||||
configured_fax=yes
|
configured_fax=yes
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Makefile.in generated by automake 1.8.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.1 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
@ -46,7 +46,8 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
CONFIG_HEADER = $(top_builddir)/config.h
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
CONFIG_CLEAN_FILES =
|
CONFIG_CLEAN_FILES =
|
||||||
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(pkgsysconfdir)" "$(DESTDIR)$(python_moduledir)"
|
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibdir)" \
|
||||||
|
"$(DESTDIR)$(pkgsysconfdir)" "$(DESTDIR)$(python_moduledir)"
|
||||||
binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
|
binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
|
||||||
SCRIPTS = $(bin_SCRIPTS)
|
SCRIPTS = $(bin_SCRIPTS)
|
||||||
SOURCES =
|
SOURCES =
|
||||||
|
@ -57,6 +58,12 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||||
install-recursive installcheck-recursive installdirs-recursive \
|
install-recursive installcheck-recursive installdirs-recursive \
|
||||||
pdf-recursive ps-recursive uninstall-info-recursive \
|
pdf-recursive ps-recursive uninstall-info-recursive \
|
||||||
uninstall-recursive
|
uninstall-recursive
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||||
dist_pkglibDATA_INSTALL = $(INSTALL_DATA)
|
dist_pkglibDATA_INSTALL = $(INSTALL_DATA)
|
||||||
pkgsysconfDATA_INSTALL = $(INSTALL_DATA)
|
pkgsysconfDATA_INSTALL = $(INSTALL_DATA)
|
||||||
python_moduleDATA_INSTALL = $(INSTALL_DATA)
|
python_moduleDATA_INSTALL = $(INSTALL_DATA)
|
||||||
|
@ -127,6 +134,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
am__leading_dot = @am__leading_dot@
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
bindir = @bindir@
|
bindir = @bindir@
|
||||||
build_alias = @build_alias@
|
build_alias = @build_alias@
|
||||||
datadir = @datadir@
|
datadir = @datadir@
|
||||||
|
@ -227,7 +236,7 @@ install-dist_pkglibDATA: $(dist_pkglib_DATA)
|
||||||
test -z "$(pkglibdir)" || $(mkdir_p) "$(DESTDIR)$(pkglibdir)"
|
test -z "$(pkglibdir)" || $(mkdir_p) "$(DESTDIR)$(pkglibdir)"
|
||||||
@list='$(dist_pkglib_DATA)'; for p in $$list; do \
|
@list='$(dist_pkglib_DATA)'; for p in $$list; do \
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " $(dist_pkglibDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkglibdir)/$$f'"; \
|
echo " $(dist_pkglibDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkglibdir)/$$f'"; \
|
||||||
$(dist_pkglibDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkglibdir)/$$f"; \
|
$(dist_pkglibDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkglibdir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -235,7 +244,7 @@ install-dist_pkglibDATA: $(dist_pkglib_DATA)
|
||||||
uninstall-dist_pkglibDATA:
|
uninstall-dist_pkglibDATA:
|
||||||
@$(NORMAL_UNINSTALL)
|
@$(NORMAL_UNINSTALL)
|
||||||
@list='$(dist_pkglib_DATA)'; for p in $$list; do \
|
@list='$(dist_pkglib_DATA)'; for p in $$list; do \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \
|
echo " rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \
|
||||||
rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \
|
rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -244,7 +253,7 @@ install-pkgsysconfDATA: $(pkgsysconf_DATA)
|
||||||
test -z "$(pkgsysconfdir)" || $(mkdir_p) "$(DESTDIR)$(pkgsysconfdir)"
|
test -z "$(pkgsysconfdir)" || $(mkdir_p) "$(DESTDIR)$(pkgsysconfdir)"
|
||||||
@list='$(pkgsysconf_DATA)'; for p in $$list; do \
|
@list='$(pkgsysconf_DATA)'; for p in $$list; do \
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " $(pkgsysconfDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgsysconfdir)/$$f'"; \
|
echo " $(pkgsysconfDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgsysconfdir)/$$f'"; \
|
||||||
$(pkgsysconfDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgsysconfdir)/$$f"; \
|
$(pkgsysconfDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgsysconfdir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -252,7 +261,7 @@ install-pkgsysconfDATA: $(pkgsysconf_DATA)
|
||||||
uninstall-pkgsysconfDATA:
|
uninstall-pkgsysconfDATA:
|
||||||
@$(NORMAL_UNINSTALL)
|
@$(NORMAL_UNINSTALL)
|
||||||
@list='$(pkgsysconf_DATA)'; for p in $$list; do \
|
@list='$(pkgsysconf_DATA)'; for p in $$list; do \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " rm -f '$(DESTDIR)$(pkgsysconfdir)/$$f'"; \
|
echo " rm -f '$(DESTDIR)$(pkgsysconfdir)/$$f'"; \
|
||||||
rm -f "$(DESTDIR)$(pkgsysconfdir)/$$f"; \
|
rm -f "$(DESTDIR)$(pkgsysconfdir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -261,7 +270,7 @@ install-python_moduleDATA: $(python_module_DATA)
|
||||||
test -z "$(python_moduledir)" || $(mkdir_p) "$(DESTDIR)$(python_moduledir)"
|
test -z "$(python_moduledir)" || $(mkdir_p) "$(DESTDIR)$(python_moduledir)"
|
||||||
@list='$(python_module_DATA)'; for p in $$list; do \
|
@list='$(python_module_DATA)'; for p in $$list; do \
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " $(python_moduleDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(python_moduledir)/$$f'"; \
|
echo " $(python_moduleDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(python_moduledir)/$$f'"; \
|
||||||
$(python_moduleDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(python_moduledir)/$$f"; \
|
$(python_moduleDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(python_moduledir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -269,7 +278,7 @@ install-python_moduleDATA: $(python_module_DATA)
|
||||||
uninstall-python_moduleDATA:
|
uninstall-python_moduleDATA:
|
||||||
@$(NORMAL_UNINSTALL)
|
@$(NORMAL_UNINSTALL)
|
||||||
@list='$(python_module_DATA)'; for p in $$list; do \
|
@list='$(python_module_DATA)'; for p in $$list; do \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " rm -f '$(DESTDIR)$(python_moduledir)/$$f'"; \
|
echo " rm -f '$(DESTDIR)$(python_moduledir)/$$f'"; \
|
||||||
rm -f "$(DESTDIR)$(python_moduledir)/$$f"; \
|
rm -f "$(DESTDIR)$(python_moduledir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -347,14 +356,16 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
tags=; \
|
tags=; \
|
||||||
here=`pwd`; \
|
here=`pwd`; \
|
||||||
if (etags --etags-include --version) >/dev/null 2>&1; then \
|
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||||
include_option=--etags-include; \
|
include_option=--etags-include; \
|
||||||
|
empty_fix=.; \
|
||||||
else \
|
else \
|
||||||
include_option=--include; \
|
include_option=--include; \
|
||||||
|
empty_fix=; \
|
||||||
fi; \
|
fi; \
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
if test "$$subdir" = .; then :; else \
|
if test "$$subdir" = .; then :; else \
|
||||||
test -f $$subdir/TAGS && \
|
test ! -f $$subdir/TAGS || \
|
||||||
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
||||||
fi; \
|
fi; \
|
||||||
done; \
|
done; \
|
||||||
|
@ -364,9 +375,11 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
done | \
|
done | \
|
||||||
$(AWK) ' { files[$$0] = 1; } \
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
END { for (i in files) print i; }'`; \
|
END { for (i in files) print i; }'`; \
|
||||||
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||||
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
$$tags $$unique
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$tags $$unique; \
|
||||||
|
fi
|
||||||
ctags: CTAGS
|
ctags: CTAGS
|
||||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
|
@ -417,15 +430,17 @@ distdir: $(DISTFILES)
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
done
|
done
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||||
if test "$$subdir" = .; then :; else \
|
if test "$$subdir" = .; then :; else \
|
||||||
test -d "$(distdir)/$$subdir" \
|
test -d "$(distdir)/$$subdir" \
|
||||||
|| mkdir "$(distdir)/$$subdir" \
|
|| $(mkdir_p) "$(distdir)/$$subdir" \
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
|
distdir=`$(am__cd) $(distdir) && pwd`; \
|
||||||
|
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
|
||||||
(cd $$subdir && \
|
(cd $$subdir && \
|
||||||
$(MAKE) $(AM_MAKEFLAGS) \
|
$(MAKE) $(AM_MAKEFLAGS) \
|
||||||
top_distdir="../$(top_distdir)" \
|
top_distdir="$$top_distdir" \
|
||||||
distdir="../$(distdir)/$$subdir" \
|
distdir="$$distdir/$$subdir" \
|
||||||
distdir) \
|
distdir) \
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
|
@ -457,7 +472,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@ -522,15 +537,16 @@ uninstall-info: uninstall-info-recursive
|
||||||
distclean-recursive distclean-tags distdir dvi dvi-am html \
|
distclean-recursive distclean-tags distdir dvi dvi-am html \
|
||||||
html-am info info-am install install-am install-binSCRIPTS \
|
html-am info info-am install install-am install-binSCRIPTS \
|
||||||
install-data install-data-am install-dist_pkglibDATA \
|
install-data install-data-am install-dist_pkglibDATA \
|
||||||
install-exec install-exec-am install-info install-info-am \
|
install-exec install-exec-am install-exec-hook install-info \
|
||||||
install-man install-pkgsysconfDATA install-python_moduleDATA \
|
install-info-am install-man install-pkgsysconfDATA \
|
||||||
install-strip installcheck installcheck-am installdirs \
|
install-python_moduleDATA install-strip installcheck \
|
||||||
installdirs-am maintainer-clean maintainer-clean-generic \
|
installcheck-am installdirs installdirs-am maintainer-clean \
|
||||||
maintainer-clean-recursive mostlyclean mostlyclean-generic \
|
maintainer-clean-generic maintainer-clean-recursive \
|
||||||
mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
|
mostlyclean mostlyclean-generic mostlyclean-recursive pdf \
|
||||||
uninstall uninstall-am uninstall-binSCRIPTS \
|
pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
|
||||||
uninstall-dist_pkglibDATA uninstall-info-am \
|
uninstall-binSCRIPTS uninstall-dist_pkglibDATA uninstall-hook \
|
||||||
uninstall-pkgsysconfDATA uninstall-python_moduleDATA
|
uninstall-info-am uninstall-pkgsysconfDATA \
|
||||||
|
uninstall-python_moduleDATA
|
||||||
|
|
||||||
|
|
||||||
capisuitefax: capisuitefax.in
|
capisuitefax: capisuitefax.in
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
def py_compile(target, source, env):
|
||||||
|
"""compile python modules for .../python2.x/site-packages/"""
|
||||||
|
# Note: this differs from #/capisuite/SConscript.py_compile in 'dfile'
|
||||||
|
import py_compile, os.path
|
||||||
|
py_compile.compile(source[0].abspath,
|
||||||
|
#cfile=target[0].abspath,
|
||||||
|
dfile = os.path.join(env.subst('$python_moduledir'),
|
||||||
|
env.subst('$SOURCE.file')),
|
||||||
|
)
|
||||||
|
|
||||||
|
# these ar meant to be used by users
|
||||||
|
user_scripts = [env.FileSubst('capisuitefax', 'capisuitefax.in'),]
|
||||||
|
env.AddPostAction(user_scripts, 'chmod 755 $TARGETS')
|
||||||
|
|
||||||
|
# these are meant to be used by the admin
|
||||||
|
sbin_scripts = [File('capisuite-checkconfig'),]
|
||||||
|
#env.AddPostAction(sbin_scripts, 'chmod 755 $TARGETS')
|
||||||
|
|
||||||
|
# config files
|
||||||
|
configs = [
|
||||||
|
env.FileSubst('fax.conf', 'fax.confin'),
|
||||||
|
env.FileSubst('answering_machine.conf', 'answering_machine.confin')
|
||||||
|
]
|
||||||
|
|
||||||
|
# this is no longer needed
|
||||||
|
# todo: check cs_helper.py into cvs instead of cs_helper.pyin
|
||||||
|
env.FileSubst('cs_helpers.py', 'cs_helpers.pyin')
|
||||||
|
|
||||||
|
pymodules = []
|
||||||
|
for mod in Split('cs_helpers'):
|
||||||
|
pymodules.append(mod+'.py')
|
||||||
|
pymodules.append(env.Command(mod + '.pyc', mod+'.py', py_compile))
|
||||||
|
|
||||||
|
#--- install ---
|
||||||
|
|
||||||
|
install_pylib = env.Install('$python_moduledir', pymodules)
|
||||||
|
Alias('install-pylib',install_pylib)
|
||||||
|
|
||||||
|
for i in [env.Install('$pkgbindir', user_scripts),
|
||||||
|
env.Install('$pkgsbindir', sbin_scripts),
|
||||||
|
env.Install('$pkglibdir', Split('idle.py incoming.py'))]:
|
||||||
|
Alias('install-scripts', i)
|
||||||
|
Alias('install', i)
|
||||||
|
|
||||||
|
Alias('install',
|
||||||
|
env.Install('$python_moduledir', pymodules),
|
||||||
|
env.Install('$pkgsysconfdir', configs),
|
||||||
|
env.Install('$pkglibdir', 'README'),
|
||||||
|
)
|
|
@ -85,6 +85,24 @@ record_silence_timeout="5"
|
||||||
# header field.
|
# header field.
|
||||||
voice_email_from="capisuite daemon <root>"
|
voice_email_from="capisuite daemon <root>"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
############################# Mail settings ###################################
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# defined for voice receive: call_from, call_to, date,
|
||||||
|
# msg_length, filename, hostname
|
||||||
|
|
||||||
|
[MailVoiceReceived]
|
||||||
|
subject = Received a voice call from %(call_from)s to %(call_to)s
|
||||||
|
text =
|
||||||
|
You got a voice call from %(call_from)s to %(call_to)s
|
||||||
|
Date: %(date)s
|
||||||
|
Length: %(msg_length)i seconds
|
||||||
|
|
||||||
|
See attached file.
|
||||||
|
The original file was saved to file://%(filename)s on host "%(hostname)s".
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
############################# user settings ###################################
|
############################# user settings ###################################
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -108,12 +126,12 @@ voice_email_from="capisuite daemon <root>"
|
||||||
# is necessary for example for the austrian "Global Call" where no number is
|
# is necessary for example for the austrian "Global Call" where no number is
|
||||||
# signalled when the main MSN is called (sic).
|
# signalled when the main MSN is called (sic).
|
||||||
#
|
#
|
||||||
# voice_email="<mailaddress1>,<mailaddress2>,..." (optional, defaults to empty string)
|
# voice_email="<mailaddress1>,<mailaddress2>,..." (optional)
|
||||||
#
|
#
|
||||||
# If given, this string indicates email-addresses where the received faxes
|
# If given, this string indicates email-addresses where the received faxes
|
||||||
# and voice calls will be sent to. If it is empty, the recorded calls and
|
# and voice calls will be sent to. If it is not given, the recorded calls and
|
||||||
# faxes will be sent to the user on the current system. If you don't want to
|
# faxes will be sent to the user on the current system. If you don't want to
|
||||||
# get emails, see the "action" option below
|
# get emails, see the "action" option below.
|
||||||
#
|
#
|
||||||
# pin="<PIN number>" (optional, defaults to empty)
|
# pin="<PIN number>" (optional, defaults to empty)
|
||||||
#
|
#
|
||||||
|
@ -142,6 +160,5 @@ voice_email_from="capisuite daemon <root>"
|
||||||
#voice_action="MailAndSave"
|
#voice_action="MailAndSave"
|
||||||
#voice_delay="10"
|
#voice_delay="10"
|
||||||
#record_length="60"
|
#record_length="60"
|
||||||
#voice_email=""
|
|
||||||
#pin="99*45"
|
#pin="99*45"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import sys, os, os.path
|
||||||
|
|
||||||
|
def error(*msgs):
|
||||||
|
for m in msgs:
|
||||||
|
print >>sys.stderr, m,
|
||||||
|
print >>sys.stderr
|
||||||
|
sys.exit(10)
|
||||||
|
|
||||||
|
try:
|
||||||
|
import capisuite.config
|
||||||
|
import capisuite.fileutils
|
||||||
|
from capisuite.consts import *
|
||||||
|
except Exception, e:
|
||||||
|
error("failed to import capisuite's python modules", str(e))
|
||||||
|
|
||||||
|
|
||||||
|
# Sompe helper functions, if you don't know what they do, just skip to
|
||||||
|
# the easy part
|
||||||
|
|
||||||
|
def test_nextfile(user, path, queue, prefix):
|
||||||
|
path = os.path.join(path, user, queue)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
print "Directory", path, "does not exist"
|
||||||
|
print " ==> this is ok, if this queue has never been",
|
||||||
|
print "used before (e.g. never send a fax)"
|
||||||
|
print
|
||||||
|
return
|
||||||
|
file = os.path.join(path, prefix+"-nextnr")
|
||||||
|
if not os.path.exists(file):
|
||||||
|
print "File", file, "does not exist"
|
||||||
|
print " ==> this is ok, if this queue has never been",
|
||||||
|
print "used before (e.g. never send a fax)"
|
||||||
|
print
|
||||||
|
return
|
||||||
|
|
||||||
|
print "Trying to read file:", file
|
||||||
|
num = None
|
||||||
|
try:
|
||||||
|
num = capisuite.fileutils.readCounter(file, default=None)
|
||||||
|
except IOError, err:
|
||||||
|
print >>sys.stderr, "****Failed to read/parse the *nextnr file:", err
|
||||||
|
except ValueError:
|
||||||
|
print >>sys.stderr, "****Failed to convert file content to int number"
|
||||||
|
else:
|
||||||
|
if num is None:
|
||||||
|
print " ", file, 'is unset'
|
||||||
|
else:
|
||||||
|
print " ", file, 'contains number', num
|
||||||
|
|
||||||
|
|
||||||
|
def checkQdirs(user, basedir, queuedir):
|
||||||
|
path = os.path.join(basedir, user, queuedir)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
if os.getuid() == 0:
|
||||||
|
print 'creating user queue dir', path
|
||||||
|
capisuite.fileutils._mkuserdir(user, basedir, user, queuedir)
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
print >>sys.stderr, 'missing user queue dir', path
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# END helper functions ================
|
||||||
|
|
||||||
|
def checkGlobalConfig(file=None):
|
||||||
|
print "Reading global configuration ...",
|
||||||
|
try:
|
||||||
|
config = capisuite.config.readGlobalConfig(file)
|
||||||
|
except IOError, err:
|
||||||
|
print
|
||||||
|
error("Failed to read/parse config file:", err)
|
||||||
|
print 'okay'
|
||||||
|
|
||||||
|
print
|
||||||
|
print "========= current configuration ==================="
|
||||||
|
for section in config.sections():
|
||||||
|
print "----------------", '['+section+']', "-------------"
|
||||||
|
options = config.options(section)
|
||||||
|
options.sort()
|
||||||
|
for option in options:
|
||||||
|
print option, '=', config.get(section, option)
|
||||||
|
print
|
||||||
|
|
||||||
|
|
||||||
|
print
|
||||||
|
print "=========== Testing User Queues and Sequence Files ====="
|
||||||
|
print
|
||||||
|
|
||||||
|
basedir = config.get('GLOBAL', 'fax_user_dir')
|
||||||
|
userdirs_missing = 0
|
||||||
|
for user in config.listUsers():
|
||||||
|
print "----------------", user, "-------------"
|
||||||
|
for queue in (SEND_Q, RECEIVED_Q):
|
||||||
|
if not checkQdirs(user, basedir, queue):
|
||||||
|
userdirs_missing += 1
|
||||||
|
else:
|
||||||
|
test_nextfile(user, basedir, queue, "fax")
|
||||||
|
if queue == RECEIVED_Q:
|
||||||
|
test_nextfile(user, basedir, queue, "voice")
|
||||||
|
|
||||||
|
if userdirs_missing:
|
||||||
|
print
|
||||||
|
print 'Some user queue dirs are missing.'
|
||||||
|
print "Rerun as 'root' to create them."
|
||||||
|
print
|
||||||
|
|
||||||
|
#----------- main -----------#
|
||||||
|
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
checkGlobalConfig()
|
||||||
|
elif 0:
|
||||||
|
checkGlobalConfig(sys.argv[1])
|
||||||
|
else:
|
||||||
|
config = capisuite.config.readGlobalConfig(sys.argv[1])
|
||||||
|
sections = config.sections()
|
||||||
|
sections.sort()
|
||||||
|
for section in sections:
|
||||||
|
print "----------------", '['+section+']', "-------------"
|
||||||
|
options = config.options(section)
|
||||||
|
options.sort()
|
||||||
|
for option in options:
|
||||||
|
print option, '=', config.get(section, option)
|
||||||
|
print
|
||||||
|
print 'known users:',
|
||||||
|
print config.listUsers()
|
||||||
|
# todo: these checks:
|
||||||
|
# - are all users valid system users?
|
||||||
|
# - do all voice-users have 'voice_delay' set?
|
||||||
|
# - option --configured to chekc if any fax or voice user is configured
|
|
@ -1,4 +1,5 @@
|
||||||
#!@PYTHON@
|
#!@PYTHON@
|
||||||
|
# -*- mode: python -*-
|
||||||
#
|
#
|
||||||
# capisuitefax - capisuite tool for enqueuing faxes
|
# capisuitefax - capisuite tool for enqueuing faxes
|
||||||
# ---------------------------------------------------
|
# ---------------------------------------------------
|
||||||
|
@ -11,18 +12,10 @@
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
|
|
||||||
import getopt,os,sys,re,time,pwd,errno,fcntl,string
|
import getopt, os, sys, pwd, string, commands
|
||||||
# capisuite stuff
|
# capisuite stuff
|
||||||
import cs_helpers
|
import capisuite.fax
|
||||||
|
import capisuite.config
|
||||||
dialstring=""
|
|
||||||
addressee=""
|
|
||||||
subject=""
|
|
||||||
abort=""
|
|
||||||
user=""
|
|
||||||
quiet=0
|
|
||||||
listqueue=0
|
|
||||||
useprefix=1
|
|
||||||
|
|
||||||
def usage(error=""):
|
def usage(error=""):
|
||||||
print """capisuitefax - capisuite tool for enqueueing faxes
|
print """capisuitefax - capisuite tool for enqueueing faxes
|
||||||
|
@ -50,165 +43,163 @@ other options:
|
||||||
-l, --list print jobs in the send queue
|
-l, --list print jobs in the send queue
|
||||||
|
|
||||||
The given files must be in Adobe PostScript or PDF format"""
|
The given files must be in Adobe PostScript or PDF format"""
|
||||||
if (error!=""):
|
if error:
|
||||||
print
|
print
|
||||||
print "ERROR:",error
|
print "ERROR:",error
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def showlist(config,user):
|
|
||||||
sendq=cs_helpers.getOption(config,"","fax_user_dir")
|
|
||||||
if (sendq==None):
|
|
||||||
print "ERROR: option fax_user_dir not set in fax configuration"
|
|
||||||
sys.exit(1)
|
|
||||||
sendq=os.path.join(sendq,user,"sendq")+"/"
|
|
||||||
|
|
||||||
print "ID Nr./Addressee Tries Next try Subject"
|
def convert2Fax(filenames, faxname):
|
||||||
|
# todo: clean this up, maybe rewrite it
|
||||||
|
"""
|
||||||
|
convert file 'filename' to a SFF fax file 'faxfile'.
|
||||||
|
"""
|
||||||
|
def checkFile(fname, fname_):
|
||||||
|
if not os.access(fname, os.R_OK):
|
||||||
|
print >> sys.stderr, "can't open", fname
|
||||||
|
return 0
|
||||||
|
status, filetype = commands.getstatusoutput(
|
||||||
|
"file -b -i %s 2>/dev/null" % fname_)
|
||||||
|
if status:
|
||||||
|
usage("Error when executing command 'file'")
|
||||||
|
return 0
|
||||||
|
if filetype.find("application/postscript") < 0 \
|
||||||
|
and filetype.find("application/pdf") < 0:
|
||||||
|
print >> sys.stderr, arg, "is not a PostScript/PDF file"
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
files=os.listdir(sendq)
|
# todo: catch errors!
|
||||||
files=filter (lambda s: re.match("fax-.*\.txt",s),files)
|
files = []
|
||||||
if (not len(files)):
|
for fname in filenames:
|
||||||
print "--- queue empty ---"
|
fname_ = commands.mkarg(fname)
|
||||||
|
if not checkFile(fname, fname_):
|
||||||
|
return 0
|
||||||
|
files.append(fname_)
|
||||||
|
command = "gs -dNOPAUSE -dQUIET -dBATCH -sDEVICE=cfax " \
|
||||||
|
"-sOutputFile=%s %s" % (faxname, ' '.join(files))
|
||||||
|
ret = os.system(command) >> 8
|
||||||
|
if ret:
|
||||||
|
print >> sys.stderr, "error during SFF-conversion ot file", arg
|
||||||
|
print >> sys.stderr, "Ghostscript not installed?"
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
for job in files:
|
|
||||||
control=cs_helpers.readConfig(sendq+job)
|
|
||||||
sys.stdout.write(re.match("fax-([0-9]+)\.txt",job).group(1))
|
|
||||||
sys.stdout.write("\t")
|
|
||||||
dest=cs_helpers.getOption(control,"GLOBAL","addressee","")
|
|
||||||
if (dest==""):
|
|
||||||
dest=control.get("GLOBAL","dialstring")
|
|
||||||
sys.stdout.write(dest+"\t")
|
|
||||||
if (len(dest)<8):
|
|
||||||
sys.stdout.write("\t")
|
|
||||||
sys.stdout.write(control.get("GLOBAL","tries")+"\t")
|
|
||||||
sys.stdout.write(control.get("GLOBAL","starttime")+"\t")
|
|
||||||
sys.stdout.write(cs_helpers.getOption(control,"GLOBAL","subject","")+"\n")
|
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
def abortjob(config,user,job):
|
|
||||||
sendq=cs_helpers.getOption(config,"","fax_user_dir")
|
|
||||||
if (sendq==None):
|
|
||||||
print "ERROR: option fax_user_dir not set in fax configuration"
|
|
||||||
sys.exit(1)
|
|
||||||
sendq=os.path.join(sendq,user,"sendq")+"/"
|
|
||||||
job="fax-"+job+".txt"
|
|
||||||
|
|
||||||
if (not os.access(sendq+job,os.W_OK)):
|
|
||||||
print "job to abort not valid"
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
def showQueue(config, user):
|
||||||
try:
|
try:
|
||||||
lockfile=open(sendq+job[:-3]+"lock","w")
|
jobs = capisuite.fax.getQueueDetails(config, user)
|
||||||
# lock so that it isn't deleted while sending
|
except capisuite.config.NoOptionError:
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_EX | fcntl.LOCK_NB)
|
print "ERROR: option fax_user_dir not set in fax configuration"
|
||||||
os.unlink(sendq+job)
|
return 10
|
||||||
os.unlink(sendq+job[:-3]+"sff")
|
if not jobs:
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_UN)
|
print "--- queue empty ---"
|
||||||
os.unlink(sendq+job[:-3]+"lock")
|
else:
|
||||||
except IOError,err:
|
format = "%s\t%s %2s\t%-24s %s"
|
||||||
if (err.errno in (errno.EACCES,errno.EAGAIN)):
|
print format % ('ID', 'Numb./Addr.', 'Try', 'Next try', 'Subject')
|
||||||
print "Job is currently in transmission. Can't abort."
|
for entry in jobs:
|
||||||
|
print format % entry
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def abortJob(config, user, job):
|
||||||
|
# todo: test whether 'job' is an integer
|
||||||
|
try:
|
||||||
|
capisuite.fax.abortUserJob(config, user, jobnum=job)
|
||||||
|
except capisuite.fax.InvalidJob:
|
||||||
|
print "job to abort not valid"
|
||||||
|
return 1
|
||||||
|
except capisuite.fax.JobLockedError:
|
||||||
|
print "Job is currently in transmission. Can't abort."
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
optlist,args = getopt.getopt(sys.argv[1:], "d:a:u:lhqnA:S:"
|
optlist,args = getopt.getopt(sys.argv[1:], "d:a:u:lhqnA:S:",
|
||||||
,['dialstring=','noprefix','help',"abort=","list","quiet","user=",
|
['dialstring=','noprefix','help',"abort=","list","quiet","user=",
|
||||||
'addressee=','subject='])
|
'addressee=','subject='])
|
||||||
|
|
||||||
except getopt.GetoptError, e:
|
except getopt.GetoptError, e:
|
||||||
usage(e.msg)
|
usage(e.msg)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# read options
|
# read options
|
||||||
for option,param in optlist:
|
dialstring = addressee = subject = abort = user = ""
|
||||||
if option in ('-d','--dialstring'): dialstring=param
|
quiet = listqueue = 0
|
||||||
if option in ('-A','--addressee'): addressee=param
|
useprefix = 1
|
||||||
if option in ('-S','--subject'): subject=param
|
|
||||||
if option in ('-n','--noprefix'): useprefix=0
|
for option, param in optlist:
|
||||||
|
# commands
|
||||||
if option in ('-h','--help'): usage()
|
if option in ('-h','--help'): usage()
|
||||||
if option in ('-l','--list'): listqueue=1
|
elif option in ('-l','--list'): listqueue = 1
|
||||||
if option in ('-a','--abort'): abort=param
|
elif option in ('-a','--abort'): abort = param
|
||||||
if option in ('-q','--quiet'): quiet=1
|
# send options
|
||||||
if option in ('-u','--user'):
|
elif option in ('-d','--dialstring'): dialstring = param
|
||||||
if (os.getuid()==0):
|
elif option in ('-A','--addressee'): addressee = param
|
||||||
user=param
|
elif option in ('-S','--subject'): subject = param
|
||||||
|
elif option in ('-n','--noprefix'): useprefix = 0
|
||||||
|
elif option in ('-q','--quiet'): quiet = 1
|
||||||
|
elif option in ('-u','--user'):
|
||||||
|
if not os.getuid():
|
||||||
|
user = param
|
||||||
else:
|
else:
|
||||||
usage("--user may only used as root!")
|
usage("--user may only used as root!")
|
||||||
|
|
||||||
if (not abort and not listqueue and not dialstring):
|
if not abort and not listqueue and not dialstring:
|
||||||
usage("No usable command given.")
|
usage("No usable command given.")
|
||||||
|
|
||||||
# filter out common separators from dialstring, check it
|
config = capisuite.config.readGlobalConfig()
|
||||||
dialstring=dialstring.translate(string.maketrans("",""),"-/ ()")
|
if not user:
|
||||||
for i in dialstring:
|
user = pwd.getpwuid(os.getuid()).pw_name
|
||||||
if ((i>'9' or i<'0') and i not in ('+*#')):
|
|
||||||
usage("Invalid dialstring given.")
|
|
||||||
|
|
||||||
if (dialstring and len(args)==0):
|
if listqueue:
|
||||||
usage("No fax files given")
|
sys.exit(showQueue(config, user))
|
||||||
|
elif abort:
|
||||||
|
try:
|
||||||
|
jobnum = int(abort)
|
||||||
|
except ValueError:
|
||||||
|
print "Error: job id has to be a number, but is %r" % abort
|
||||||
|
sys.exit(1)
|
||||||
|
sys.exit(abortJob(config, user, jobnum))
|
||||||
|
else:
|
||||||
|
# queue fax for sending
|
||||||
|
|
||||||
# test if this user is allowed to send faxes
|
# filter out common separators from dialstring, check it
|
||||||
config=cs_helpers.readConfig()
|
dialstring = dialstring.translate(string.maketrans("",""),"-/ ()")
|
||||||
if (user==""):
|
for i in dialstring:
|
||||||
user=pwd.getpwuid(os.getuid())[0]
|
if not i in '+0123456789*#':
|
||||||
if (not config.has_section(user)):
|
usage("Invalid dialstring given, character %r is not allowed." % i)
|
||||||
print "Sorry, you're no valid user for CapiSuite"
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if ((cs_helpers.getOption(config,user,"outgoing_MSN","")=="") and (config.get(user,"fax_numbers","")=="")):
|
if dialstring and len(args)==0:
|
||||||
print "Sorry, you're not allowed to use fax services"
|
usage("No fax files given")
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# test environment
|
# test if this user is allowed to send faxes
|
||||||
sendq=cs_helpers.getOption(config,"","fax_user_dir")
|
if not config.has_section(user):
|
||||||
if (sendq==None):
|
print "Sorry, you're no valid user for CapiSuite"
|
||||||
print "ERROR: option fax_user_dir not set in fax configuration"
|
sys.exit(1)
|
||||||
sys.exit(1)
|
|
||||||
sendq=os.path.join(sendq,user,"sendq")+"/"
|
|
||||||
if (not os.access(sendq,os.W_OK)):
|
|
||||||
print "can't write to queue dir"
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if (listqueue):
|
if not config.has_option(user, "outgoing_MSN") and \
|
||||||
showlist(config,user)
|
not config.has_option(user, "fax_numbers"):
|
||||||
|
print "Sorry, you're not allowed to use fax services"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
if (abort):
|
if useprefix:
|
||||||
abortjob(config,user,abort)
|
dialstring = config.getUser(user, "dial_prefix", '') + dialstring
|
||||||
|
|
||||||
prefix=cs_helpers.getOption(config,user,"dial_prefix","")
|
# convert and enqueue files
|
||||||
if (useprefix):
|
jobDesc = {
|
||||||
dialstring=prefix+dialstring
|
"dialstring": dialstring,
|
||||||
|
#"user": user,
|
||||||
# convert and enqueue files
|
"addressee": addressee,
|
||||||
for i in args:
|
"subject": subject,
|
||||||
if (not os.access(i,os.R_OK)):
|
# todo: allow these to be specified for this jobs
|
||||||
sys.stderr.write("can't open "+i+'\n')
|
#'stationID': ...
|
||||||
continue
|
#'headline': ...
|
||||||
t=os.popen("file -b -i "+cs_helpers.escape(i)+" 2>/dev/null")
|
}
|
||||||
filetype=t.read()
|
try:
|
||||||
if (t.close()):
|
jobnum = capisuite.fax.enqueueJob(config, user, args,
|
||||||
usage("can't execute \"file\"")
|
convert2Fax, **jobDesc)
|
||||||
if (not re.search("application/postscript",filetype) \
|
except IOError, e:
|
||||||
and not re.search("application/pdf",filetype)):
|
print e
|
||||||
sys.stderr.write(i+" is not a PostScript/PDF file\n")
|
print "can't write to queue dir"
|
||||||
continue
|
sys.exit(1)
|
||||||
|
print "Successful enqueued as job", jobnum, "for", dialstring
|
||||||
newname=cs_helpers.uniqueName(sendq,"fax","sff")
|
|
||||||
|
|
||||||
command="gs -dNOPAUSE -dQUIET -dBATCH -sDEVICE=cfax -sOutputFile=" \
|
|
||||||
+ newname+" "+cs_helpers.escape(i)
|
|
||||||
ret=(os.system(command))>>8
|
|
||||||
if (ret):
|
|
||||||
sys.stderr.write("error during SFF-conversion at file "+i+'. \
|
|
||||||
Ghostscript not installed?\n')
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
cs_helpers.writeDescription(newname,"dialstring=\""+dialstring+"\"\n"
|
|
||||||
+"starttime=\""+time.ctime()+"\"\ntries=\"0\"\n"
|
|
||||||
+"user=\""+user+"\"\naddressee=\""+addressee+"\"\nsubject=\""
|
|
||||||
+subject+"\"\n")
|
|
||||||
os.chmod(newname,0600)
|
|
||||||
os.chmod(newname[:-3]+"txt",0600)
|
|
||||||
if (os.getuid()==0):
|
|
||||||
user_entry=pwd.getpwnam(user)
|
|
||||||
os.chown(newname,user_entry[2],user_entry[3])
|
|
||||||
os.chown(newname[:-3]+"txt",user_entry[2],user_entry[3])
|
|
||||||
print i,"successful enqueued as",newname,"for",dialstring
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- mode: python -*-
|
||||||
# cs_helpers.py - some helper functions for CapiSuite scripts
|
# cs_helpers.py - some helper functions for CapiSuite scripts
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
# copyright : (C) 2002 by Gernot Hillier
|
# copyright : (C) 2002 by Gernot Hillier
|
||||||
|
@ -9,131 +10,84 @@
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
|
|
||||||
# the name of the config file read by the scripts; see there for options and
|
import os, commands
|
||||||
# descriptions
|
|
||||||
configfile_fax="@pkgsysconfdir@/fax.conf"
|
|
||||||
configfile_voice="@pkgsysconfdir@/answering_machine.conf"
|
|
||||||
|
|
||||||
# @brief read configuration file and return a ConfigParser object
|
from capisuite.config import *
|
||||||
#
|
from capisuite.voice import sayNumber, getAudio
|
||||||
# The configfile is read from the path given above and the surrounding
|
|
||||||
# quotation marks from the values are removed
|
|
||||||
#
|
|
||||||
# @return the constructed config file object
|
|
||||||
def readConfig(file=""):
|
|
||||||
import ConfigParser
|
|
||||||
config=ConfigParser.ConfigParser()
|
|
||||||
if (file==""):
|
|
||||||
config.readfp(open(configfile_fax))
|
|
||||||
config.readfp(open(configfile_voice))
|
|
||||||
else:
|
|
||||||
config.readfp(open(file))
|
|
||||||
for s in config.sections():
|
|
||||||
for o in config.options(s):
|
|
||||||
value=config.get(s,o)
|
|
||||||
if (len(value)>1 and value[0]=='"'):
|
|
||||||
config.set(s,o,value[1:-1])
|
|
||||||
if (not config.has_section('GLOBAL')):
|
|
||||||
raise IOError("invalid config file, section GLOBAL missing")
|
|
||||||
return config
|
|
||||||
|
|
||||||
# @brief escape a filename to include it savely in a shell command
|
# Note: readConfig is now imported from capisuite.config
|
||||||
#
|
|
||||||
# The filename is enclosed in single quotation marks and quotation
|
|
||||||
# marks therein are quoted
|
|
||||||
#
|
|
||||||
# @return the escaped filename
|
|
||||||
def escape(filename):
|
|
||||||
return "'%s'" % filename.replace("'","'\\''")
|
|
||||||
|
|
||||||
# @brief get an option from the user or global section
|
# @brief escape a argument to include it savely in a shell command
|
||||||
#
|
#
|
||||||
# The option is searched in the users section and if not found
|
# This is just a wrapper to commands.mkarg which strips the leading
|
||||||
# in the global section.
|
# space which mkarg() adds.
|
||||||
#
|
#
|
||||||
# @param config the ConfigParser object containing the values
|
# @return the escaped argument
|
||||||
# @param user user section to use, if empty only global section is read
|
def escape(arg):
|
||||||
# @param option the name of the option to search for
|
arg = commands.mkarg(arg)
|
||||||
#
|
if arg[0] == ' ':
|
||||||
# @return the value for this option or None if it's not found
|
arg = arg[1:]
|
||||||
def getOption(config,user,option,default=None):
|
return arg
|
||||||
if config.has_option(user,option):
|
|
||||||
return config.get(user,option)
|
|
||||||
elif config.has_option('GLOBAL',option):
|
|
||||||
return config.get('GLOBAL',option)
|
|
||||||
else:
|
|
||||||
return default
|
|
||||||
|
|
||||||
# @brief Search for an audio file first in user_dir, than in audio_dir
|
def getOption(config, user, option, default=None):
|
||||||
#
|
return config.getUser(user, option, default)
|
||||||
# @param config the ConfigParser object containing the configuration
|
|
||||||
# @param user the name of the user
|
|
||||||
# @param filename the filename of the wave file
|
|
||||||
#
|
|
||||||
# @return the found file with full path
|
|
||||||
def getAudio(config,user,filename):
|
|
||||||
import os,capisuite
|
|
||||||
systemdir=getOption(config,"","audio_dir")
|
|
||||||
if (systemdir==None):
|
|
||||||
raise IOError("option audio_dir not found.")
|
|
||||||
userdir=getOption(config,"","voice_user_dir")
|
|
||||||
if (userdir==None):
|
|
||||||
raise IOError("option voice_user_dir not found.")
|
|
||||||
userdir=os.path.join(userdir,user)
|
|
||||||
if (int(getOption(config,"","user_audio_files","0"))
|
|
||||||
and os.access(os.path.join(userdir,filename),os.R_OK)):
|
|
||||||
return os.path.join(userdir,filename)
|
|
||||||
else:
|
|
||||||
return os.path.join(systemdir,filename)
|
|
||||||
|
|
||||||
# @brief thread-safe creation of a unique filename in a directory
|
# Note: getAudio is now imported from capisuite.voice
|
||||||
#
|
# Note: uniqueName is now imported from capisuite.fileutils
|
||||||
# This function reads the nextnumber from then "nextnr"-file in the given
|
def uniqueName(*args, **kwargs):
|
||||||
# directory and updates it. It holds the next free file number.
|
return capisuite.fileutils.uniqueName(*args, **kwargs)[1]
|
||||||
#
|
|
||||||
# If nextnr doesn't exist, it's created.
|
|
||||||
#
|
|
||||||
# The filenames created will have the format
|
|
||||||
#
|
|
||||||
# basename-number.suffix
|
|
||||||
#
|
|
||||||
# @param directory name of the directory to work in
|
|
||||||
# @param basename the basename of the filename
|
|
||||||
# @param suffix the suffix of the filename (without ".")
|
|
||||||
#
|
|
||||||
# @return new file name
|
|
||||||
def uniqueName(directory,basename,suffix):
|
|
||||||
import fcntl,os,re
|
|
||||||
# acquire lock
|
|
||||||
lockfile=open(os.path.join(directory,"cs_lock"),"w")
|
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_EX)
|
|
||||||
|
|
||||||
try:
|
|
||||||
countfile=open("%s-nextnr" % os.path.join(directory,basename),"r")
|
|
||||||
nextnr=int(countfile.readline())
|
|
||||||
countfile.close()
|
|
||||||
except IOError:
|
|
||||||
# search for next free sequence number
|
|
||||||
files=os.listdir(directory)
|
|
||||||
files=filter (lambda s: re.match("%s-.*\.%s" % (re.escape(basename),re.escape(suffix)),s),files)
|
|
||||||
if (len(files)):
|
|
||||||
files=map(lambda s: int(s[len(basename)+1:-len(suffix)-1]),files)
|
|
||||||
nextnr=max(files)+1 # take nr of last file and increase it by one
|
|
||||||
else:
|
|
||||||
nextnr=0
|
|
||||||
files.sort()
|
|
||||||
|
|
||||||
newname="%s-%i.%s" % (os.path.join(directory,basename),nextnr,suffix)
|
def __sendmail(mail_from, mail_to, msg):
|
||||||
|
import popen2, capisuite.core
|
||||||
|
|
||||||
countfile=open("%s-nextnr" % os.path.join(directory,basename),"w")
|
r,w = popen2.popen2("{ /usr/sbin/sendmail -t -f %s } 2>&1" % escape(mail_from))
|
||||||
countfile.write('%i\n' % (nextnr+1))
|
try:
|
||||||
countfile.close()
|
w.write(msg.as_string())
|
||||||
|
except IOError: #Errno 32: Broken Pipe
|
||||||
|
capisuite.core.error("Error while calling sendmail. Not installed?\n")
|
||||||
|
return 0
|
||||||
|
w.close()
|
||||||
|
#ret = sendmail.wait()
|
||||||
|
text = r.read()
|
||||||
|
r.close()
|
||||||
|
if text:
|
||||||
|
capisuite.core.error("Error while calling sendmail")#, return code=%i" % ret)
|
||||||
|
capisuite.core.error(text)
|
||||||
|
return 0
|
||||||
|
capisuite.core.log("sendmail finished successful",3)
|
||||||
|
return 1
|
||||||
|
|
||||||
# unlock
|
def __sendmail(fromaddr, toaddr, msg):
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_UN)
|
import smtplib, capisuite.core
|
||||||
lockfile.close()
|
smtpserver, port = 'localhost', 25
|
||||||
os.unlink(os.path.join(directory,"cs_lock"))
|
server = smtplib.SMTP(smtpserver, port)
|
||||||
return newname
|
server.sendmail(fromaddr, (toaddr), msg.as_string())
|
||||||
|
server.quit()
|
||||||
|
capisuite.core.log("mail sent successfully",3)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def __call(msg, cmd, *args):
|
||||||
|
"""
|
||||||
|
outfile MUST be last parameter!
|
||||||
|
"""
|
||||||
|
# todo: think about using commands.getstatusoutput() here
|
||||||
|
ret = os.spawnlp(os.P_WAIT, cmd, cmd, *(args))
|
||||||
|
if ret or not os.access(args[-1], os.F_OK):
|
||||||
|
raise ConvertionError("Error while converting %s. "
|
||||||
|
"File damaged or %s not installed?" %(msg, cmd))
|
||||||
|
|
||||||
|
def sff2tif(infile, outfile):
|
||||||
|
__call('sff to tif', "sfftobmp", "-tif", infile, outfile)
|
||||||
|
|
||||||
|
def cff2ps(infile, outfile):
|
||||||
|
__call("cff to ps", "jpeg2ps", "-m", infile , "-o", outfile)
|
||||||
|
|
||||||
|
def la2wav(infile, outfile):
|
||||||
|
__call('la to wav', "sox", infile, '-w', outfile)
|
||||||
|
|
||||||
|
class ConvertionError(Exception): pass
|
||||||
|
|
||||||
# @brief send email with text and attachment of type sff or la converted to pdf/wav
|
# @brief send email with text and attachment of type sff or la converted to pdf/wav
|
||||||
#
|
#
|
||||||
|
@ -149,95 +103,84 @@ def uniqueName(directory,basename,suffix):
|
||||||
# @param mail_type containing either "sff" or "la"
|
# @param mail_type containing either "sff" or "la"
|
||||||
# @param text a string containing the text of the first part of the mail
|
# @param text a string containing the text of the first part of the mail
|
||||||
# @param attachment name of the file to send as attachment
|
# @param attachment name of the file to send as attachment
|
||||||
def sendMIMEMail(mail_from,mail_to,mail_subject,mail_type,text,attachment):
|
def sendMIMEMail(mail_from, mail_to, mail_subject, mail_type,
|
||||||
import email.MIMEBase,email.MIMEText,email.MIMEAudio,email.Encoders,encodings.ascii,os,sys,popen2,capisuite
|
text, attachment):
|
||||||
msg = email.MIMEBase.MIMEBase("multipart","mixed")
|
import email.MIMEBase, email.MIMEText, email.MIMEAudio, email.Encoders
|
||||||
msg['Subject']=mail_subject
|
import encodings.ascii, os
|
||||||
msg['From']=mail_from
|
|
||||||
msg['To']=mail_to
|
|
||||||
|
|
||||||
msg.preamble = 'This is a Multipart-MIME-message. Please use a capable mailer.\n'
|
msg = email.MIMEBase.MIMEBase("multipart","mixed")
|
||||||
msg.epilogue = '' # To guarantee the message ends with a newline
|
msg['Subject']=mail_subject
|
||||||
|
msg['From']=mail_from
|
||||||
|
msg['To']=mail_to
|
||||||
|
|
||||||
basename=attachment[:attachment.rindex('.')+1]
|
msg.preamble = 'This is a Multipart-MIME-message. Please use a capable mailer.\n'
|
||||||
try:
|
msg.epilogue = '' # To guarantee the message ends with a newline
|
||||||
if (mail_type=="sff"): # normal fax file
|
|
||||||
# sff -> tif
|
basepath = os.path.splitext(attachment)[0]
|
||||||
ret=os.spawnlp(os.P_WAIT,"sfftobmp","sfftobmp","-tif",attachment,"%stif" % basename)
|
basename = os.path.basename(basepath)
|
||||||
if (ret or not os.access("%stif" % basename,os.F_OK)):
|
try:
|
||||||
raise "conv-error","Error while converting sff to tif. File damaged or sfftobmp not installed?"
|
if mail_type == "sff": # normal fax file
|
||||||
# tif -> ps -> pdf
|
# convert sff -> tif
|
||||||
# the first pipe must be handled by the shell so that the output of
|
sff2tif(attachment, "%s.tif" % basepath)
|
||||||
# of ps2pdf can be read immediately. Handling this shell in Python
|
# convert tif -> ps -> pdf
|
||||||
# leads to an overflow of the ps2pdf output pipe...
|
cmd = "tiff2ps -a %s | ps2pdf - -" % escape("%s.tif" %basepath)
|
||||||
command="tiff2ps -a %s | ps2pdf - -" % escape("%stif" % basename)
|
try:
|
||||||
tiff2pdf=popen2.Popen3(command)
|
status, content = commands.getstatusoutput(cmd)
|
||||||
if (tiff2pdf.poll()!=-1):
|
finally:
|
||||||
raise "conv-error","Error while calling tiff2ps or ps2pdf. Not installed?"
|
os.unlink("%s.tif" % basepath)
|
||||||
tiff2pdf.tochild.close() # we don't need the input pipe
|
if status:
|
||||||
# create attachment with pdf stream
|
raise ConvertionError("Error while calling tiff2ps or ps2pdf. "
|
||||||
filepart = email.MIMEBase.MIMEBase("application","pdf",name="%spdf" % os.path.basename(basename))
|
"Not installed?")
|
||||||
filepart.add_header('Content-Disposition','attachment',filename="%spdf" % os.path.basename(basename))
|
filepart = email.MIMEBase.MIMEBase("application","pdf",
|
||||||
filepart.set_payload(tiff2pdf.fromchild.read())
|
name = "%s.pdf" % basename)
|
||||||
tiff2pdf.fromchild.close()
|
filepart.add_header('Content-Disposition','attachment',
|
||||||
ret=tiff2pdf.wait()
|
filename = "%s.pdf" % basename)
|
||||||
if (ret!=0):
|
filepart.set_payload(content)
|
||||||
raise "conv-error","Error %i occured during tiff2ps or ps2pdf" % ret
|
email.Encoders.encode_base64(filepart)
|
||||||
os.unlink("%stif" % basename)
|
elif mail_type == "cff": # color fax file
|
||||||
email.Encoders.encode_base64(filepart)
|
# convert cff -> ps
|
||||||
elif (mail_type=="cff"): # color fax file
|
cff2ps(attachment, "%s.ps" % basepath)
|
||||||
# cff -> ps
|
# convert ps -> pdf
|
||||||
ret=os.spawnlp(os.P_WAIT,"jpeg2ps","jpeg2ps","-m",attachment,"-o","%sps" % basename)
|
cmd = "ps2pdf %s -" % escape("%s.ps" % basepath)
|
||||||
if (ret or not os.access("%sps" % basename,os.F_OK)):
|
try:
|
||||||
raise "conv-error","Can't convert cff to ps. File damaged or jpeg2ps not installed?"
|
status, content = commands.getstatusoutput(cmd)
|
||||||
# tif -> ps -> pdf
|
finally:
|
||||||
# the first pipe must be handled by the shell so that the output of
|
os.unlink("%s.ps" % basepath)
|
||||||
# of ps2pdf can be read immediately. Handling this shell in Python
|
if status:
|
||||||
# leads to an overflow of the ps2pdf output pipe...
|
raise ConvertionError("Error while calling ps2pdf. "
|
||||||
command="ps2pdf %s -" % escape("%sps" % basename)
|
"Not installed?")
|
||||||
ps2pdf=popen2.Popen3(command)
|
filepart = email.MIMEBase.MIMEBase("application", "pdf",
|
||||||
if (ps2pdf.poll()!=-1):
|
name = "%s.pdf" % basename)
|
||||||
raise "conv-error","Error while calling ps2pdf. Not installed?"
|
filepart.add_header('Content-Disposition', 'attachment',
|
||||||
ps2pdf.tochild.close() # we don't need the input pipe
|
filename="%s.pdf" % basename)
|
||||||
# create attachment with pdf stream
|
filepart.set_payload(content)
|
||||||
filepart = email.MIMEBase.MIMEBase("application","pdf",name="%spdf" % os.path.basename(basename))
|
email.Encoders.encode_base64(filepart)
|
||||||
filepart.add_header('Content-Disposition','attachment',filename="%spdf" % os.path.basename(basename))
|
elif mail_type == "la": # voice file
|
||||||
filepart.set_payload(ps2pdf.fromchild.read())
|
# la -> wav
|
||||||
ps2pdf.fromchild.close()
|
la2wav(attachment, "%s.wav" % basepath)
|
||||||
ret=ps2pdf.wait()
|
content = open("%s.wav" % basepath).read()
|
||||||
if (ret!=0):
|
os.unlink("%s.wav" % basepath)
|
||||||
raise "conv-error","Error %i occured during ps2pdf" % ret
|
filepart = email.MIMEAudio.MIMEAudio(content, "x-wav",
|
||||||
os.unlink("%sps" % basename)
|
email.Encoders.encode_base64,
|
||||||
email.Encoders.encode_base64(filepart)
|
name = "%s.wav" % basename)
|
||||||
elif (mail_type=="la"): # voice file
|
filepart.add_header('Content-Disposition', 'attachment',
|
||||||
# la -> wav
|
filename = "%s.wav" % basename)
|
||||||
# don't use stdout as sox needs a file to be able to seek in it otherwise the header will be incomplete
|
textpart = email.MIMEText.MIMEText(text)
|
||||||
ret = os.spawnlp(os.P_WAIT,"sox","sox",attachment,"-w","%swav" % basename)
|
msg.attach(textpart)
|
||||||
if (ret or not os.access("%swav" % basename,os.R_OK)):
|
msg.attach(filepart)
|
||||||
raise "conv-error","Error while calling sox. File damaged or sox not installed?"
|
except ConvertionError, errormessage:
|
||||||
filepart = email.MIMEAudio.MIMEAudio(open("%swav" % basename).read(),"x-wav",email.Encoders.encode_base64,name="%swav" % os.path.basename(basename))
|
text = [text, ''
|
||||||
filepart.add_header('Content-Disposition','attachment',filename="%swav" % os.path.basename(basename))
|
'The following error occured while converting file:',
|
||||||
os.unlink("%swav" % basename)
|
str(errormessage), ''
|
||||||
textpart = email.MIMEText.MIMEText(text)
|
'Please talk to your friendly administrator.', ''
|
||||||
msg.attach(textpart)
|
]
|
||||||
msg.attach(filepart)
|
# todo: add encoding (at least as example)
|
||||||
except "conv-error",errormessage:
|
# todo: use latin-1 as std-encoding instead of ascii
|
||||||
text="%s\n\nERROR occured while converting file: %s\nPlease talk to your friendly administrator.\n" % (text,errormessage)
|
textpart = email.MIMEText.MIMEText('\n'.join(text))
|
||||||
textpart = email.MIMEText.MIMEText(text)
|
msg.attach(textpart)
|
||||||
msg.attach(textpart)
|
|
||||||
|
return __sendmail(mail_from, mail_to, msg)
|
||||||
|
|
||||||
sendmail = popen2.Popen3("sendmail -t -f %s" % escape(mail_from))
|
|
||||||
if (sendmail.poll()!=-1):
|
|
||||||
capisuite.error("Error while calling sendmail. Not installed?\n")
|
|
||||||
return
|
|
||||||
sendmail.tochild.write(msg.as_string())
|
|
||||||
sendmail.tochild.close()
|
|
||||||
sendmail.fromchild.close()
|
|
||||||
ret=sendmail.wait()
|
|
||||||
if (ret!=0):
|
|
||||||
capisuite.error("Error while calling sendmail, return code=%i" % ret)
|
|
||||||
else:
|
|
||||||
capisuite.log("sendmail finished successful",3)
|
|
||||||
|
|
||||||
# @brief send a simple text email
|
# @brief send a simple text email
|
||||||
#
|
#
|
||||||
|
@ -247,28 +190,21 @@ def sendMIMEMail(mail_from,mail_to,mail_subject,mail_type,text,attachment):
|
||||||
# @param mail_to the To: address for the mail
|
# @param mail_to the To: address for the mail
|
||||||
# @param mail_subject the subject of the mail
|
# @param mail_subject the subject of the mail
|
||||||
# @param text a string containing the text of the first part of the mail
|
# @param text a string containing the text of the first part of the mail
|
||||||
def sendSimpleMail(mail_from,mail_to,mail_subject,text):
|
#
|
||||||
import email.Encoders,email.MIMEText,encodings.ascii,popen2,sys,capisuite
|
# @result returns true on success
|
||||||
# Create a text/plain message. Don't forget to change charset here
|
def sendSimpleMail(mail_from, mail_to, mail_subject, text):
|
||||||
# if you want to use non-us-ascii characters in the mail!
|
#import email.Encoders, email.MIMEText, encodings.ascii
|
||||||
msg = email.MIMEText.MIMEText(text)
|
|
||||||
|
|
||||||
msg['Subject'] = mail_subject
|
# Create a text/plain message. Don't forget to change charset here
|
||||||
msg['From'] = mail_from
|
# if you want to use non-us-ascii characters in the mail!
|
||||||
msg['To'] = mail_to
|
# todo: add encoding anyway (at least as example)
|
||||||
|
# todo: use latin-1 as std-encoding instead of ascii
|
||||||
sendmail = popen2.Popen3("sendmail -t -f %s" % escape(mail_from))
|
import email.MIMEText
|
||||||
if (sendmail.poll()!=-1):
|
msg = email.MIMEText.MIMEText(text)
|
||||||
capisuite.error("Error while calling sendmail. Not installed?\n")
|
msg['Subject'] = mail_subject
|
||||||
return
|
msg['From'] = mail_from
|
||||||
sendmail.tochild.write(msg.as_string())
|
msg['To'] = mail_to
|
||||||
sendmail.tochild.close()
|
return __sendmail(mail_from, mail_to, msg)
|
||||||
sendmail.fromchild.close()
|
|
||||||
ret=sendmail.wait()
|
|
||||||
if (ret!=0):
|
|
||||||
capisuite.error("Error while calling sendmail, return code=%i" % ret)
|
|
||||||
else:
|
|
||||||
capisuite.log("sendmail finished successful",3)
|
|
||||||
|
|
||||||
|
|
||||||
# @brief write description file for received fax or voice
|
# @brief write description file for received fax or voice
|
||||||
|
@ -279,157 +215,19 @@ def sendSimpleMail(mail_from,mail_to,mail_subject,text):
|
||||||
#
|
#
|
||||||
# @param filename the data filename (with extension!)
|
# @param filename the data filename (with extension!)
|
||||||
# @param content the content as string
|
# @param content the content as string
|
||||||
def writeDescription(filename,content):
|
def writeDescription(filename, content):
|
||||||
descr=open("%stxt" % filename[:filename.rindex('.')+1],"w")
|
from types import StringType
|
||||||
descr.write("# Description file for %s\n" % filename)
|
assert isinstance(content, StringType)
|
||||||
descr.write("# This if for internal use of CapiSuite.\n")
|
import capisuite.fileutils
|
||||||
descr.write("# Only change if you know what you do!!\n")
|
descrname = capisuite.fileutils.controlname(filename)
|
||||||
descr.write("[GLOBAL]\n")
|
descr = open(descrname, "w")
|
||||||
descr.write("filename=\"%s\"\n" % filename)
|
print >> descr, "# Description file for", filename
|
||||||
descr.write(content)
|
print >> descr, "# This if for internal use of CapiSuite."
|
||||||
descr.close()
|
print >> descr, "# Only change if you know what you do!"
|
||||||
|
print >> descr, "[GLOBAL]"
|
||||||
|
print >> descr, 'filename="%s"' % filename
|
||||||
|
print >> descr, content
|
||||||
|
descr.close()
|
||||||
|
|
||||||
# @brief say a german number
|
# sayNumber is now imported from capisuite.voice
|
||||||
#
|
|
||||||
# All numbers from 0 to 99 are said correctly, while all larger ones are
|
|
||||||
# split into numbers and only the numbers are said one after another.
|
|
||||||
# An input of "-" produces the word "unbekannt" (unknown)
|
|
||||||
#
|
|
||||||
# @param call reference to the call
|
|
||||||
# @param number the number to say
|
|
||||||
# @param curr_user the current user named
|
|
||||||
# @param config the ConfigParser instance holding the configuration info
|
|
||||||
# @param gender if the number is used in connection with a singular noun ("f" --> "eine Nachricht")
|
|
||||||
def sayNumber(call,number,curr_user,config,gender="-"):
|
|
||||||
import capisuite
|
|
||||||
if (number=="-" or number=="??"): # "??" is needed for backward compatibility to versions <= 0.4.1a
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"unbekannt.la"),1)
|
|
||||||
elif (gender!="-" and number in ("1","01")):
|
|
||||||
if (gender in ("n","m")):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"ein.la"),1)
|
|
||||||
else:
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"eine.la"),1)
|
|
||||||
elif (len(number)==2 and number[0]!="0"):
|
|
||||||
if (number[0]=="1"):
|
|
||||||
if (number[1]=="0"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"10.la"),1)
|
|
||||||
elif (number[1]=="1"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"11.la"),1)
|
|
||||||
elif (number[1]=="2"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"12.la"),1)
|
|
||||||
elif (number[1]=="3"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"13.la"),1)
|
|
||||||
elif (number[1]=="4"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"14.la"),1)
|
|
||||||
elif (number[1]=="5"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"15.la"),1)
|
|
||||||
elif (number[1]=="6"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"16.la"),1)
|
|
||||||
elif (number[1]=="7"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"17.la"),1)
|
|
||||||
elif (number[1]=="8"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"18.la"),1)
|
|
||||||
elif (number[1]=="9"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"19.la"),1)
|
|
||||||
else:
|
|
||||||
if (number[1]=="0"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"%s.la" % number),1)
|
|
||||||
elif (number[1]=="1"):
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"ein.la"),1)
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"und.la"),1)
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"%s0.la" % number[0]),1)
|
|
||||||
else:
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"%s.la" % number[1]),1)
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"und.la"),1)
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"%s0.la" % number[0]),1)
|
|
||||||
else:
|
|
||||||
for i in number:
|
|
||||||
capisuite.audio_send(call,getAudio(config,curr_user,"%s.la" % i),1)
|
|
||||||
|
|
||||||
# Old Log (for new changes see ChangeLog):
|
|
||||||
# Revision 1.14 2003/10/19 20:17:54 gernot
|
|
||||||
# - sendMIMEMail: better wording for some error messages during file conversion
|
|
||||||
#
|
|
||||||
# Revision 1.13 2003/07/21 17:44:07 gernot
|
|
||||||
# - forgot one import in last commit :-|
|
|
||||||
#
|
|
||||||
# Revision 1.12 2003/07/20 10:27:51 gernot
|
|
||||||
# - workaround for Python RuntimeError "cannot unmarshal code objects in
|
|
||||||
# restricted execution mode", thx to Sander Roest for finally finding
|
|
||||||
# this solution
|
|
||||||
#
|
|
||||||
# Revision 1.11 2003/06/16 10:20:36 gernot
|
|
||||||
# - use new multipage feature of jpeg2ps (requires special jpeg2ps version!)
|
|
||||||
#
|
|
||||||
# Revision 1.10 2003/05/25 13:38:30 gernot
|
|
||||||
# - support reception of color fax documents
|
|
||||||
#
|
|
||||||
# Revision 1.9 2003/04/24 21:04:20 gernot
|
|
||||||
# - replace functions deprecated in Python 2.2.2 (mainly related to the email
|
|
||||||
# module)
|
|
||||||
#
|
|
||||||
# Revision 1.8 2003/04/24 14:03:18 gernot
|
|
||||||
# - shortened some long lines
|
|
||||||
# - added function escape which escapes a string for shell usage
|
|
||||||
# - escape mail addresses given to sendmail
|
|
||||||
#
|
|
||||||
# Revision 1.7 2003/04/16 07:16:35 gernot
|
|
||||||
# - fixed pipe buffer overflow for conversion of long fax documents to PDF
|
|
||||||
#
|
|
||||||
# Revision 1.6 2003/04/10 21:29:51 gernot
|
|
||||||
# - support empty destination number for incoming calls correctly (austrian
|
|
||||||
# telecom does this (sic))
|
|
||||||
# - core now returns "-" instead of "??" for "no number available" (much nicer
|
|
||||||
# in my eyes)
|
|
||||||
# - new wave file used in remote inquiry for "unknown number"
|
|
||||||
#
|
|
||||||
# Revision 1.5 2003/04/10 20:54:44 gernot
|
|
||||||
# - allow multiple mail addresses to be set as fax_email or voice_email
|
|
||||||
#
|
|
||||||
# Revision 1.4 2003/04/08 07:59:56 gernot
|
|
||||||
# - replace some wrong space indentations by tabs...
|
|
||||||
#
|
|
||||||
# Revision 1.3 2003/04/07 15:58:37 gernot
|
|
||||||
# - attachments to sent e-mails now get a valid filename
|
|
||||||
#
|
|
||||||
# Revision 1.2 2003/03/20 09:12:42 gernot
|
|
||||||
# - error checking for reading of configuration improved, many options got
|
|
||||||
# optional, others produce senseful error messages now if not found,
|
|
||||||
# fixes bug# 531, thx to Dieter Pelzel for reporting
|
|
||||||
#
|
|
||||||
# Revision 1.1.1.1 2003/02/19 08:19:54 gernot
|
|
||||||
# initial checkin of 0.4
|
|
||||||
#
|
|
||||||
# Revision 1.8 2003/02/10 14:03:34 ghillie
|
|
||||||
# - cosmetical fixes in sendMIMEMail
|
|
||||||
# - added wait() calls to popen objects, otherwise processes will hang
|
|
||||||
# after CapiSuite has run them (i.e. sendmail stays as Zombie)
|
|
||||||
#
|
|
||||||
# Revision 1.7 2003/02/03 14:47:49 ghillie
|
|
||||||
# - sayNumber now works correctly for all numbers between 0 and 99
|
|
||||||
# (in german). Added the necessary voice files and improved "1"-"9"
|
|
||||||
#
|
|
||||||
# Revision 1.6 2003/01/27 21:55:10 ghillie
|
|
||||||
# - getOption returns now None if option isn't found at all (no exception)
|
|
||||||
# - removed capisuite.log from uniqueName() (not possible in capisuitefax!)
|
|
||||||
# - added some missing "import capisuite" statements
|
|
||||||
#
|
|
||||||
# Revision 1.5 2003/01/27 19:24:29 ghillie
|
|
||||||
# - updated to use new configuration files for fax & answering machine
|
|
||||||
#
|
|
||||||
# Revision 1.4 2003/01/19 12:02:40 ghillie
|
|
||||||
# - use capisuite log functions instead of stdout/stderr
|
|
||||||
#
|
|
||||||
# Revision 1.3 2003/01/17 15:08:17 ghillie
|
|
||||||
# - typos as usual...
|
|
||||||
# - added sendSimpleMail for normal text messages
|
|
||||||
#
|
|
||||||
# Revision 1.2 2003/01/15 15:52:49 ghillie
|
|
||||||
# - readConfig now takes filename as parameter
|
|
||||||
# - uniqueName: countfile now has basename as prefix, fixed small bug
|
|
||||||
# in countfile creation
|
|
||||||
# - sendMail: added .la->.wav convertion, error messages now included
|
|
||||||
# in messages to user
|
|
||||||
# - writeDescription: [data] renamed to [global]
|
|
||||||
# - sayNumber: small fixes
|
|
||||||
#
|
|
||||||
|
|
|
@ -114,6 +114,55 @@ fax_headline="Sent by CapiSuite (www.CapiSuite.de)"
|
||||||
# messages.
|
# messages.
|
||||||
fax_email_from="capisuite daemon <root>"
|
fax_email_from="capisuite daemon <root>"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
############################# Mail settings ###################################
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
#########
|
||||||
|
# defined for fax receive: call_from, call_to, stationID, bitRate,
|
||||||
|
# resolution color, numPages, filename, hostname
|
||||||
|
|
||||||
|
[MailFaxReceived]
|
||||||
|
subject = Received a fax from %(call_from)s to %(call_to)s
|
||||||
|
text =
|
||||||
|
You got a fax from %(call_from)s to %(call_to)s
|
||||||
|
Station ID: %(stationID)s
|
||||||
|
Transmission Details: bit rate %(bitRate)i %(resolution)s %(color)s
|
||||||
|
Pages: %(numPages)i
|
||||||
|
|
||||||
|
See attached file.
|
||||||
|
The original file was saved to file://%(filename)s on host "%(hostname)s".
|
||||||
|
|
||||||
|
#########
|
||||||
|
# defined for fax send: addressee, dialstring, subject, filename, tries,
|
||||||
|
# result, resultB3, filename, hostname
|
||||||
|
|
||||||
|
[MailFaxSent]
|
||||||
|
subject = Fax to %(addressee)s (%(dialstring)s) sent successfully.
|
||||||
|
text =
|
||||||
|
Your fax job to %(addressee)s (%(dialstring)s) was sent successfully.
|
||||||
|
|
||||||
|
Subject: %(subject)s
|
||||||
|
Filename: %(filename)s
|
||||||
|
Number of tries: %(tries)i
|
||||||
|
Last result: 0x%(result)x/0x%(resultB3)x
|
||||||
|
|
||||||
|
It was moved to file://%(filename)s on host %(hostname)s.
|
||||||
|
|
||||||
|
|
||||||
|
[MailFaxFailed]
|
||||||
|
subject = Fax to %(addressee)s (%(dialstring)s) FAILED.
|
||||||
|
text =
|
||||||
|
I'm sorry, but your fax job to %(addressee)s (%(dialstring)s) failed finally.
|
||||||
|
|
||||||
|
Subject: %(subject)s
|
||||||
|
Filename: %(filename)s
|
||||||
|
Number of tries: %(tries)i
|
||||||
|
Last result: 0x%(result)x/0x%(resultB3)x
|
||||||
|
|
||||||
|
It was moved to file://%(filename)s on host %(hostname)s.
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
############################# user settings ###################################
|
############################# user settings ###################################
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
351
scripts/idle.py
351
scripts/idle.py
|
@ -1,3 +1,5 @@
|
||||||
|
# -*- mode: python ; coding: iso_8859_15 -*-
|
||||||
|
#
|
||||||
# idle.py - default script for capisuite
|
# idle.py - default script for capisuite
|
||||||
# ---------------------------------------------
|
# ---------------------------------------------
|
||||||
# copyright : (C) 2002 by Gernot Hillier
|
# copyright : (C) 2002 by Gernot Hillier
|
||||||
|
@ -10,247 +12,140 @@
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
|
|
||||||
import os,re,time,pwd,fcntl
|
import os, time, pwd, fcntl
|
||||||
|
|
||||||
# capisuite stuff
|
# capisuite stuff
|
||||||
import capisuite,cs_helpers
|
#import capisuite
|
||||||
|
import capisuite.fax
|
||||||
|
from capisuite.config import NoOptionError
|
||||||
|
import capisuite.core as core
|
||||||
|
|
||||||
|
# todo: eliminate this
|
||||||
|
import cs_helpers
|
||||||
|
|
||||||
|
# sendfax is now imported from capisuite.fax
|
||||||
|
|
||||||
|
from capisuite.fileutils import _releaseLock, _getLock, LockTakenError
|
||||||
|
|
||||||
def idle(capi):
|
def idle(capi):
|
||||||
config=cs_helpers.readConfig()
|
|
||||||
spool=cs_helpers.getOption(config,"","spool_dir")
|
|
||||||
if (spool==None):
|
|
||||||
capisuite.error("global option spool_dir not found.")
|
|
||||||
return
|
|
||||||
|
|
||||||
done=os.path.join(spool,"done")
|
|
||||||
failed=os.path.join(spool,"failed")
|
|
||||||
|
|
||||||
if (not os.access(done,os.W_OK) or not os.access(failed,os.W_OK)):
|
config = capisuite.config.readGlobalConfig()
|
||||||
capisuite.error("Can't read/write to the necessary spool dirs")
|
try:
|
||||||
return
|
spool = config.get('GLOBAL', "spool_dir")
|
||||||
|
max_tries = config.getint('GLOBAL', "send_tries")
|
||||||
|
delays = config.getList('GLOBAL', "send_delays")
|
||||||
|
except NoOptionError, err:
|
||||||
|
core.error("global option %s not found." % err.option)
|
||||||
|
return
|
||||||
|
|
||||||
userlist=config.sections()
|
# todo: implement config.getQueue(queue,user=None)
|
||||||
userlist.remove('GLOBAL')
|
doneQ = os.path.join(spool, "done")
|
||||||
|
failedQ = os.path.join(spool, "failed")
|
||||||
|
|
||||||
for user in userlist: # search in all user-specified sendq's
|
if not os.access(doneQ, os.W_OK) or not os.access(failedQ, os.W_OK):
|
||||||
userdata=pwd.getpwnam(user)
|
core.error("Can't read/write to the necessary spool dirs")
|
||||||
outgoing_nr=cs_helpers.getOption(config,user,"outgoing_MSN","")
|
return
|
||||||
if (outgoing_nr==""):
|
|
||||||
incoming_nrs=cs_helpers.getOption(config,user,"fax_numbers","")
|
|
||||||
if (incoming_nrs==""):
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
outgoing_nr=(incoming_nrs.split(','))[0]
|
|
||||||
|
|
||||||
udir=cs_helpers.getOption(config,"","fax_user_dir")
|
# search in all user-specified sendq's
|
||||||
if (udir==None):
|
for user in config.listUsers():
|
||||||
capisuite.error("global option fax_user_dir not found.")
|
outgoing_num = config.getUser(user, "outgoing_msn")
|
||||||
return
|
if not outgoing_num:
|
||||||
udir=os.path.join(udir,user)
|
incoming_nums = config.getUser(user, "fax_numbers")
|
||||||
sendq=os.path.join(udir,"sendq")
|
if not incoming_nums:
|
||||||
if (not os.access(udir,os.F_OK)):
|
continue
|
||||||
os.mkdir(udir,0700)
|
outgoing_num = incoming_nums.split(',')[0].strip()
|
||||||
os.chown(udir,userdata[2],userdata[3])
|
|
||||||
if (not os.access(sendq,os.F_OK)):
|
|
||||||
os.mkdir(sendq,0700)
|
|
||||||
os.chown(sendq,userdata[2],userdata[3])
|
|
||||||
|
|
||||||
files=os.listdir(sendq)
|
mailaddress = config.getUser(user, "fax_email", user)
|
||||||
files=filter (lambda s: re.match("fax-.*\.txt",s),files)
|
fromaddress = config.getUser(user, "fax_email_from", user)
|
||||||
|
|
||||||
for job in files:
|
for jobnum, controlfile in capisuite.fax.getQueueFiles(config, user):
|
||||||
job_fax="%ssff" % job[:-3]
|
assert controlfile == os.path.abspath(controlfile)
|
||||||
real_user_c=os.stat(os.path.join(sendq,job)).st_uid
|
try:
|
||||||
real_user_j=os.stat(os.path.join(sendq,job_fax)).st_uid
|
# lock the job so that it isn't deleted while sending
|
||||||
if (real_user_j!=pwd.getpwnam(user)[2] or real_user_c!=pwd.getpwnam(user)[2]):
|
lock = _getLock(forfile=controlfile, blocking=0)
|
||||||
capisuite.error("job %s seems to be manipulated (wrong uid)! Ignoring..." % os.path.join(sendq,job_fax))
|
except LockTakenError:
|
||||||
continue
|
# if we didn't get the lock, continue with next job
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
control = capisuite.config.JobDescription(controlfile)
|
||||||
|
|
||||||
lockfile=open(os.path.join(sendq,"%slock" % job[:-3]),"w")
|
fax_file = control.get('filename')
|
||||||
# read directory contents
|
assert fax_file == os.path.abspath(fax_file)
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_EX) # lock so that it isn't deleted while sending
|
|
||||||
|
|
||||||
if (not os.access(os.path.join(sendq,job),os.W_OK)): # perhaps it was cancelled?
|
# both the job control file and the fax file must have
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_UN)
|
# the users uid
|
||||||
lockfile.close()
|
uid = pwd.getpwnam(user).pw_uid
|
||||||
os.unlink(os.path.join(sendq,"%slock" % job[:-3]))
|
if os.stat(controlfile).st_uid != uid or \
|
||||||
continue
|
os.stat(fax_file).st_uid != uid:
|
||||||
|
core.error("job %s seems to be manipulated (wrong uid)! "
|
||||||
|
"Ignoring..." % controlfile)
|
||||||
|
_releaseLock(lock)
|
||||||
|
continue
|
||||||
|
|
||||||
control=cs_helpers.readConfig(os.path.join(sendq,job))
|
# todo: describe what is tested here
|
||||||
# set DST value to -1 (unknown), as strptime sets it wrong for some reason
|
# perhaps it was cancelled?
|
||||||
starttime=(time.strptime(control.get("GLOBAL","starttime")))[0:8]+(-1,)
|
if not os.access(controlfile, os.W_OK):
|
||||||
starttime=time.mktime(starttime)
|
_releaseLock(lock)
|
||||||
if (starttime>time.time()):
|
continue
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_UN)
|
|
||||||
lockfile.close()
|
|
||||||
os.unlink(os.path.join(sendq,"%slock" % job[:-3]))
|
|
||||||
continue
|
|
||||||
|
|
||||||
tries=control.getint("GLOBAL","tries")
|
# set DST value to -1 (unknown), as strptime sets it wrong
|
||||||
dialstring=control.get("GLOBAL","dialstring")
|
# for some reason
|
||||||
addressee=cs_helpers.getOption(control,"GLOBAL","addressee","")
|
starttime = time.strptime(control.get("starttime"))[:-1]+(-1, )
|
||||||
subject=cs_helpers.getOption(control,"GLOBAL","subject","")
|
starttime = time.mktime(starttime)
|
||||||
mailaddress=cs_helpers.getOption(config,user,"fax_email","")
|
if starttime > time.time():
|
||||||
if (mailaddress==""):
|
_releaseLock(lock)
|
||||||
mailaddress=user
|
continue
|
||||||
fromaddress=cs_helpers.getOption(config,user,"fax_email_from","")
|
|
||||||
if (fromaddress==""):
|
|
||||||
fromaddress=user
|
|
||||||
|
|
||||||
capisuite.log("job %s from %s to %s initiated" % (job_fax,user,dialstring),1)
|
sendinfo = {
|
||||||
result,resultB3 = sendfax(capi,os.path.join(sendq,job_fax),outgoing_nr,dialstring,user,config)
|
'outgoing_num': outgoing_num,
|
||||||
tries+=1
|
'dialstring': control.get("dialstring")
|
||||||
capisuite.log("job %s: result was %x,%x" % (job_fax,result,resultB3),1)
|
}
|
||||||
|
# these options may overwrite the global settings per job
|
||||||
|
for n in ('stationID', 'headline'):
|
||||||
|
if control.has_option(n):
|
||||||
|
sendinfo[n] = control.get(n)
|
||||||
|
|
||||||
if (result in (0,0x3400,0x3480,0x3490,0x349f) and resultB3==0):
|
core.log("job %s from %s to %s initiated" %
|
||||||
movejob(job_fax,sendq,done,user)
|
(jobnum, user, sendinfo['dialstring']), 1)
|
||||||
capisuite.log("job %s: finished successfully" % job_fax,1)
|
result, resultB3 = capisuite.fax.sendfax(config, user, capi,
|
||||||
mailtext="Your fax job to %s (%s) was sent successfully.\n\n" \
|
fax_file, **sendinfo)
|
||||||
"Subject: %s\nFilename: %s\nNeeded tries: %i\n" \
|
core.log("job %s: result was %x, %x" % \
|
||||||
"Last result: 0x%x/0x%x\n\nIt was moved to " \
|
(jobnum, result, resultB3), 1)
|
||||||
"file://%s on host \"%s\"" % (addressee,dialstring, \
|
sendinfo['result'] = result
|
||||||
subject,job_fax,tries,result,resultB3, \
|
sendinfo['resultB3'] = resultB3
|
||||||
os.path.join(done,"%s-%s" % (user,job_fax)), \
|
|
||||||
os.uname()[1])
|
# todo: use symbolic names for these results to be more
|
||||||
cs_helpers.sendSimpleMail(fromaddress,mailaddress,
|
# meaningfull
|
||||||
"Fax to %s (%s) sent successfully." % (addressee,dialstring),
|
send_ok = resultB3 == 0 \
|
||||||
mailtext)
|
and result in (0, 0x3400, 0x3480, 0x3490, 0x349f)
|
||||||
else:
|
tries = control.getint("tries") +1
|
||||||
max_tries=int(cs_helpers.getOption(config,"","send_tries","10"))
|
if send_ok:
|
||||||
delays=cs_helpers.getOption(config,"","send_delays","60,60,60,300,300,3600,3600,18000,36000").split(",")
|
core.log("job %s: finished successfully" % jobnum, 1)
|
||||||
delays=map(int,delays)
|
control = capisuite.fax.moveJob(controlfile, doneQ, user)
|
||||||
if ((tries-1)<len(delays)):
|
sendinfo.update(control.items())
|
||||||
next_delay=delays[tries-1]
|
sendinfo['hostname'] = os.uname()[1]
|
||||||
else:
|
cs_helpers.sendSimpleMail(
|
||||||
next_delay=delays[-1]
|
fromaddress, mailaddress,
|
||||||
starttime=time.time()+next_delay
|
config.get('MailFaxSent', 'subject') % sendinfo,
|
||||||
capisuite.log("job %s: delayed for %i seconds" % (job_fax,next_delay),2)
|
config.get('MailFaxSent', 'text') % sendinfo)
|
||||||
cs_helpers.writeDescription(os.path.join(sendq,job_fax), \
|
elif tries >= max_tries:
|
||||||
"dialstring=\"%s\"\nstarttime=\"%s\"\ntries=\"%i\"\n" \
|
# too many ties, send failed
|
||||||
"user=\"%s\"\naddressee=\"%s\"\nsubject=\"%s\"\n" \
|
core.log("job %s: failed finally" % jobnum, 1)
|
||||||
% (dialstring,time.ctime(starttime),tries,user, \
|
control = capisuite.fax.moveJob(controlfile, failedQ, user)
|
||||||
addressee,subject))
|
sendinfo.update(control.items())
|
||||||
if (tries>=max_tries):
|
cs_helpers.sendSimpleMail(
|
||||||
movejob(job_fax,sendq,failed,user)
|
fromaddress, mailaddress,
|
||||||
capisuite.log("job %s: failed finally" % job_fax,1)
|
config.get('MailFaxFailed', 'subject') % sendinfo,
|
||||||
mailtext="I'm sorry, but your fax job to %s (%s) " \
|
config.get('MailFaxFailed', 'text') % sendinfo)
|
||||||
"failed finally.\n\nSubject: %s\n" \
|
else:
|
||||||
"Filename: %s\nTries: %i\n" \
|
# delay next try
|
||||||
"Last result: 0x%x/0x%x\n\n" \
|
next_delay = int(delays[ min(len(delays),tries) -1 ])
|
||||||
"It was moved to file://%s-%s on host %s.\n\n" \
|
core.log("job %s: delayed for %i seconds" % \
|
||||||
% (addressee,dialstring,subject,job_fax,tries,result, \
|
(jobnum, next_delay), 2)
|
||||||
resultB3,os.path.join(failed,user),job_fax,os.uname()[1])
|
starttime = time.time() + next_delay
|
||||||
cs_helpers.sendSimpleMail(fromaddress,mailaddress,
|
control.set('starttime', time.ctime(starttime))
|
||||||
"Fax to %s (%s) FAILED." % (addressee,dialstring),
|
control.set('tries', tries)
|
||||||
mailtext)
|
control.write(controlfile)
|
||||||
|
finally:
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_UN)
|
_releaseLock(lock)
|
||||||
lockfile.close()
|
|
||||||
os.unlink("%slock" % os.path.join(sendq,job[:-3]))
|
|
||||||
|
|
||||||
def sendfax(capi,job,outgoing_nr,dialstring,user,config):
|
|
||||||
try:
|
|
||||||
controller=int(cs_helpers.getOption(config,"","send_controller","1"))
|
|
||||||
timeout=int(cs_helpers.getOption(config,user,"outgoing_timeout","60"))
|
|
||||||
stationID=cs_helpers.getOption(config,user,"fax_stationID")
|
|
||||||
if (stationID==None):
|
|
||||||
capisuite.error("Warning: fax_stationID for user %s not set" % user)
|
|
||||||
stationID=""
|
|
||||||
headline=cs_helpers.getOption(config,user,"fax_headline","")
|
|
||||||
(call,result)=capisuite.call_faxG3(capi,controller,outgoing_nr,dialstring,timeout,stationID,headline)
|
|
||||||
if (result!=0):
|
|
||||||
return(result,0)
|
|
||||||
capisuite.fax_send(call,job)
|
|
||||||
return(capisuite.disconnect(call))
|
|
||||||
except capisuite.CallGoneError:
|
|
||||||
return(capisuite.disconnect(call))
|
|
||||||
|
|
||||||
def movejob(job,olddir,newdir,user):
|
|
||||||
os.rename(os.path.join(olddir,job),os.path.join(newdir,"%s-%s" % (user,job)))
|
|
||||||
os.rename(os.path.join(olddir,"%stxt" % job[:-3]),os.path.join(newdir, "%s-%stxt" % (user,job[:-3])))
|
|
||||||
|
|
||||||
#
|
|
||||||
# History:
|
|
||||||
#
|
|
||||||
# Old Log (for new changes see ChangeLog):
|
|
||||||
# Revision 1.11 2003/12/02 18:50:09 gernot
|
|
||||||
# - fax_numbers is really allowed to be empty now...
|
|
||||||
#
|
|
||||||
# Revision 1.10 2003/10/03 13:42:09 gernot
|
|
||||||
# - added new options "fax_email_from" and "voice_email_from"
|
|
||||||
#
|
|
||||||
# Revision 1.9 2003/09/21 12:34:37 gernot
|
|
||||||
# - add 0x349f to list of normal results
|
|
||||||
#
|
|
||||||
# Revision 1.8 2003/06/26 11:53:17 gernot
|
|
||||||
# - fax jobs can be given an addressee and a subject now (resolves #18, reported
|
|
||||||
# by Achim Bohnet)
|
|
||||||
#
|
|
||||||
# Revision 1.7 2003/06/19 14:58:43 gernot
|
|
||||||
# - fax_numbers is now really optional (bug #23)
|
|
||||||
# - tries counter was wrongly reported (bug #29)
|
|
||||||
#
|
|
||||||
# Revision 1.6 2003/04/06 11:07:40 gernot
|
|
||||||
# - fix for 1-hour-delayed sending of fax (DST problem)
|
|
||||||
#
|
|
||||||
# Revision 1.5 2003/03/20 09:12:42 gernot
|
|
||||||
# - error checking for reading of configuration improved, many options got
|
|
||||||
# optional, others produce senseful error messages now if not found,
|
|
||||||
# fixes bug# 531, thx to Dieter Pelzel for reporting
|
|
||||||
#
|
|
||||||
# Revision 1.4 2003/03/13 11:09:58 gernot
|
|
||||||
# - use stricted permissions for saved files and created userdirs. Fixes
|
|
||||||
# bug #544
|
|
||||||
#
|
|
||||||
# Revision 1.3 2003/03/09 11:48:10 gernot
|
|
||||||
# - removed wrong unlock operation (lock not acquired at this moment!)
|
|
||||||
#
|
|
||||||
# Revision 1.2 2003/03/06 09:59:11 gernot
|
|
||||||
# - added "file://" as prefix to filenames in sent mails, thx to
|
|
||||||
# Achim Bohnet for this suggestion
|
|
||||||
#
|
|
||||||
# Revision 1.1.1.1 2003/02/19 08:19:54 gernot
|
|
||||||
# initial checkin of 0.4
|
|
||||||
#
|
|
||||||
# Revision 1.12 2003/02/18 09:54:22 ghillie
|
|
||||||
# - added missing lockfile deletions, corrected locking protocol
|
|
||||||
# -> fixes Bugzilla 23731
|
|
||||||
#
|
|
||||||
# Revision 1.11 2003/02/17 16:48:43 ghillie
|
|
||||||
# - do locking, so that jobs can be deleted
|
|
||||||
#
|
|
||||||
# Revision 1.10 2003/02/10 14:50:52 ghillie
|
|
||||||
# - revert logic of outgoing_MSN: it's overriding the first number of
|
|
||||||
# fax_numbers now
|
|
||||||
#
|
|
||||||
# Revision 1.9 2003/02/05 15:59:11 ghillie
|
|
||||||
# - search for *.txt instead of *.sff so no *.sff which is currently created
|
|
||||||
# by capisuitefax will be found!
|
|
||||||
#
|
|
||||||
# Revision 1.8 2003/01/31 11:22:00 ghillie
|
|
||||||
# - use different sendq's for each user (in his user_dir).
|
|
||||||
# - use prefix user- for names in done and failed
|
|
||||||
#
|
|
||||||
# Revision 1.7 2003/01/27 21:56:46 ghillie
|
|
||||||
# - mailaddress may be not set, that's the same as ""
|
|
||||||
# - use first entry of fax_numbers as outgoing MSN if it exists
|
|
||||||
#
|
|
||||||
# Revision 1.6 2003/01/27 19:24:29 ghillie
|
|
||||||
# - updated to use new configuration files for fax & answering machine
|
|
||||||
#
|
|
||||||
# Revision 1.5 2003/01/19 12:03:27 ghillie
|
|
||||||
# - use capisuite log functions instead of stdout/stderr
|
|
||||||
#
|
|
||||||
# Revision 1.4 2003/01/17 15:09:26 ghillie
|
|
||||||
# - updated to use new configuration file capisuite-script.conf
|
|
||||||
#
|
|
||||||
# Revision 1.3 2003/01/13 16:12:00 ghillie
|
|
||||||
# - renamed from idle.pyin to idle.py as all previously processed variables
|
|
||||||
# stay in the config file and cs_helpers.pyin now
|
|
||||||
#
|
|
||||||
# Revision 1.2 2002/12/16 13:07:22 ghillie
|
|
||||||
# - finished queue processing
|
|
||||||
#
|
|
||||||
# Revision 1.1 2002/12/14 13:53:19 ghillie
|
|
||||||
# - idle.py and incoming.py are now auto-created from *.pyin
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# -*- mode: python ; coding: iso_8859_15 -*-
|
||||||
|
#
|
||||||
# incoming.py - standard incoming script for capisuite
|
# incoming.py - standard incoming script for capisuite
|
||||||
# ----------------------------------------------------
|
# ----------------------------------------------------
|
||||||
# copyright : (C) 2002 by Gernot Hillier
|
# copyright : (C) 2002 by Gernot Hillier
|
||||||
|
@ -11,581 +13,419 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# general imports
|
# general imports
|
||||||
import time,os,re,string,pwd
|
import time, os
|
||||||
|
|
||||||
# CapiSuite imports
|
# CapiSuite imports
|
||||||
import capisuite,cs_helpers
|
import capisuite, cs_helpers
|
||||||
|
from capisuite.config import NoOptionError
|
||||||
|
import capisuite.fileutils as fileutils
|
||||||
|
import capisuite.fax
|
||||||
|
import capisuite.voice
|
||||||
|
from capisuite import core
|
||||||
|
say = capisuite.voice.say # shortcut
|
||||||
|
|
||||||
# @brief main function called by CapiSuite when an incoming call is received
|
def callIncoming(call, service, call_from, call_to):
|
||||||
#
|
"""
|
||||||
# It will decide if this call should be accepted, with which service and for
|
Main function called by CapiSuite when an incoming call is received.
|
||||||
# which user. The real call handling is done in faxIncoming and voiceIncoming.
|
|
||||||
#
|
|
||||||
# @param call reference to the call. Needed by all capisuite functions
|
|
||||||
# @param service one of SERVICE_FAXG3, SERVICE_VOICE, SERVICE_OTHER
|
|
||||||
# @param call_from string containing the number of the calling party
|
|
||||||
# @param call_to string containing the number of the called party
|
|
||||||
def callIncoming(call,service,call_from,call_to):
|
|
||||||
# read config file and search for call_to in the user sections
|
|
||||||
try:
|
|
||||||
config=cs_helpers.readConfig()
|
|
||||||
userlist=config.sections()
|
|
||||||
userlist.remove('GLOBAL')
|
|
||||||
curr_user=""
|
|
||||||
|
|
||||||
for u in userlist:
|
It will decide if this call should be accepted, with which service
|
||||||
if config.has_option(u,'voice_numbers'):
|
and for which user. The real call handling is done in faxIncoming
|
||||||
numbers=config.get(u,'voice_numbers')
|
and voiceIncoming.
|
||||||
if (call_to in numbers.split(',') or numbers=="*"):
|
|
||||||
if (service==capisuite.SERVICE_VOICE):
|
|
||||||
curr_user=u
|
|
||||||
curr_service=capisuite.SERVICE_VOICE
|
|
||||||
break
|
|
||||||
if (service==capisuite.SERVICE_FAXG3):
|
|
||||||
curr_user=u
|
|
||||||
curr_service=capisuite.SERVICE_FAXG3
|
|
||||||
break
|
|
||||||
|
|
||||||
if config.has_option(u,'fax_numbers'):
|
'call' reference to the call. Needed by all capisuite functions
|
||||||
numbers=config.get(u,'fax_numbers')
|
'service' one of SERVICE_FAXG3, SERVICE_VOICE, SERVICE_OTHER
|
||||||
if (call_to in numbers.split(',') or numbers=="*"):
|
'call_from' string containing the number of the calling party
|
||||||
if (service in (capisuite.SERVICE_FAXG3,capisuite.SERVICE_VOICE)):
|
'call_to' string containing the number of the called party
|
||||||
curr_user=u
|
"""
|
||||||
curr_service=capisuite.SERVICE_FAXG3
|
# convert into a python call handle
|
||||||
break
|
# TODO-gh: can't we get rid of this line?
|
||||||
|
call = core.Call(call, service, call_from, call_to)
|
||||||
|
# read config file and search for call.to_nr in the user sections
|
||||||
|
try:
|
||||||
|
config = capisuite.config.readGlobalConfig()
|
||||||
|
except IOError, e:
|
||||||
|
core.error("Error occured during config file reading: %s "
|
||||||
|
"Disconnecting..." % e)
|
||||||
|
call.reject(0x34A9)
|
||||||
|
return
|
||||||
|
|
||||||
except IOError,e:
|
for user in config.listUsers():
|
||||||
capisuite.error("Error occured during config file reading: %s Disconnecting..." % e)
|
# accept a voice call on 'voice_numbers'
|
||||||
capisuite.reject(call,0x34A9)
|
if config.has_option(user, 'voice_numbers'):
|
||||||
return
|
numbers = config.getList(user, 'voice_numbers')
|
||||||
# answer the call with the right service
|
if numbers == ["*"] or call.to_nr in numbers:
|
||||||
if (curr_user==""):
|
if service in (core.SERVICE_VOICE, ):
|
||||||
capisuite.log("call from %s to %s ignoring" % (call_from,call_to),1,call)
|
break
|
||||||
capisuite.reject(call,1)
|
# accept a voice or fax call on 'fax_numbers'
|
||||||
return
|
if config.has_option(user, 'fax_numbers'):
|
||||||
try:
|
numbers = config.getList(user, 'fax_numbers')
|
||||||
if (curr_service==capisuite.SERVICE_VOICE):
|
if numbers == ["*"] or call.to_nr in numbers:
|
||||||
delay=cs_helpers.getOption(config,curr_user,"voice_delay")
|
if service in (core.SERVICE_FAXG3, core.SERVICE_VOICE):
|
||||||
if (delay==None):
|
# set service type to 'fax'
|
||||||
capisuite.error("voice_delay not found for user %s! -> rejecting call" % curr_user)
|
service = core.SERVICE_FAXG3
|
||||||
capisuite.reject(call,0x34A9)
|
break
|
||||||
return
|
else:
|
||||||
capisuite.log("call from %s to %s for %s connecting with voice" % (call_from,call_to,curr_user),1,call)
|
# no matching entry found (no users as this number)
|
||||||
capisuite.connect_voice(call,int(delay))
|
call.log("call from %s to %s ignoring" % (call.from_nr, call.to_nr), 1)
|
||||||
voiceIncoming(call,call_from,call_to,curr_user,config)
|
call.reject(1)
|
||||||
elif (curr_service==capisuite.SERVICE_FAXG3):
|
return
|
||||||
faxIncoming(call,call_from,call_to,curr_user,config,0)
|
|
||||||
except capisuite.CallGoneError: # catch exceptions from connect_*
|
|
||||||
(cause,causeB3)=capisuite.disconnect(call)
|
|
||||||
capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call)
|
|
||||||
|
|
||||||
# @brief called by callIncoming when an incoming fax call is received
|
# answer the call with the right service
|
||||||
#
|
try:
|
||||||
# @param call reference to the call. Needed by all capisuite functions
|
if service == core.SERVICE_VOICE:
|
||||||
# @param call_from string containing the number of the calling party
|
voiceIncoming(config, user, call)
|
||||||
# @param call_to string containing the number of the called party
|
elif service == core.SERVICE_FAXG3:
|
||||||
# @param curr_user name of the user who is responsible for this
|
faxIncoming(config, user, call, 0)
|
||||||
# @param config ConfigParser instance holding the config data
|
else:
|
||||||
# @param already_connected 1 if we're already connected (that means we must switch to fax mode)
|
raise RuntimeError
|
||||||
def faxIncoming(call,call_from,call_to,curr_user,config,already_connected):
|
except NoOptionError, err:
|
||||||
try:
|
core.error("global option %s not found -> rejecting call" %
|
||||||
udir=cs_helpers.getOption(config,"","fax_user_dir")
|
err.option)
|
||||||
if (udir==None):
|
call.reject(0x34A9)
|
||||||
capisuite.error("global option fax_user_dir not found! -> rejecting call")
|
except fileutils.UnknownUserError:
|
||||||
capisuite.reject(call,0x34A9)
|
core.error("user %s is not a valid system user. Disconnecting." % user,
|
||||||
return
|
call)
|
||||||
udir=os.path.join(udir,curr_user)
|
call.reject(0x34A9)
|
||||||
if (not os.path.exists(udir)):
|
except core.CallGoneError:
|
||||||
userdata=pwd.getpwnam(curr_user)
|
causes = call.disconnect()
|
||||||
os.mkdir(udir,0700)
|
call.log("connection lost with cause 0x%x, 0x%x" % causes, 1)
|
||||||
os.chown(udir,userdata[2],userdata[3])
|
|
||||||
if (not os.path.exists(os.path.join(udir,"received"))):
|
|
||||||
userdata=pwd.getpwnam(curr_user)
|
|
||||||
os.mkdir(os.path.join(udir,"received"),0700)
|
|
||||||
os.chown(os.path.join(udir,"received"),userdata[2],userdata[3])
|
|
||||||
except KeyError:
|
|
||||||
capisuite.error("user %s is not a valid system user. Disconnecting" % curr_user,call)
|
|
||||||
capisuite.reject(call,0x34A9)
|
|
||||||
return
|
|
||||||
filename="" # assure the variable is defined...
|
|
||||||
faxInfo=None
|
|
||||||
try:
|
|
||||||
stationID=cs_helpers.getOption(config,curr_user,"fax_stationID")
|
|
||||||
if (stationID==None):
|
|
||||||
capisuite.error("Warning: fax_stationID not found for user %s -> using empty string" % curr_user)
|
|
||||||
stationID=""
|
|
||||||
headline=cs_helpers.getOption(config,curr_user,"fax_headline","") # empty string is no problem here
|
|
||||||
capisuite.log("call from %s to %s for %s connecting with fax" % (call_from,call_to,curr_user),1,call)
|
|
||||||
if (already_connected):
|
|
||||||
faxInfo=capisuite.switch_to_faxG3(call,stationID,headline)
|
|
||||||
else:
|
|
||||||
faxInfo=capisuite.connect_faxG3(call,stationID,headline,0)
|
|
||||||
if (faxInfo!=None and faxInfo[3]==1):
|
|
||||||
faxFormat="cff" # color fax
|
|
||||||
else:
|
|
||||||
faxFormat="sff" # normal b&w fax
|
|
||||||
filename=cs_helpers.uniqueName(os.path.join(udir,"received"),"fax",faxFormat)
|
|
||||||
faxInfo=capisuite.fax_receive(call,filename)
|
|
||||||
(cause,causeB3)=capisuite.disconnect(call)
|
|
||||||
capisuite.log("connection finished with cause 0x%x,0x%x" % (cause,causeB3),1,call)
|
|
||||||
|
|
||||||
except capisuite.CallGoneError: # catch this here to get the cause info in the mail
|
|
||||||
(cause,causeB3)=capisuite.disconnect(call)
|
|
||||||
capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call)
|
|
||||||
|
|
||||||
if (os.access(filename,os.R_OK)):
|
def faxIncoming(config, user, call, already_connected):
|
||||||
cs_helpers.writeDescription(filename,
|
"""
|
||||||
"call_from=\"%s\"\ncall_to=\"%s\"\ntime=\"%s\"\n" \
|
Called by callIncoming when an incoming fax call is received
|
||||||
"cause=\"0x%x/0x%x\"\n" % (call_from,call_to,time.ctime(),cause,causeB3))
|
|
||||||
userdata=pwd.getpwnam(curr_user)
|
|
||||||
os.chmod(filename,0600)
|
|
||||||
os.chown(filename,userdata[2],userdata[3])
|
|
||||||
os.chmod("%stxt" % filename[:-3],0600)
|
|
||||||
os.chown("%stxt" % filename[:-3],userdata[2],userdata[3])
|
|
||||||
|
|
||||||
fromaddress=cs_helpers.getOption(config,curr_user,"fax_email_from","")
|
'call' a python Call handle referencing to the call
|
||||||
if (fromaddress==""):
|
'user' name of the user who is responsible for this
|
||||||
fromaddress=curr_user
|
'config' ConfigParser instance holding the config data
|
||||||
mailaddress=cs_helpers.getOption(config,curr_user,"fax_email","")
|
'already_connected' ture if we're already connected (that means we must
|
||||||
if (mailaddress==""):
|
switch to fax mode)
|
||||||
mailaddress=curr_user
|
"""
|
||||||
action=cs_helpers.getOption(config,curr_user,"fax_action","").lower()
|
# todo: use config.getQueue + _mkdir here
|
||||||
if (action not in ("mailandsave","saveonly")):
|
receivedQ = fileutils._mkuserdir(user,
|
||||||
capisuite.error("Warning: No valid fax_action definition found for user %s -> assuming SaveOnly" % curr_user)
|
config.get('GLOBAL', "fax_user_dir"),
|
||||||
action="saveonly"
|
user, "received")
|
||||||
if (action=="mailandsave"):
|
|
||||||
mailText="You got a fax from %s to %s\nDate: %s" % (call_from,call_to,time.ctime())
|
|
||||||
if (faxInfo!=None and len(faxInfo)>=5):
|
|
||||||
mailText="%sStation ID: %s\nTransmission Details: bit rate %i " \
|
|
||||||
"%s %s\nPages: %i\n\nSee attached file.\n" \
|
|
||||||
"The original file was saved to file://%s " \
|
|
||||||
"on host \"%s\"." % (mailText,faxInfo[0], \
|
|
||||||
faxInfo[1],(faxInfo[2] and "hiRes" or "loRes"), \
|
|
||||||
(faxInfo[3] and "color" or ""),faxInfo[4], \
|
|
||||||
filename,os.uname()[1])
|
|
||||||
cs_helpers.sendMIMEMail(fromaddress, mailaddress, "Fax received from %s to %s" % (call_from,call_to),
|
|
||||||
faxFormat, mailText, filename)
|
|
||||||
|
|
||||||
# @brief called by callIncoming when an incoming voice call is received
|
# assure these variables are defined
|
||||||
#
|
filename = faxInfo = None
|
||||||
# @param call reference to the call. Needed by all capisuite functions
|
|
||||||
# @param call_from string containing the number of the calling party
|
|
||||||
# @param call_to string containing the number of the called party
|
|
||||||
# @param curr_user name of the user who is responsible for this
|
|
||||||
# @param config ConfigParser instance holding the config data
|
|
||||||
def voiceIncoming(call,call_from,call_to,curr_user,config):
|
|
||||||
try:
|
|
||||||
udir=cs_helpers.getOption(config,"","voice_user_dir")
|
|
||||||
if (udir==None):
|
|
||||||
capisuite.error("global option voice_user_dir not found! -> rejecting call")
|
|
||||||
capisuite.reject(call,0x34A9)
|
|
||||||
return
|
|
||||||
udir=os.path.join(udir,curr_user)
|
|
||||||
if (not os.path.exists(udir)):
|
|
||||||
userdata=pwd.getpwnam(curr_user)
|
|
||||||
os.mkdir(udir,0700)
|
|
||||||
os.chown(udir,userdata[2],userdata[3])
|
|
||||||
if (not os.path.exists(os.path.join(udir,"received"))):
|
|
||||||
userdata=pwd.getpwnam(curr_user)
|
|
||||||
os.mkdir(os.path.join(udir,"received"),0700)
|
|
||||||
os.chown(os.path.join(udir,"received"),userdata[2],userdata[3])
|
|
||||||
except KeyError:
|
|
||||||
capisuite.error("user %s is not a valid system user. Disconnecting" % curr_user,call)
|
|
||||||
capisuite.reject(call,0x34A9)
|
|
||||||
return
|
|
||||||
filename=cs_helpers.uniqueName(os.path.join(udir,"received"),"voice","la")
|
|
||||||
action=cs_helpers.getOption(config,curr_user,"voice_action","").lower()
|
|
||||||
if (action not in ("mailandsave","saveonly","none")):
|
|
||||||
capisuite.error("Warning: No valid voice_action definition found for user %s -> assuming SaveOnly" % curr_user)
|
|
||||||
action="saveonly"
|
|
||||||
try:
|
|
||||||
capisuite.enable_DTMF(call)
|
|
||||||
userannouncement=os.path.join(udir,cs_helpers.getOption(config,curr_user,"announcement","announcement.la"))
|
|
||||||
pin=cs_helpers.getOption(config,curr_user,"pin","")
|
|
||||||
if (os.access(userannouncement,os.R_OK)):
|
|
||||||
capisuite.audio_send(call,userannouncement,1)
|
|
||||||
else:
|
|
||||||
if (call_to!="-"):
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"anrufbeantworter-von.la"),1)
|
|
||||||
cs_helpers.sayNumber(call,call_to,curr_user,config)
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"bitte-nachricht.la"),1)
|
|
||||||
|
|
||||||
if (action!="none"):
|
stationID = config.getUser(user, "fax_stationID", default="")
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"),1)
|
if not stationID:
|
||||||
length=cs_helpers.getOption(config,curr_user,"record_length","60")
|
core.error("Warning: fax_stationID not found for user %s "
|
||||||
silence_timeout=cs_helpers.getOption(config,curr_user,"record_silence_timeout","5")
|
"-> using empty string" % user)
|
||||||
msg_length=capisuite.audio_receive(call,filename,int(length), int(silence_timeout),1)
|
# empty string is no problem for headline
|
||||||
|
headline = config.getUser(user, "fax_headline", default="")
|
||||||
|
|
||||||
dtmf_list=capisuite.read_DTMF(call,0)
|
call.log("call from %s to %s for %s connecting with fax" % \
|
||||||
if (dtmf_list=="X"):
|
(call.from_nr, call.to_nr, user), 1)
|
||||||
if (os.access(filename,os.R_OK)):
|
try:
|
||||||
os.unlink(filename)
|
if already_connected:
|
||||||
faxIncoming(call,call_from,call_to,curr_user,config,1)
|
faxInfo = call.switch_to_faxG3(stationID, headline)
|
||||||
elif (dtmf_list!="" and pin!=""):
|
else:
|
||||||
dtmf_list="%s%s" % (dtmf_list,capisuite.read_DTMF(call,3)) # wait 5 seconds for input
|
faxInfo = call.connect_faxG3(stationID, headline)
|
||||||
count=1
|
filename = fileutils.uniqueName(receivedQ, "fax", faxInfo.format)[1]
|
||||||
while (count<3 and pin!=dtmf_list): # try again if input was wrong
|
call.fax_receive(filename)
|
||||||
capisuite.log("wrong PIN entered...",1,call)
|
causes = call.disconnect()
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"))
|
call.log("connection finished with cause 0x%x, 0x%x" % causes, 1)
|
||||||
dtmf_list=capisuite.read_DTMF(call,3)
|
except core.CallGoneError:
|
||||||
count+=1
|
# catch this here to get the cause info into the mail
|
||||||
if (pin==dtmf_list):
|
causes = call.disconnect()
|
||||||
if (os.access(filename,os.R_OK)):
|
call.log("connection lost with cause 0x%x, 0x%x" % causes, 1)
|
||||||
os.unlink(filename)
|
# todo: send error mail here? Don't think it makes sense to send
|
||||||
capisuite.log("Starting remote inquiry...",1,call)
|
# a mail on each try, which would mean sending 10 mails for one fax...
|
||||||
remoteInquiry(call,udir,curr_user,config)
|
# If the user wants to know the current status he should use "capisuitefax -l"
|
||||||
|
else:
|
||||||
|
assert filename
|
||||||
|
if os.access(filename, os.R_OK):
|
||||||
|
faxInfo = faxInfo.as_dict()
|
||||||
|
faxInfo.update({
|
||||||
|
'filename' : filename,
|
||||||
|
'call_from': call.from_nr,
|
||||||
|
'call_to' : call.to_nr,
|
||||||
|
'causes' : causes,
|
||||||
|
'hostname' : os.uname()[1]
|
||||||
|
})
|
||||||
|
capisuite.fax.createReceivedJob(user, **faxInfo)
|
||||||
|
action = _getAction(config, user, "fax_action",
|
||||||
|
("saveonly", "mailandsave"))
|
||||||
|
if action == "mailandsave":
|
||||||
|
fromaddress = config.getUser(user, "fax_email_from", user)
|
||||||
|
mailaddress = config.getUser(user, "fax_email", user)
|
||||||
|
|
||||||
(cause,causeB3)=capisuite.disconnect(call)
|
cs_helpers.sendMIMEMail(
|
||||||
capisuite.log("connection finished with cause 0x%x,0x%x" % (cause,causeB3),1,call)
|
fromaddress, mailaddress,
|
||||||
|
config.get('MailFaxReceived', 'subject') % faxInfo,
|
||||||
|
faxInfo['format'],
|
||||||
|
config.get('MailFaxReceived', 'text') % faxInfo,
|
||||||
|
filename)
|
||||||
|
|
||||||
except capisuite.CallGoneError: # catch this here to get the cause info in the mail
|
|
||||||
(cause,causeB3)=capisuite.disconnect(call)
|
|
||||||
capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call)
|
|
||||||
|
|
||||||
if (os.access(filename,os.R_OK)):
|
def _getAction(config, user, action_name, allowed_actions):
|
||||||
cs_helpers.writeDescription(filename,
|
action = config.getUser(user, action_name, "").lower()
|
||||||
"call_from=\"%s\"\ncall_to=\"%s\"\ntime=\"%s\"\n" \
|
if action not in allowed_actions:
|
||||||
"cause=\"0x%x/0x%x\"\n" % (call_from,call_to,time.ctime(),cause,causeB3))
|
action = allowed_actions[0]
|
||||||
userdata=pwd.getpwnam(curr_user)
|
core.error("Warning: No valid %s definition found for user %s -> "
|
||||||
os.chmod(filename,0600)
|
"assuming %s" % action_name, user, action)
|
||||||
os.chown(filename,userdata[2],userdata[3])
|
return action
|
||||||
os.chmod("%stxt" % filename[:-2],0600)
|
|
||||||
os.chown("%stxt" % filename[:-2],userdata[2],userdata[3])
|
|
||||||
|
|
||||||
fromaddress=cs_helpers.getOption(config,curr_user,"voice_email_from","")
|
|
||||||
if (fromaddress==""):
|
|
||||||
fromaddress=curr_user
|
|
||||||
mailaddress=cs_helpers.getOption(config,curr_user,"voice_email","")
|
|
||||||
if (mailaddress==""):
|
|
||||||
mailaddress=curr_user
|
|
||||||
if (action=="mailandsave"):
|
|
||||||
mailText="You got a voice call from %s to %s\n" \
|
|
||||||
"Date: %s\nLength: %i s\n\nSee attached file.\n" \
|
|
||||||
"The original file was saved to file://%s on" \
|
|
||||||
"host \"%s\".\n\n" % (call_from,call_to,time.ctime(), \
|
|
||||||
msg_length,filename,os.uname()[1])
|
|
||||||
subject="Voice call received from %s to %s" % (call_from,call_to)
|
|
||||||
cs_helpers.sendMIMEMail(fromaddress,mailaddress,subject,"la",mailText,filename)
|
|
||||||
|
|
||||||
# @brief remote inquiry function (uses german wave snippets!)
|
def voiceIncoming(config, user, call):
|
||||||
#
|
"""
|
||||||
# commands for remote inquiry
|
Called by callIncoming when an incoming voice call is received
|
||||||
# delete message - 1
|
|
||||||
# next message - 4
|
|
||||||
# last message - 5
|
|
||||||
# repeat current message - 6
|
|
||||||
#
|
|
||||||
# @param call reference to the call. Needed by all capisuite functions
|
|
||||||
# @param userdir spool_dir of the current_user
|
|
||||||
# @param curr_user name of the user who is responsible for this
|
|
||||||
# @param config ConfigParser instance holding the config data
|
|
||||||
def remoteInquiry(call,userdir,curr_user,config):
|
|
||||||
import time,fcntl,errno,os
|
|
||||||
# acquire lock
|
|
||||||
lockfile=open(os.path.join(userdir,"received/inquiry_lock"),"w")
|
|
||||||
try:
|
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_EX | fcntl.LOCK_NB) # only one inquiry at a time!
|
|
||||||
|
|
||||||
except IOError,err: # can't get the lock
|
'call' a python Call handle referencing to the call
|
||||||
if (err.errno in (errno.EACCES,errno.EAGAIN)):
|
'user' name of the user who is responsible for this
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"fernabfrage-aktiv.la"))
|
'config' ConfigParser instance holding the config data
|
||||||
lockfile.close()
|
"""
|
||||||
return
|
try:
|
||||||
|
if not config.has_option(user, 'voice_delay'):
|
||||||
|
core.error("voice_delay not found for user %s! -> "
|
||||||
|
"rejecting call" % user)
|
||||||
|
call.reject(0x34A9)
|
||||||
|
return
|
||||||
|
delay = config.getint(user, "voice_delay")
|
||||||
|
call.log("call from %s to %s for %s connecting with voice" % \
|
||||||
|
(call.from_nr, call.to_nr, user), 1)
|
||||||
|
call.connect_voice(delay)
|
||||||
|
|
||||||
try:
|
userdir = config.get('GLOBAL', "voice_user_dir")
|
||||||
# read directory contents
|
action = _getAction(config, user, "voice_action",
|
||||||
messages=os.listdir(os.path.join(userdir,"received"))
|
("saveonly", "mailandsave", "none"))
|
||||||
messages=filter (lambda s: re.match("voice-.*\.la",s),messages) # only use voice-* files
|
receivedQ = fileutils._mkuserdir(user, userdir, user, "received")
|
||||||
messages=map(lambda s: int(re.match("voice-([0-9]+)\.la",s).group(1)),messages) # filter out numbers
|
userannouncement = os.path.join(userdir, user,
|
||||||
messages.sort()
|
config.getUser(user, "announcement", "announcement.la"))
|
||||||
|
pin = config.getUser(user, "pin", "")
|
||||||
|
filename = None # assure it's defined
|
||||||
|
|
||||||
# read the number of the message heard last at the last inquiry
|
call.enable_DTMF()
|
||||||
lastinquiry=-1
|
if os.access(userannouncement, os.R_OK):
|
||||||
if (os.access(os.path.join(userdir,"received/last_inquiry"),os.W_OK)):
|
call.audio_send(userannouncement, 1)
|
||||||
lastfile=open(os.path.join(userdir,"received/last_inquiry"),"r")
|
else:
|
||||||
lastinquiry=int(lastfile.readline())
|
if call.to_nr != "-":
|
||||||
lastfile.close()
|
say(config, user, call, "anrufbeantworter-von.la")
|
||||||
|
capisuite.voice.sayNumber(config, user, call, call.to_nr)
|
||||||
|
say(config, user, call, "bitte-nachricht.la")
|
||||||
|
|
||||||
# sort out old messages
|
if action != "none":
|
||||||
oldmessages=[]
|
say(config, user, call, "beep.la")
|
||||||
i=0
|
length = config.getUser(user, "record_length", 60)
|
||||||
while (i<len(messages)):
|
# todo: put this into voice.getNameForRecord
|
||||||
if (messages[i]<=lastinquiry):
|
filename = fileutils.uniqueName(receivedQ, "voice", 'la')[1]
|
||||||
oldmessages.append(messages[i])
|
silence_timeout = config.getUser(user, "record_silence_timeout", 5)
|
||||||
del messages[i]
|
msg_length = call.audio_receive(filename, int(length),
|
||||||
else:
|
int(silence_timeout), 1)
|
||||||
i+=1
|
dtmf_list = call.read_DTMF(0)
|
||||||
|
if dtmf_list == "X":
|
||||||
|
if os.access(filename, os.R_OK):
|
||||||
|
os.unlink(filename)
|
||||||
|
faxIncoming(config, user, call, 1)
|
||||||
|
elif dtmf_list and pin:
|
||||||
|
# wait 5 seconds for input
|
||||||
|
dtmf_list += call.read_DTMF(3)
|
||||||
|
count = 1
|
||||||
|
# allow three tries
|
||||||
|
while count < 3 and pin != dtmf_list:
|
||||||
|
call.log("wrong PIN entered...", 1)
|
||||||
|
say(config, user, call, "beep.la")
|
||||||
|
dtmf_list = call.read_DTMF(3)
|
||||||
|
count += 1
|
||||||
|
else:
|
||||||
|
# failed three time
|
||||||
|
# todo: hang up?
|
||||||
|
# gh: Yes.
|
||||||
|
pass
|
||||||
|
if pin == dtmf_list:
|
||||||
|
if os.access(filename, os.R_OK):
|
||||||
|
os.unlink(filename)
|
||||||
|
call.log("Starting remote inquiry...", 1)
|
||||||
|
remoteInquiry(call, user, config, receivedQ)
|
||||||
|
|
||||||
cs_helpers.sayNumber(call,str(len(messages)),curr_user,config,"f")
|
except core.CallGoneError:
|
||||||
if (len(messages)==1):
|
# catch this here to get the cause info in the mail
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachricht.la"),1)
|
causes = call.disconnect()
|
||||||
else:
|
call.log("connection lost with cause 0x%x, 0x%x" % causes, 1)
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachrichten.la"),1)
|
else:
|
||||||
|
causes = call.disconnect()
|
||||||
|
call.log("connection finished with cause 0x%x, 0x%x" % causes, 1)
|
||||||
|
|
||||||
# menu for record new announcement
|
if (filename and os.access(filename, os.R_OK)):
|
||||||
cmd=""
|
info = capisuite.voice.createReceivedJob(user, filename, call.from_nr,
|
||||||
while (cmd not in ("1","9")):
|
call.to_nr, causes)
|
||||||
if (len(messages)+len(oldmessages)):
|
fromaddress = config.getUser(user, "voice_email_from", user)
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"zum-abhoeren-1.la"),1)
|
mailaddress = config.getUser(user, "voice_email", user)
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"fuer-neue-ansage-9.la"),1)
|
if action == "mailandsave":
|
||||||
cmd=capisuite.read_DTMF(call,0,1)
|
info['hostname'] = os.uname()[1]
|
||||||
if (cmd=="9"):
|
info['msg_length'] = msg_length
|
||||||
newAnnouncement(call,userdir,curr_user,config)
|
cs_helpers.sendMIMEMail(
|
||||||
return
|
fromaddress, mailaddress,
|
||||||
|
config.get('MailVoiceReceived', 'subject') % info,
|
||||||
|
"la",
|
||||||
|
config.get('MailVoiceReceived', 'text') % info,
|
||||||
|
filename)
|
||||||
|
|
||||||
# start inquiry
|
def remoteInquiry(config, user, call, receivedQ):
|
||||||
for curr_msgs in (messages,oldmessages):
|
"""
|
||||||
cs_helpers.sayNumber(call,str(len(curr_msgs)),curr_user,config,"f")
|
Remote inquiry function (uses german wave snippets!)
|
||||||
if (curr_msgs==messages):
|
|
||||||
if (len(curr_msgs)==1):
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachricht.la"),1)
|
|
||||||
else:
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachrichten.la"),1)
|
|
||||||
else:
|
|
||||||
if (len(curr_msgs)==1):
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"nachricht.la"),1)
|
|
||||||
else:
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"nachrichten.la"),1)
|
|
||||||
|
|
||||||
i=0
|
Implemented commands for remote inquiry are:
|
||||||
while (i<len(curr_msgs)):
|
delete message - 1
|
||||||
filename=os.path.join(userdir,"received/voice-%i.la" % curr_msgs[i])
|
next message - 4
|
||||||
descr=cs_helpers.readConfig("%stxt" % filename[:-2])
|
last message - 5
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"nachricht.la"),1)
|
repeat current message - 6
|
||||||
cs_helpers.sayNumber(call,str(i+1),curr_user,config)
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"von.la"),1)
|
|
||||||
cs_helpers.sayNumber(call,descr.get('GLOBAL','call_from'),curr_user,config)
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"fuer.la"),1)
|
|
||||||
cs_helpers.sayNumber(call,descr.get('GLOBAL','call_to'),curr_user,config)
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"am.la"),1)
|
|
||||||
calltime=time.strptime(descr.get('GLOBAL','time'))
|
|
||||||
cs_helpers.sayNumber(call,str(calltime[2]),curr_user,config)
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"..la"),1)
|
|
||||||
cs_helpers.sayNumber(call,str(calltime[1]),curr_user,config)
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"..la"),1)
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"um.la"),1)
|
|
||||||
cs_helpers.sayNumber(call,str(calltime[3]),curr_user,config,"n")
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"uhr.la"),1)
|
|
||||||
cs_helpers.sayNumber(call,str(calltime[4]),curr_user,config)
|
|
||||||
capisuite.audio_send(call,filename,1)
|
|
||||||
cmd=""
|
|
||||||
while (cmd not in ("1","4","5","6")):
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"erklaerung.la"),1)
|
|
||||||
cmd=capisuite.read_DTMF(call,0,1)
|
|
||||||
if (cmd=="1"):
|
|
||||||
os.remove(filename)
|
|
||||||
os.remove("%stxt" % filename[:-2])
|
|
||||||
del curr_msgs[i]
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"nachricht-geloescht.la"))
|
|
||||||
elif (cmd=="4"):
|
|
||||||
if (curr_msgs[i]>lastinquiry):
|
|
||||||
lastinquiry=curr_msgs[i]
|
|
||||||
lastfile=open(os.path.join(userdir,"received/last_inquiry"),"w")
|
|
||||||
lastfile.write("%i\n" % curr_msgs[i])
|
|
||||||
lastfile.close()
|
|
||||||
i+=1
|
|
||||||
elif (cmd=="5"):
|
|
||||||
i-=1
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"keine-weiteren-nachrichten.la"))
|
|
||||||
|
|
||||||
finally:
|
'user' name of the user who is responsible for this
|
||||||
# unlock
|
'config' ConfigParser instance holding the config data
|
||||||
fcntl.lockf(lockfile,fcntl.LOCK_UN)
|
'call' reference to the call. Needed by all capisuite functions
|
||||||
lockfile.close()
|
'receivedQ' the received queue dir of the user
|
||||||
os.unlink(os.path.join(userdir,"received/inquiry_lock"))
|
"""
|
||||||
|
try:
|
||||||
|
lock = fileutils._getLock(lockname=os.path.join(receivedQ,
|
||||||
|
'inquiry_lock'),
|
||||||
|
blocking=0)
|
||||||
|
except fileutils.LockTakenError:
|
||||||
|
say(config, user, call, "fernabfrage-aktiv.la")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
# read directory contents
|
||||||
|
messages = capisuite.voice.getQueue(config, user)
|
||||||
|
|
||||||
# @brief remote inquiry: record new announcement (uses german wave snippets!)
|
# read the number of the message heard last at the last inquiry
|
||||||
#
|
lastinquiry = capisuite.voice.getInquiryCounter(config, user)
|
||||||
# @param call reference to the call. Needed by all capisuite functions
|
# filter out old messages
|
||||||
# @param userdir spool_dir of the current_user
|
oldmessages = [m for m in messages if m[0] <= lastinquiry]
|
||||||
# @param curr_user name of the user who is responsible for this
|
messages = [m for m in messages if m[0] > lastinquiry]
|
||||||
# @param config ConfigParser instance holding the config data
|
oldmessages.sort()
|
||||||
def newAnnouncement(call,userdir,curr_user,config):
|
messages.sort()
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"bitte-neue-ansage-komplett.la"))
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"))
|
|
||||||
cmd=""
|
|
||||||
while (cmd!="1"):
|
|
||||||
capisuite.audio_receive(call,os.path.join(userdir,"announcement-tmp.la"),60,3)
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-ansage-lautet.la"))
|
|
||||||
capisuite.audio_send(call,os.path.join(userdir,"announcement-tmp.la"))
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"wenn-einverstanden-1.la"))
|
|
||||||
cmd=capisuite.read_DTMF(call,0,1)
|
|
||||||
if (cmd!="1"):
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"bitte-neue-ansage-kurz.la"))
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"))
|
|
||||||
userannouncement=os.path.join(userdir,cs_helpers.getOption(config,curr_user,"announcement","announcement.la"))
|
|
||||||
os.rename(os.path.join(userdir,"announcement-tmp.la"),userannouncement)
|
|
||||||
userdata=pwd.getpwnam(curr_user)
|
|
||||||
os.chown(userannouncement,userdata[2],userdata[3])
|
|
||||||
|
|
||||||
capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"ansage-gespeichert.la"))
|
announceNumMessages(config, user, call, len(messages), new=1)
|
||||||
|
|
||||||
|
# menu for record new announcement
|
||||||
|
cmd = ""
|
||||||
|
while cmd not in ("1", "9"):
|
||||||
|
if len(messages) or len(oldmessages):
|
||||||
|
say(config, user, call, "zum-abhoeren-1.la")
|
||||||
|
say(config, user, call, "fuer-neue-ansage-9.la")
|
||||||
|
cmd = call.read_DTMF(0, 1)
|
||||||
|
if cmd == "9":
|
||||||
|
cmd_recordNewAnnouncement(config, user, call, receivedQ)
|
||||||
|
return
|
||||||
|
|
||||||
|
# start inquiry
|
||||||
|
cmd_inquiry(config, user, call, oldmessages, messages, lastinquiry)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
fileutils._releaseLock(lock)
|
||||||
|
|
||||||
|
|
||||||
|
def announceNumMessages(config, user, call, numMessages, new):
|
||||||
|
if numMessages == 1:
|
||||||
|
msg = "nachricht.la"
|
||||||
|
else:
|
||||||
|
msg = "nachrichten.la"
|
||||||
|
if new:
|
||||||
|
msg = 'neue-' + msg
|
||||||
|
capisuite.voice.sayNumber(config, user, call, numMessages, gender="f")
|
||||||
|
say(config, user, call, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_inquiry(config, user, call, oldmessages, messages, lastinquiry):
|
||||||
|
"""
|
||||||
|
Remote inquiry function (uses german wave snippets!)
|
||||||
|
|
||||||
|
Implemented commands for remote inquiry are:
|
||||||
|
delete message - 1
|
||||||
|
next message - 4
|
||||||
|
last message - 5
|
||||||
|
repeat current message - 6
|
||||||
|
|
||||||
|
'user' name of the user who is responsible for this
|
||||||
|
'config' ConfigParser instance holding the config data
|
||||||
|
'call' reference to the call. Needed by all capisuite functions
|
||||||
|
'userdir' spool_dir of the current_user
|
||||||
|
"""
|
||||||
|
for curr_msgs in (messages, oldmessages):
|
||||||
|
capisuite.voice.sayNumber(config, user, call, len(curr_msgs), "f")
|
||||||
|
announceNumMessages(config, user, call, len(messages),
|
||||||
|
new = (curr_msgs == messages))
|
||||||
|
i = 0
|
||||||
|
while i < len(curr_msgs):
|
||||||
|
msgnum, controlfile = curr_msgs[i]
|
||||||
|
descr = config.JobDescription(controlfile)
|
||||||
|
# play the announcement
|
||||||
|
for f in _getSoundsForAnnounceMessages(i, descr):
|
||||||
|
say(config, user, call, "%s.la" % f)
|
||||||
|
# play the recorded file
|
||||||
|
call.audio_send(descr.get('filename'), 1)
|
||||||
|
cmd = ""
|
||||||
|
while cmd not in ("1", "4", "5", "6"):
|
||||||
|
say(config, user, call, "erklaerung.la")
|
||||||
|
cmd = call.read_DTMF(0, 1)
|
||||||
|
if cmd == "1":
|
||||||
|
cmd_deleteMessage(config, user, call, controlfile)
|
||||||
|
del curr_msgs[i]
|
||||||
|
elif cmd == "4":
|
||||||
|
if msgnum > lastinquiry:
|
||||||
|
lastinquiry = msgnum
|
||||||
|
capisuite.voice.setInquiryCounter(config, user, msgnum)
|
||||||
|
i += 1
|
||||||
|
elif cmd == "5":
|
||||||
|
i -= 1
|
||||||
|
say(config, user, call, "keine-weiteren-nachrichten.la")
|
||||||
|
# todo: say 'hauptmenu'
|
||||||
|
|
||||||
|
def _getSoundsForAnnounceMessages(msgnum, descr):
|
||||||
|
"""
|
||||||
|
generated a list of sound to be played before replaying a recored message
|
||||||
|
"""
|
||||||
|
getNumberFiles = capisuite.voice.getNumberFiles
|
||||||
|
yield 'nachricht'
|
||||||
|
for f in getNumberFiles(msgnum+1): yield f
|
||||||
|
yield 'von'
|
||||||
|
for f in getNumberFiles(descr.get('call_from')): yield f
|
||||||
|
yield 'fuer'
|
||||||
|
for f in getNumberFiles(descr.get('call_to')): yield f
|
||||||
|
yield 'am'
|
||||||
|
calltime = time.strptime(descr.get('time'))
|
||||||
|
for f in getNumberFiles(calltime[2]): yield f
|
||||||
|
yield '.'
|
||||||
|
for f in getNumberFiles(calltime[1]): yield f
|
||||||
|
yield '.'
|
||||||
|
yield 'um'
|
||||||
|
for f in getNumberFiles(calltime[3], 'n'): yield f
|
||||||
|
yield 'uhr'
|
||||||
|
for f in getNumberFiles(calltime[4]): yield f
|
||||||
|
|
||||||
|
def cmd_deleteMessage(config, user, call, controlfile):
|
||||||
|
capisuite.fax.abortJob(controlfile)
|
||||||
|
say(config, user, call, "nachricht-geloescht.la")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_recordNewAnnouncement(config, user, call, userdir):
|
||||||
|
"""
|
||||||
|
remote inquiry command: record new announcement (uses german wave snippets!)
|
||||||
|
'config' ConfigParser instance holding the config data
|
||||||
|
'user' name of the user who is responsible for this
|
||||||
|
'call' reference to the call. Needed by all capisuite functions
|
||||||
|
'userdir' spool_dir of the current_user
|
||||||
|
"""
|
||||||
|
say(config, user, call, "bitte-neue-ansage-komplett.la", "beep.la")
|
||||||
|
|
||||||
|
tmpfile = os.path.join(userdir, "announcement-tmp.la")
|
||||||
|
while 1:
|
||||||
|
call.audio_receive(tmpfile, 60, 3)
|
||||||
|
say(config, user, call, "neue-ansage-lautet.la")
|
||||||
|
call.audio_send(tmpfile)
|
||||||
|
say(config, user, call, "wenn-einverstanden-1.la")
|
||||||
|
cmd = call.read_DTMF(0, 1)
|
||||||
|
# todo: allow eg. '9' for cancel and go back to menu
|
||||||
|
if cmd == "1":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
say(config, user, call, "bitte-neue-ansage-kurz.la", "beep.la")
|
||||||
|
|
||||||
|
userannouncement = os.path.join(userdir,
|
||||||
|
config.getUser(user, "announcement", "announcement.la"))
|
||||||
|
os.rename(tmpfile, userannouncement)
|
||||||
|
fileutils._setProtection(user, userannouncement, mode=0666)
|
||||||
|
say(config, user, call, "ansage-gespeichert.la")
|
||||||
|
|
||||||
#
|
|
||||||
# History:
|
|
||||||
#
|
|
||||||
# Old Log (for new changes see ChangeLog):
|
|
||||||
# Revision 1.13 2003/12/01 20:53:05 gernot
|
|
||||||
# - confused "hiRes" and "loRes". Thx to Ingo Goeppert <Ingo.Goeppert@gmx.de>
|
|
||||||
# for the report!
|
|
||||||
#
|
|
||||||
# Revision 1.12 2003/10/03 13:42:09 gernot
|
|
||||||
# - added new options "fax_email_from" and "voice_email_from"
|
|
||||||
#
|
|
||||||
# Revision 1.11 2003/08/24 12:47:50 gernot
|
|
||||||
# - faxIncoming tried to reconnect when it was called after a switch from
|
|
||||||
# voice to fax mode, which lead to a call abort. Thx to Harald Jansen &
|
|
||||||
# Andreas Scholz for reporting!
|
|
||||||
#
|
|
||||||
# Revision 1.10 2003/07/20 10:30:37 gernot
|
|
||||||
# - started implementing faxInfo output in sent mails, not working currently
|
|
||||||
#
|
|
||||||
# Revision 1.9 2003/06/27 07:51:09 gernot
|
|
||||||
# - replaced german umlaut in filename "nachricht-gelscht.la", can cause
|
|
||||||
# problems on Redhat, thx to Herbert Hübner for reporting
|
|
||||||
#
|
|
||||||
# Revision 1.8 2003/06/16 10:21:05 gernot
|
|
||||||
# - define filename in any case (thx to Axel Schneck for reporting and
|
|
||||||
# analyzing...)
|
|
||||||
#
|
|
||||||
# Revision 1.7 2003/05/25 13:38:30 gernot
|
|
||||||
# - support reception of color fax documents
|
|
||||||
#
|
|
||||||
# Revision 1.6 2003/04/10 21:29:51 gernot
|
|
||||||
# - support empty destination number for incoming calls correctly (austrian
|
|
||||||
# telecom does this (sic))
|
|
||||||
# - core now returns "-" instead of "??" for "no number available" (much nicer
|
|
||||||
# in my eyes)
|
|
||||||
# - new wave file used in remote inquiry for "unknown number"
|
|
||||||
#
|
|
||||||
# Revision 1.5 2003/03/20 09:12:42 gernot
|
|
||||||
# - error checking for reading of configuration improved, many options got
|
|
||||||
# optional, others produce senseful error messages now if not found,
|
|
||||||
# fixes bug# 531, thx to Dieter Pelzel for reporting
|
|
||||||
#
|
|
||||||
# Revision 1.4 2003/03/13 11:08:06 gernot
|
|
||||||
# - fix remote inquiry locking (should fix bug #534, but doesn't - anyway,
|
|
||||||
# this fix is definitely necessary)
|
|
||||||
# - stricter permissions of saved files and created dirs, fixes #544
|
|
||||||
# - add "file://" prefix to the path shown in the mails to the user
|
|
||||||
#
|
|
||||||
# Revision 1.3 2003/02/21 13:13:34 gernot
|
|
||||||
# - removed some debug output (oops...)
|
|
||||||
#
|
|
||||||
# Revision 1.2 2003/02/21 11:02:17 gernot
|
|
||||||
# - removed os.setuid() from incoming script
|
|
||||||
# -> fixes Bug #527
|
|
||||||
#
|
|
||||||
# Revision 1.1.1.1 2003/02/19 08:19:54 gernot
|
|
||||||
# initial checkin of 0.4
|
|
||||||
#
|
|
||||||
# Revision 1.11 2003/02/17 11:13:43 ghillie
|
|
||||||
# - remoteinquiry supports new and old messages now
|
|
||||||
#
|
|
||||||
# Revision 1.10 2003/02/03 14:50:08 ghillie
|
|
||||||
# - fixed small typo
|
|
||||||
#
|
|
||||||
# Revision 1.9 2003/01/31 16:32:41 ghillie
|
|
||||||
# - support "*" for "all numbers"
|
|
||||||
# - automatic switch voice->fax when SI says fax
|
|
||||||
#
|
|
||||||
# Revision 1.8 2003/01/31 11:24:41 ghillie
|
|
||||||
# - wrong user handling for more than one users fixed
|
|
||||||
# - creates user_dir/user and user_dir/user/received now separately as
|
|
||||||
# idle.py can also create user_dir/user now
|
|
||||||
#
|
|
||||||
# Revision 1.7 2003/01/27 21:57:54 ghillie
|
|
||||||
# - fax_numbers and voice_numbers may not exist (no fatal error any more)
|
|
||||||
# - accept missing email option
|
|
||||||
# - fixed typo
|
|
||||||
#
|
|
||||||
# Revision 1.6 2003/01/27 19:24:29 ghillie
|
|
||||||
# - updated to use new configuration files for fax & answering machine
|
|
||||||
#
|
|
||||||
# Revision 1.5 2003/01/19 12:03:27 ghillie
|
|
||||||
# - use capisuite log functions instead of stdout/stderr
|
|
||||||
#
|
|
||||||
# Revision 1.4 2003/01/17 15:09:49 ghillie
|
|
||||||
# - cs_helpers.sendMail was renamed to sendMIMEMail
|
|
||||||
#
|
|
||||||
# Revision 1.3 2003/01/16 12:58:34 ghillie
|
|
||||||
# - changed DTMF timeout for pin to 3 seconds
|
|
||||||
# - delete recorded wave if fax or remote inquiry is recognized
|
|
||||||
# - updates in remoteInquiry: added menu for recording own announcement
|
|
||||||
# - fixed some typos
|
|
||||||
# - remoteInquiry: delete description file together with call if requested
|
|
||||||
# - new function: newAnnouncement
|
|
||||||
#
|
|
||||||
# Revision 1.2 2003/01/15 15:55:12 ghillie
|
|
||||||
# - added exception handler in callIncoming
|
|
||||||
# - faxIncoming: small typo corrected
|
|
||||||
# - voiceIncoming & remoteInquiry: updated to new config file system
|
|
||||||
#
|
|
||||||
# Revision 1.1 2003/01/13 16:12:58 ghillie
|
|
||||||
# - renamed from incoming.pyin to incoming.py as all previously processed
|
|
||||||
# variables are moved to config and cs_helpers.pyin
|
|
||||||
#
|
|
||||||
# Revision 1.4 2002/12/18 14:34:56 ghillie
|
|
||||||
# - added some informational prints
|
|
||||||
# - accept voice calls to fax nr
|
|
||||||
#
|
|
||||||
# Revision 1.3 2002/12/16 15:04:51 ghillie
|
|
||||||
# - added missing path prefix to delete routing in remote inquiry
|
|
||||||
#
|
|
||||||
# Revision 1.2 2002/12/16 13:09:25 ghillie
|
|
||||||
# - added some comments about the conf_* vars
|
|
||||||
# - added conf_wavedir
|
|
||||||
# - added support for B3 cause now returned by disconnect()
|
|
||||||
# - corrected some dir entries to work in installed system
|
|
||||||
#
|
|
||||||
# Revision 1.1 2002/12/14 13:53:18 ghillie
|
|
||||||
# - idle.py and incoming.py are now auto-created from *.pyin
|
|
||||||
#
|
|
||||||
# Revision 1.4 2002/12/11 12:58:05 ghillie
|
|
||||||
# - read return value from disconnect()
|
|
||||||
# - added disconnect() to exception handler
|
|
||||||
#
|
|
||||||
# Revision 1.3 2002/12/09 15:18:35 ghillie
|
|
||||||
# - added disconnect() in exception handler
|
|
||||||
#
|
|
||||||
# Revision 1.2 2002/12/02 21:30:42 ghillie
|
|
||||||
# fixed some minor typos
|
|
||||||
#
|
|
||||||
# Revision 1.1 2002/12/02 21:15:55 ghillie
|
|
||||||
# - moved scripts to own directory
|
|
||||||
# - added remote-connect script to repository
|
|
||||||
#
|
|
||||||
# Revision 1.20 2002/12/02 20:59:44 ghillie
|
|
||||||
# another typo :-|
|
|
||||||
#
|
|
||||||
# Revision 1.19 2002/12/02 20:54:07 ghillie
|
|
||||||
# fixed small typo
|
|
||||||
#
|
|
||||||
# Revision 1.18 2002/12/02 16:51:32 ghillie
|
|
||||||
# nearly complete new script, supports answering machine, fax receiving and remote inquiry now
|
|
||||||
#
|
|
||||||
# Revision 1.17 2002/11/29 16:28:43 ghillie
|
|
||||||
# - updated syntax (connect_telephony -> connect_voice)
|
|
||||||
#
|
|
||||||
# Revision 1.16 2002/11/29 11:09:04 ghillie
|
|
||||||
# renamed CapiCom to CapiSuite (name conflict with MS crypto API :-( )
|
|
||||||
#
|
|
||||||
# Revision 1.15 2002/11/25 11:43:43 ghillie
|
|
||||||
# updated to new syntax
|
|
||||||
#
|
|
||||||
# Revision 1.14 2002/11/23 16:16:17 ghillie
|
|
||||||
# moved switch2fax after audio_receive()
|
|
||||||
#
|
|
||||||
# Revision 1.13 2002/11/22 15:48:58 ghillie
|
|
||||||
# renamed pcallcontrol module to capicom
|
|
||||||
#
|
|
||||||
# Revision 1.12 2002/11/22 15:02:39 ghillie
|
|
||||||
# - added automatic switch between speech and fax
|
|
||||||
# - some comments added
|
|
||||||
#
|
|
||||||
# Revision 1.11 2002/11/19 15:57:18 ghillie
|
|
||||||
# - Added missing throw() declarations
|
|
||||||
# - phew. Added error handling. All exceptions are caught now.
|
|
||||||
#
|
|
||||||
# Revision 1.10 2002/11/18 12:32:36 ghillie
|
|
||||||
# - callIncoming lives now in __main__, not necessarily in pcallcontrol any more
|
|
||||||
# - added some comments and header
|
|
||||||
#
|
|
||||||
|
|
|
@ -1,59 +1,81 @@
|
||||||
import string,os,time
|
import pcallcontrol as cc
|
||||||
import pcallcontrol
|
import os, time
|
||||||
cc=pcallcontrol
|
import commands
|
||||||
|
|
||||||
def callWaiting(CIP,callingParty,calledParty):
|
def acceptCall(CIP, callingParty, calledParty):
|
||||||
if (calledParty=="23"):
|
print "nehme Anruf von",callingParty,"an",calledParty,"an."
|
||||||
print "nehme Anruf von",callingParty,"an",calledParty,"an."
|
cc.connect(16) # 16 = telephony
|
||||||
cc.connect(16) # 16 = telephony
|
|
||||||
else:
|
def rejectCall(CIP, callingParty, calledParty):
|
||||||
print "nehme Anruf von",callingParty,"an",calledParty,"nicht an."
|
print "nehme Anruf von",callingParty,"an",calledParty,"nicht an."
|
||||||
cc.reject(2) # 2 = normal call clearing
|
cc.reject(2) # 2 = normal call clearing
|
||||||
|
|
||||||
|
|
||||||
|
def establishInternetConnection():
|
||||||
|
# establish connection
|
||||||
|
timeout = time.time()+15 # 15 seconds timeout
|
||||||
|
os.spawnl(os.P_NOWAIT, "ping", "ping", "-w", "1", "www.hillier.de")
|
||||||
|
c_status = ""
|
||||||
|
# wait 30 secs for connect
|
||||||
|
while c_status != "CONNECTED" and time.time() < timeout:
|
||||||
|
lines = commands.getoutput("/usr/sbin/cinternet --status")
|
||||||
|
for l in lines.splitlines():
|
||||||
|
if l.startswith("status"):
|
||||||
|
c_status = l[9:].strip()
|
||||||
|
print 'status:', c_status
|
||||||
|
time.sleep(1)
|
||||||
|
# get ip address
|
||||||
|
save_lang = os.environ["LANG"]
|
||||||
|
os.environ["LANG"] = ""
|
||||||
|
lines = commands.getoutput("/sbin/ifconfig ppp0")
|
||||||
|
os.environ["LANG"] = save_lang
|
||||||
|
for l in lines: # no need to split into lines
|
||||||
|
index = l.find("inet addr:")
|
||||||
|
if index >= 0:
|
||||||
|
index += 10
|
||||||
|
rindex = l.find(" ", index)
|
||||||
|
ip_address = l[index:rindex]
|
||||||
|
# play ip address
|
||||||
|
for i in ip_address:
|
||||||
|
cc.audio_send(i+".la")
|
||||||
|
|
||||||
|
|
||||||
|
callWaitingMap = {
|
||||||
|
'23': acceptCall,
|
||||||
|
'default': denyCall,
|
||||||
|
}
|
||||||
|
|
||||||
|
def callWaiting(CIP, callingParty, calledParty):
|
||||||
|
action = callWaitingMap.get(calledParty, None)
|
||||||
|
if action:
|
||||||
|
action(CIP, callingParty, calledParty)
|
||||||
|
else:
|
||||||
|
action = callWaitingMap.get('default', None)
|
||||||
|
if action:
|
||||||
|
action(CIP, callingParty, calledParty)
|
||||||
|
|
||||||
|
callConnectedMap = {
|
||||||
|
'3008': establishInternetConnection,
|
||||||
|
}
|
||||||
|
|
||||||
def callConnected():
|
def callConnected():
|
||||||
try:
|
try:
|
||||||
cc.enableDTMF()
|
cc.enableDTMF()
|
||||||
cc.audio_send("send.la")
|
cc.audio_send("send.la")
|
||||||
code=cc.getDTMF()
|
code = cc.getDTMF()
|
||||||
print "Bekommen habe ich",code
|
print "Bekommen habe ich",code
|
||||||
if code=="3008":
|
action = callWaitingMap.get(calledParty, None)
|
||||||
# establish connection
|
if action:
|
||||||
start_t=time.time()
|
action(CIP, callingParty, calledParty)
|
||||||
os.spawnl(os.P_NOWAIT,"ping","ping","-w","1","www.hillier.de")
|
else:
|
||||||
c_status=""
|
action = callWaitingMap.get('default', None)
|
||||||
# wait 30 secs for connect
|
if action:
|
||||||
while ((c_status!="CONNECTED") and (time.time()<start_t+15)):
|
action(CIP, callingParty, calledParty)
|
||||||
cmd=os.popen("/usr/sbin/cinternet --status")
|
cc.disconnect()
|
||||||
lines=cmd.readlines()
|
|
||||||
cmd.close()
|
|
||||||
for l in lines:
|
|
||||||
if (l[0:6]=="status"):
|
|
||||||
c_status=l[9:]
|
|
||||||
c_status=string.strip(c_status)
|
|
||||||
print c_status
|
|
||||||
time.sleep(1)
|
|
||||||
# get ip address
|
|
||||||
save_lang=os.environ["LANG"]
|
|
||||||
os.environ["LANG"]=""
|
|
||||||
cmd=os.popen("/sbin/ifconfig ppp0")
|
|
||||||
lines=cmd.readlines()
|
|
||||||
cmd.close()
|
|
||||||
os.environ["LANG"]=save_lang
|
|
||||||
for l in lines:
|
|
||||||
index=string.find(l,"inet addr:")
|
|
||||||
if (index!=-1):
|
|
||||||
index+=10
|
|
||||||
rindex=string.find(l," ",index)
|
|
||||||
ip_address=l[index:rindex]
|
|
||||||
# play ip address
|
|
||||||
for i in ip_address:
|
|
||||||
cc.audio_send(i+".la")
|
|
||||||
|
|
||||||
cc.disconnect()
|
except cc.CallGoneError:
|
||||||
|
print "schimpf schimpf: call gone"
|
||||||
|
|
||||||
except cc.CallGoneError:
|
cc.callWaiting = callWaiting
|
||||||
print "schimpf schimpf"
|
cc.callConnected = callConnected
|
||||||
|
|
||||||
cc.callWaiting=callWaiting
|
|
||||||
cc.callConnected=callConnected
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Makefile.in generated by automake 1.8.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.1 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
@ -47,6 +47,12 @@ CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
CONFIG_CLEAN_FILES =
|
CONFIG_CLEAN_FILES =
|
||||||
SOURCES =
|
SOURCES =
|
||||||
DIST_SOURCES =
|
DIST_SOURCES =
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||||
am__installdirs = "$(DESTDIR)$(pkgdatadir)"
|
am__installdirs = "$(DESTDIR)$(pkgdatadir)"
|
||||||
dist_pkgdataDATA_INSTALL = $(INSTALL_DATA)
|
dist_pkgdataDATA_INSTALL = $(INSTALL_DATA)
|
||||||
DATA = $(dist_pkgdata_DATA)
|
DATA = $(dist_pkgdata_DATA)
|
||||||
|
@ -113,6 +119,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
am__leading_dot = @am__leading_dot@
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
bindir = @bindir@
|
bindir = @bindir@
|
||||||
build_alias = @build_alias@
|
build_alias = @build_alias@
|
||||||
datadir = @datadir@
|
datadir = @datadir@
|
||||||
|
@ -195,7 +203,7 @@ install-dist_pkgdataDATA: $(dist_pkgdata_DATA)
|
||||||
test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)"
|
test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)"
|
||||||
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
|
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " $(dist_pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \
|
echo " $(dist_pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \
|
||||||
$(dist_pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \
|
$(dist_pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -203,7 +211,7 @@ install-dist_pkgdataDATA: $(dist_pkgdata_DATA)
|
||||||
uninstall-dist_pkgdataDATA:
|
uninstall-dist_pkgdataDATA:
|
||||||
@$(NORMAL_UNINSTALL)
|
@$(NORMAL_UNINSTALL)
|
||||||
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
|
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \
|
echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \
|
||||||
rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \
|
rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -267,7 +275,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@ -328,7 +336,7 @@ uninstall-am: uninstall-dist_pkgdataDATA uninstall-info-am
|
||||||
installcheck installcheck-am installdirs maintainer-clean \
|
installcheck installcheck-am installdirs maintainer-clean \
|
||||||
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
|
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
|
||||||
pdf-am ps ps-am uninstall uninstall-am \
|
pdf-am ps ps-am uninstall uninstall-am \
|
||||||
uninstall-dist_pkgdataDATA uninstall-info-am
|
uninstall-dist_pkgdataDATA uninstall-hook uninstall-info-am
|
||||||
|
|
||||||
|
|
||||||
uninstall-hook:
|
uninstall-hook:
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
import os, fnmatch
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
def findFiles(pattern, subdir=''):
|
||||||
|
files = []
|
||||||
|
for file in os.listdir(os.path.join(Dir('.').srcnode().abspath, subdir)):
|
||||||
|
if fnmatch.fnmatch(file, pattern):
|
||||||
|
files.append(os.path.join(subdir, file))
|
||||||
|
return files
|
||||||
|
|
||||||
|
Alias('install', env.Install('$pkgdatadir/waves', 'README' ))
|
||||||
|
Alias('install', env.Install('$pkgdatadir/waves', findFiles('*.la')))
|
|
@ -4,7 +4,7 @@ sbin_PROGRAMS = capisuite
|
||||||
capisuite_LDADD=application/libccapplication.a modules/libccmodules.a \
|
capisuite_LDADD=application/libccapplication.a modules/libccmodules.a \
|
||||||
backend/libccbackend.a
|
backend/libccbackend.a
|
||||||
capisuite_SOURCES=main.cpp
|
capisuite_SOURCES=main.cpp
|
||||||
SUBDIRS = application backend modules
|
SUBDIRS = application backend modules capisuite-py
|
||||||
|
|
||||||
pkgsysconf_DATA = capisuite.conf
|
pkgsysconf_DATA = capisuite.conf
|
||||||
EXTRA_DIST = capisuite.conf.in
|
EXTRA_DIST = capisuite.conf.in
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Makefile.in generated by automake 1.8.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.1 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
@ -58,7 +58,6 @@ capisuite_DEPENDENCIES = application/libccapplication.a \
|
||||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||||
am__depfiles_maybe = depfiles
|
am__depfiles_maybe = depfiles
|
||||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/main.Po
|
|
||||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||||
CXXLD = $(CXX)
|
CXXLD = $(CXX)
|
||||||
|
@ -72,6 +71,12 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||||
install-recursive installcheck-recursive installdirs-recursive \
|
install-recursive installcheck-recursive installdirs-recursive \
|
||||||
pdf-recursive ps-recursive uninstall-info-recursive \
|
pdf-recursive ps-recursive uninstall-info-recursive \
|
||||||
uninstall-recursive
|
uninstall-recursive
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||||
pkgsysconfDATA_INSTALL = $(INSTALL_DATA)
|
pkgsysconfDATA_INSTALL = $(INSTALL_DATA)
|
||||||
DATA = $(pkgsysconf_DATA)
|
DATA = $(pkgsysconf_DATA)
|
||||||
ETAGS = etags
|
ETAGS = etags
|
||||||
|
@ -140,6 +145,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
am__leading_dot = @am__leading_dot@
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
bindir = @bindir@
|
bindir = @bindir@
|
||||||
build_alias = @build_alias@
|
build_alias = @build_alias@
|
||||||
datadir = @datadir@
|
datadir = @datadir@
|
||||||
|
@ -179,7 +186,7 @@ capisuite_LDADD = application/libccapplication.a modules/libccmodules.a \
|
||||||
backend/libccbackend.a
|
backend/libccbackend.a
|
||||||
|
|
||||||
capisuite_SOURCES = main.cpp
|
capisuite_SOURCES = main.cpp
|
||||||
SUBDIRS = application backend modules
|
SUBDIRS = application backend modules capisuite-py
|
||||||
pkgsysconf_DATA = capisuite.conf
|
pkgsysconf_DATA = capisuite.conf
|
||||||
EXTRA_DIST = capisuite.conf.in
|
EXTRA_DIST = capisuite.conf.in
|
||||||
all: all-recursive
|
all: all-recursive
|
||||||
|
@ -254,16 +261,14 @@ distclean-compile:
|
||||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
.cpp.obj:
|
.cpp.obj:
|
||||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
uninstall-info-am:
|
uninstall-info-am:
|
||||||
install-pkgsysconfDATA: $(pkgsysconf_DATA)
|
install-pkgsysconfDATA: $(pkgsysconf_DATA)
|
||||||
|
@ -271,7 +276,7 @@ install-pkgsysconfDATA: $(pkgsysconf_DATA)
|
||||||
test -z "$(pkgsysconfdir)" || $(mkdir_p) "$(DESTDIR)$(pkgsysconfdir)"
|
test -z "$(pkgsysconfdir)" || $(mkdir_p) "$(DESTDIR)$(pkgsysconfdir)"
|
||||||
@list='$(pkgsysconf_DATA)'; for p in $$list; do \
|
@list='$(pkgsysconf_DATA)'; for p in $$list; do \
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " $(pkgsysconfDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgsysconfdir)/$$f'"; \
|
echo " $(pkgsysconfDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgsysconfdir)/$$f'"; \
|
||||||
$(pkgsysconfDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgsysconfdir)/$$f"; \
|
$(pkgsysconfDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgsysconfdir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -279,7 +284,7 @@ install-pkgsysconfDATA: $(pkgsysconf_DATA)
|
||||||
uninstall-pkgsysconfDATA:
|
uninstall-pkgsysconfDATA:
|
||||||
@$(NORMAL_UNINSTALL)
|
@$(NORMAL_UNINSTALL)
|
||||||
@list='$(pkgsysconf_DATA)'; for p in $$list; do \
|
@list='$(pkgsysconf_DATA)'; for p in $$list; do \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " rm -f '$(DESTDIR)$(pkgsysconfdir)/$$f'"; \
|
echo " rm -f '$(DESTDIR)$(pkgsysconfdir)/$$f'"; \
|
||||||
rm -f "$(DESTDIR)$(pkgsysconfdir)/$$f"; \
|
rm -f "$(DESTDIR)$(pkgsysconfdir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
@ -357,14 +362,16 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
tags=; \
|
tags=; \
|
||||||
here=`pwd`; \
|
here=`pwd`; \
|
||||||
if (etags --etags-include --version) >/dev/null 2>&1; then \
|
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||||
include_option=--etags-include; \
|
include_option=--etags-include; \
|
||||||
|
empty_fix=.; \
|
||||||
else \
|
else \
|
||||||
include_option=--include; \
|
include_option=--include; \
|
||||||
|
empty_fix=; \
|
||||||
fi; \
|
fi; \
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
if test "$$subdir" = .; then :; else \
|
if test "$$subdir" = .; then :; else \
|
||||||
test -f $$subdir/TAGS && \
|
test ! -f $$subdir/TAGS || \
|
||||||
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
||||||
fi; \
|
fi; \
|
||||||
done; \
|
done; \
|
||||||
|
@ -374,9 +381,11 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
done | \
|
done | \
|
||||||
$(AWK) ' { files[$$0] = 1; } \
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
END { for (i in files) print i; }'`; \
|
END { for (i in files) print i; }'`; \
|
||||||
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||||
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
$$tags $$unique
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$tags $$unique; \
|
||||||
|
fi
|
||||||
ctags: CTAGS
|
ctags: CTAGS
|
||||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
|
@ -427,15 +436,17 @@ distdir: $(DISTFILES)
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
done
|
done
|
||||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||||
if test "$$subdir" = .; then :; else \
|
if test "$$subdir" = .; then :; else \
|
||||||
test -d "$(distdir)/$$subdir" \
|
test -d "$(distdir)/$$subdir" \
|
||||||
|| mkdir "$(distdir)/$$subdir" \
|
|| $(mkdir_p) "$(distdir)/$$subdir" \
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
|
distdir=`$(am__cd) $(distdir) && pwd`; \
|
||||||
|
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
|
||||||
(cd $$subdir && \
|
(cd $$subdir && \
|
||||||
$(MAKE) $(AM_MAKEFLAGS) \
|
$(MAKE) $(AM_MAKEFLAGS) \
|
||||||
top_distdir="../$(top_distdir)" \
|
top_distdir="$$top_distdir" \
|
||||||
distdir="../$(distdir)/$$subdir" \
|
distdir="$$distdir/$$subdir" \
|
||||||
distdir) \
|
distdir) \
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
|
@ -467,7 +478,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
env.Append(capisuite_sources = Dir('.'))
|
||||||
|
|
||||||
|
SConscript('capisuite-py/SConscript')
|
||||||
|
libmodule = SConscript('modules/SConscript')
|
||||||
|
libappl = SConscript('application/SConscript')
|
||||||
|
libback = SConscript('backend/SConscript')
|
||||||
|
|
||||||
|
capisuite = env.Program('capisuite',
|
||||||
|
['main.cpp', libappl, libmodule, libback, ])
|
||||||
|
env.AddPostAction(capisuite, 'strip $TARGET')
|
||||||
|
|
||||||
|
capisuite_conf = env.FileSubst('capisuite.conf', 'capisuite.conf.in')
|
||||||
|
|
||||||
|
install_exec = env.Install('$sbindir', capisuite)
|
||||||
|
Alias('install-exec', install_exec)
|
||||||
|
|
||||||
|
Alias('install',
|
||||||
|
env.Install('$pkgsysconfdir', capisuite_conf),
|
||||||
|
install_exec,
|
||||||
|
)
|
|
@ -1,4 +1,4 @@
|
||||||
# Makefile.in generated by automake 1.8.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.1 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
@ -46,9 +46,9 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
CONFIG_HEADER = $(top_builddir)/config.h
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
CONFIG_CLEAN_FILES =
|
CONFIG_CLEAN_FILES =
|
||||||
|
LIBRARIES = $(noinst_LIBRARIES)
|
||||||
AR = ar
|
AR = ar
|
||||||
ARFLAGS = cru
|
ARFLAGS = cru
|
||||||
LIBRARIES = $(noinst_LIBRARIES)
|
|
||||||
libccapplication_a_AR = $(AR) $(ARFLAGS)
|
libccapplication_a_AR = $(AR) $(ARFLAGS)
|
||||||
libccapplication_a_LIBADD =
|
libccapplication_a_LIBADD =
|
||||||
am_libccapplication_a_OBJECTS = capisuite.$(OBJEXT) \
|
am_libccapplication_a_OBJECTS = capisuite.$(OBJEXT) \
|
||||||
|
@ -58,11 +58,6 @@ libccapplication_a_OBJECTS = $(am_libccapplication_a_OBJECTS)
|
||||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||||
am__depfiles_maybe = depfiles
|
am__depfiles_maybe = depfiles
|
||||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/capisuite.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/capisuitemodule.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/idlescript.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/incomingscript.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/pythonscript.Po
|
|
||||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||||
CXXLD = $(CXX)
|
CXXLD = $(CXX)
|
||||||
|
@ -139,6 +134,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
am__leading_dot = @am__leading_dot@
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
bindir = @bindir@
|
bindir = @bindir@
|
||||||
build_alias = @build_alias@
|
build_alias = @build_alias@
|
||||||
datadir = @datadir@
|
datadir = @datadir@
|
||||||
|
@ -235,16 +232,14 @@ distclean-compile:
|
||||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
.cpp.obj:
|
.cpp.obj:
|
||||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
uninstall-info-am:
|
uninstall-info-am:
|
||||||
|
|
||||||
|
@ -268,9 +263,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
done | \
|
done | \
|
||||||
$(AWK) ' { files[$$0] = 1; } \
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
END { for (i in files) print i; }'`; \
|
END { for (i in files) print i; }'`; \
|
||||||
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||||
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
$$tags $$unique
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$tags $$unique; \
|
||||||
|
fi
|
||||||
ctags: CTAGS
|
ctags: CTAGS
|
||||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
|
@ -344,7 +341,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
libappl = env.StaticLibrary('ccapplication', source = Split("""
|
||||||
|
capisuite.cpp capisuitemodule.cpp pythonscript.cpp
|
||||||
|
idlescript.cpp incomingscript.cpp
|
||||||
|
"""))
|
||||||
|
|
||||||
|
Return('libappl')
|
|
@ -89,7 +89,7 @@ bool
|
||||||
convertConnRef(PyObject *conn_ref, Connection** conn)
|
convertConnRef(PyObject *conn_ref, Connection** conn)
|
||||||
{
|
{
|
||||||
if (!PyCObject_Check(conn_ref)) {
|
if (!PyCObject_Check(conn_ref)) {
|
||||||
PyErr_SetString(PyExc_TypeError,"First parameter must be the call reference.");
|
PyErr_SetString(PyExc_TypeError,"Invalid call reference given.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ bool
|
||||||
convertCapiRef(PyObject *capi_ref, Capi** capi)
|
convertCapiRef(PyObject *capi_ref, Capi** capi)
|
||||||
{
|
{
|
||||||
if (!PyCObject_Check(capi_ref)) {
|
if (!PyCObject_Check(capi_ref)) {
|
||||||
PyErr_SetString(PyExc_TypeError,"First parameter must be the Capi reference.");
|
PyErr_SetString(PyExc_TypeError,"Invalid Capi reference given.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,7 +966,7 @@ capisuitemodule_init () throw (ApplicationError)
|
||||||
{
|
{
|
||||||
PyObject *mod,*d;
|
PyObject *mod,*d;
|
||||||
try {
|
try {
|
||||||
if ( ! ( mod=Py_InitModule3("capisuite", PCallControlMethods, "Python module for controlling CapiSuite") ) ) // m=borrowed ref
|
if ( ! ( mod=Py_InitModule3("_capisuite", PCallControlMethods, "Python module for controlling CapiSuite") ) ) // m=borrowed ref
|
||||||
throw ApplicationError("unable to init python module capisuite (InitModule failed)","capisuite_init()");
|
throw ApplicationError("unable to init python module capisuite (InitModule failed)","capisuite_init()");
|
||||||
|
|
||||||
if ( ! ( d=PyModule_GetDict(mod) ) ) // d=borrowed ref
|
if ( ! ( d=PyModule_GetDict(mod) ) ) // d=borrowed ref
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Makefile.in generated by automake 1.8.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.1 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
@ -46,9 +46,9 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
CONFIG_HEADER = $(top_builddir)/config.h
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
CONFIG_CLEAN_FILES =
|
CONFIG_CLEAN_FILES =
|
||||||
|
LIBRARIES = $(noinst_LIBRARIES)
|
||||||
AR = ar
|
AR = ar
|
||||||
ARFLAGS = cru
|
ARFLAGS = cru
|
||||||
LIBRARIES = $(noinst_LIBRARIES)
|
|
||||||
libccbackend_a_AR = $(AR) $(ARFLAGS)
|
libccbackend_a_AR = $(AR) $(ARFLAGS)
|
||||||
libccbackend_a_LIBADD =
|
libccbackend_a_LIBADD =
|
||||||
am_libccbackend_a_OBJECTS = capi.$(OBJEXT) connection.$(OBJEXT)
|
am_libccbackend_a_OBJECTS = capi.$(OBJEXT) connection.$(OBJEXT)
|
||||||
|
@ -56,7 +56,6 @@ libccbackend_a_OBJECTS = $(am_libccbackend_a_OBJECTS)
|
||||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||||
am__depfiles_maybe = depfiles
|
am__depfiles_maybe = depfiles
|
||||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/capi.Po ./$(DEPDIR)/connection.Po
|
|
||||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||||
CXXLD = $(CXX)
|
CXXLD = $(CXX)
|
||||||
|
@ -133,6 +132,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
am__leading_dot = @am__leading_dot@
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
bindir = @bindir@
|
bindir = @bindir@
|
||||||
build_alias = @build_alias@
|
build_alias = @build_alias@
|
||||||
datadir = @datadir@
|
datadir = @datadir@
|
||||||
|
@ -225,16 +226,14 @@ distclean-compile:
|
||||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
.cpp.obj:
|
.cpp.obj:
|
||||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
uninstall-info-am:
|
uninstall-info-am:
|
||||||
|
|
||||||
|
@ -258,9 +257,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
done | \
|
done | \
|
||||||
$(AWK) ' { files[$$0] = 1; } \
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
END { for (i in files) print i; }'`; \
|
END { for (i in files) print i; }'`; \
|
||||||
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||||
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
$$tags $$unique
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$tags $$unique; \
|
||||||
|
fi
|
||||||
ctags: CTAGS
|
ctags: CTAGS
|
||||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
|
@ -334,7 +335,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
libback = env.StaticLibrary('ccbackend', source = Split("""
|
||||||
|
capi.cpp connection.cpp
|
||||||
|
"""))
|
||||||
|
|
||||||
|
Return('libback')
|
|
@ -0,0 +1,12 @@
|
||||||
|
pkgsysconfdir = @sysconfdir@/capisuite
|
||||||
|
|
||||||
|
pkgpython_PYTHON = __init__.py config.py consts.py core.py exceptions.py \
|
||||||
|
fax.py fileutils.py voice.py
|
||||||
|
|
||||||
|
EXTRA_DIST = config.py.in
|
||||||
|
|
||||||
|
config.py: config.py.in
|
||||||
|
rm -f $@
|
||||||
|
sed -e 's,@\pkgsysconfdir@,$(pkgsysconfdir),g' $< >$@
|
||||||
|
|
||||||
|
all-local: config.py
|
|
@ -0,0 +1,347 @@
|
||||||
|
# Makefile.in generated by automake 1.9.1 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
# 2003, 2004 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
top_builddir = ../..
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
subdir = src/capisuite-py
|
||||||
|
DIST_COMMON = $(pkgpython_PYTHON) $(srcdir)/Makefile.am \
|
||||||
|
$(srcdir)/Makefile.in
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||||
|
$(top_srcdir)/configure.in
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
SOURCES =
|
||||||
|
DIST_SOURCES =
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||||
|
am__installdirs = "$(DESTDIR)$(pkgpythondir)"
|
||||||
|
pkgpythonPYTHON_INSTALL = $(INSTALL_DATA)
|
||||||
|
py_compile = $(top_srcdir)/py-compile
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
AMDEP_FALSE = @AMDEP_FALSE@
|
||||||
|
AMDEP_TRUE = @AMDEP_TRUE@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CXX = @CXX@
|
||||||
|
CXXCPP = @CXXCPP@
|
||||||
|
CXXDEPMODE = @CXXDEPMODE@
|
||||||
|
CXXFLAGS = @CXXFLAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
OBJEXT = @OBJEXT@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
PYTHON = @PYTHON@
|
||||||
|
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
|
||||||
|
PYTHON_PLATFORM = @PYTHON_PLATFORM@
|
||||||
|
PYTHON_PREFIX = @PYTHON_PREFIX@
|
||||||
|
PYTHON_VERSION = @PYTHON_VERSION@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_CXX = @ac_ct_CXX@
|
||||||
|
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||||
|
ac_ct_STRIP = @ac_ct_STRIP@
|
||||||
|
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||||
|
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||||
|
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||||
|
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
bindir = @bindir@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
datadir = @datadir@
|
||||||
|
docdir = @docdir@
|
||||||
|
doxygen = @doxygen@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
pkgpyexecdir = @pkgpyexecdir@
|
||||||
|
pkgpythondir = @pkgpythondir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
pyexecdir = @pyexecdir@
|
||||||
|
python_configdir = @python_configdir@
|
||||||
|
python_execprefix = @python_execprefix@
|
||||||
|
python_includespec = @python_includespec@
|
||||||
|
python_linkforshared = @python_linkforshared@
|
||||||
|
python_moduledir = @python_moduledir@
|
||||||
|
python_moduleexecdir = @python_moduleexecdir@
|
||||||
|
python_prefix = @python_prefix@
|
||||||
|
python_version = @python_version@
|
||||||
|
pythondir = @pythondir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
target_alias = @target_alias@
|
||||||
|
pkgsysconfdir = @sysconfdir@/capisuite
|
||||||
|
pkgpython_PYTHON = __init__.py config.py consts.py core.py exceptions.py \
|
||||||
|
fax.py fileutils.py voice.py
|
||||||
|
|
||||||
|
EXTRA_DIST = config.py.in
|
||||||
|
all: all-am
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||||
|
&& exit 0; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/capisuite-py/Makefile'; \
|
||||||
|
cd $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --gnu src/capisuite-py/Makefile
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
uninstall-info-am:
|
||||||
|
install-pkgpythonPYTHON: $(pkgpython_PYTHON)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
test -z "$(pkgpythondir)" || $(mkdir_p) "$(DESTDIR)$(pkgpythondir)"
|
||||||
|
@list='$(pkgpython_PYTHON)'; dlist=''; for p in $$list; do\
|
||||||
|
if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \
|
||||||
|
if test -f $$b$$p; then \
|
||||||
|
f=$(am__strip_dir) \
|
||||||
|
dlist="$$dlist $$f"; \
|
||||||
|
echo " $(pkgpythonPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(pkgpythondir)/$$f'"; \
|
||||||
|
$(pkgpythonPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(pkgpythondir)/$$f"; \
|
||||||
|
else :; fi; \
|
||||||
|
done; \
|
||||||
|
test -z "$$dlist" || \
|
||||||
|
PYTHON=$(PYTHON) $(py_compile) --basedir "$(DESTDIR)$(pkgpythondir)" $$dlist
|
||||||
|
|
||||||
|
uninstall-pkgpythonPYTHON:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list='$(pkgpython_PYTHON)'; dlist=''; for p in $$list; do\
|
||||||
|
f=$(am__strip_dir) \
|
||||||
|
rm -f "$(DESTDIR)$(pkgpythondir)/$$f"; \
|
||||||
|
rm -f "$(DESTDIR)$(pkgpythondir)/$${f}c"; \
|
||||||
|
rm -f "$(DESTDIR)$(pkgpythondir)/$${f}o"; \
|
||||||
|
done
|
||||||
|
tags: TAGS
|
||||||
|
TAGS:
|
||||||
|
|
||||||
|
ctags: CTAGS
|
||||||
|
CTAGS:
|
||||||
|
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||||
|
list='$(DISTFILES)'; for file in $$list; do \
|
||||||
|
case $$file in \
|
||||||
|
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||||
|
esac; \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||||
|
dir="/$$dir"; \
|
||||||
|
$(mkdir_p) "$(distdir)$$dir"; \
|
||||||
|
else \
|
||||||
|
dir=''; \
|
||||||
|
fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||||
|
fi; \
|
||||||
|
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
all-am: Makefile all-local
|
||||||
|
installdirs:
|
||||||
|
for dir in "$(DESTDIR)$(pkgpythondir)"; do \
|
||||||
|
test -z "$$dir" || $(mkdir_p) "$$dir"; \
|
||||||
|
done
|
||||||
|
install: install-am
|
||||||
|
install-exec: install-exec-am
|
||||||
|
install-data: install-data-am
|
||||||
|
uninstall: uninstall-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
`test -z '$(STRIP)' || \
|
||||||
|
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
clean-am: clean-generic mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-generic
|
||||||
|
|
||||||
|
dvi: dvi-am
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
|
info: info-am
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am: install-pkgpythonPYTHON
|
||||||
|
|
||||||
|
install-exec-am:
|
||||||
|
|
||||||
|
install-info: install-info-am
|
||||||
|
|
||||||
|
install-man:
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-generic
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am: uninstall-info-am uninstall-pkgpythonPYTHON
|
||||||
|
|
||||||
|
.PHONY: all all-am all-local check check-am clean clean-generic \
|
||||||
|
distclean distclean-generic distdir dvi dvi-am html html-am \
|
||||||
|
info info-am install install-am install-data install-data-am \
|
||||||
|
install-exec install-exec-am install-info install-info-am \
|
||||||
|
install-man install-pkgpythonPYTHON install-strip installcheck \
|
||||||
|
installcheck-am installdirs maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
|
||||||
|
pdf-am ps ps-am uninstall uninstall-am uninstall-info-am \
|
||||||
|
uninstall-pkgpythonPYTHON
|
||||||
|
|
||||||
|
|
||||||
|
config.py: config.py.in
|
||||||
|
rm -f $@
|
||||||
|
sed -e 's,@\pkgsysconfdir@,$(pkgsysconfdir),g' $< >$@
|
||||||
|
|
||||||
|
all-local: config.py
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
|
@ -0,0 +1,27 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
def py_compile(target, source, env):
|
||||||
|
"""compile python modules for .../python2.x/site-packages/capisuite"""
|
||||||
|
# Note: this differs from #/scripts/SConscript.py_compile in 'dfile'
|
||||||
|
import py_compile, os.path
|
||||||
|
py_compile.compile(source[0].abspath,
|
||||||
|
#cfile=target[0].abspath,
|
||||||
|
dfile = os.path.join(env.subst('$pkgpython_moduledir'),
|
||||||
|
env.subst('$SOURCE.file')),
|
||||||
|
)
|
||||||
|
|
||||||
|
# substitute "pgksysconfdir"
|
||||||
|
env.FileSubst('config.py', 'config.py.in')
|
||||||
|
|
||||||
|
modules = []
|
||||||
|
for mod in Split('__init__ config consts fax fileutils voice exceptions '
|
||||||
|
'core'):
|
||||||
|
modules.append(mod+'.py')
|
||||||
|
modules.append(env.Command(mod + '.pyc', mod+'.py', py_compile))
|
||||||
|
|
||||||
|
install_pylib = env.Install('$pkgpython_moduledir', modules)
|
||||||
|
|
||||||
|
Alias('install-pylib',install_pylib)
|
||||||
|
Alias('install', install_pylib)
|
|
@ -0,0 +1,24 @@
|
||||||
|
"""capisuite
|
||||||
|
|
||||||
|
The main package of CapiSuite. This package provides the interface between
|
||||||
|
the user programmable Python scripts for handling incoming and outgoing calls
|
||||||
|
and the CapiSuite core which makes the ISDN hardware available.
|
||||||
|
|
||||||
|
This package consists of several files containing classes for certain aspects:
|
||||||
|
|
||||||
|
- core: provides the basic access to all functions of the CapiSuite core
|
||||||
|
- fax: contains all routines necessary for fax connection handling
|
||||||
|
- voice: contains all routines necessary for voice connection handling
|
||||||
|
- config: allows to read and write configuration and job description files
|
||||||
|
- fileutils: contains general file handling routines typically needed
|
||||||
|
by CapiSuite scripts
|
||||||
|
- consts: some constant definitions
|
||||||
|
- exceptions: collection of exception classes used by the classes and functions
|
||||||
|
in the other files
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
||||||
|
__copyright__ = "Copyright (c) 2004 by Hartmut Goebel"
|
||||||
|
__version__ = "$Revision: 0.0 $"
|
||||||
|
__credits__ = "This is part of www.capisuite.de; thanks to Gernot Hiller"
|
|
@ -0,0 +1,216 @@
|
||||||
|
# -*- mode: python -*-
|
||||||
|
"""capisuite.config
|
||||||
|
|
||||||
|
Handling of configuration and job description files.
|
||||||
|
|
||||||
|
This file contains CSConfigParser, a configuration parser derived from the
|
||||||
|
default Python parsers, but adapted to the needs of CapiSuite.
|
||||||
|
|
||||||
|
Additionally, the class JobDescription is defined, which allows to read and
|
||||||
|
write special text files used to store meta data about incoming and outgoing
|
||||||
|
voice and fax jobs/calls.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
||||||
|
__copyright__ = "Copyright (c) 2004 by Hartmut Goebel"
|
||||||
|
__version__ = "$Revision: 0.0 $"
|
||||||
|
__credits__ = "This is part of www.capisuite.de; thanks to Gernot Hiller"
|
||||||
|
|
||||||
|
import os.path, types, string
|
||||||
|
|
||||||
|
# the name of the config file read by the scripts; see there for
|
||||||
|
# options and descriptions
|
||||||
|
pkgsysconfdir = "@pkgsysconfdir@"
|
||||||
|
|
||||||
|
configfile_fax = os.path.join(pkgsysconfdir, "fax.conf")
|
||||||
|
configfile_voice = os.path.join(pkgsysconfdir, "answering_machine.conf")
|
||||||
|
|
||||||
|
__all__ = ['configfile_fax', 'configfile_voice',
|
||||||
|
'CSConfigParser', 'JobDescription',
|
||||||
|
'readGlobalConfig', 'readDescription', 'createDescriptionFor',
|
||||||
|
'NoOptionError', 'NoGlobalSectionError']
|
||||||
|
|
||||||
|
# try to use RawConfigParser if available
|
||||||
|
try:
|
||||||
|
from ConfigParser import RawConfigParser as ConfigParser
|
||||||
|
except:
|
||||||
|
from ConfigParser import ConfigParser as ConfigParser
|
||||||
|
|
||||||
|
# capisuite stuff
|
||||||
|
import consts
|
||||||
|
#from exceptions import NoGlobalSectionError
|
||||||
|
|
||||||
|
#--- spezialied ConfigParser --#
|
||||||
|
|
||||||
|
class CSConfigParser(ConfigParser):
|
||||||
|
"""
|
||||||
|
Specialized version of Python ConfigParser:
|
||||||
|
- if no filenames are given, read the default config files
|
||||||
|
- values are automatically quoted on setting (if required) und
|
||||||
|
unquoted on reading
|
||||||
|
"""
|
||||||
|
|
||||||
|
def read(self, filenames):
|
||||||
|
"""Read configuration files given as filenames. If no names are given,
|
||||||
|
the default fax and voice files are read.
|
||||||
|
"""
|
||||||
|
if not filenames:
|
||||||
|
ConfigParser.read(self, configfile_fax)
|
||||||
|
ConfigParser.read(self, configfile_voice)
|
||||||
|
else:
|
||||||
|
ConfigParser.read(self, filenames)
|
||||||
|
|
||||||
|
def get(self, section, option):
|
||||||
|
"""Get the value of the option from the given section (w/o quot. marks)."""
|
||||||
|
value = ConfigParser.get(self, section, option)
|
||||||
|
if len(value) > 1 and value[0] == '"':
|
||||||
|
value = value[1:-1]
|
||||||
|
self.set(section, option, value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def getList(self, section, option):
|
||||||
|
"""Return the value of the option from the given section as a list.
|
||||||
|
Commas are used as separators and leading and trailing whitespaces are
|
||||||
|
removed from all items."""
|
||||||
|
return map(string.strip, self.get(section, option).split(','))
|
||||||
|
|
||||||
|
def getUser(self, user, option, default=None, fail=0):
|
||||||
|
"""Get an option from the user or global section.
|
||||||
|
|
||||||
|
The option is searched in the user's section and if not found
|
||||||
|
in the global section.
|
||||||
|
|
||||||
|
'config' the ConfigParser object containing the values
|
||||||
|
'user' user section to use, if empty only global section is read
|
||||||
|
'option' the name of the option to search for
|
||||||
|
|
||||||
|
Returns the value for this option or None if it's not found
|
||||||
|
"""
|
||||||
|
if self.has_option(user, option):
|
||||||
|
return self.get(user, option)
|
||||||
|
elif self.has_option('GLOBAL', option):
|
||||||
|
return self.get('GLOBAL', option)
|
||||||
|
elif fail:
|
||||||
|
raise NoOptionError(user, option)
|
||||||
|
else:
|
||||||
|
return default
|
||||||
|
|
||||||
|
def listUsers(self):
|
||||||
|
ul = [ u
|
||||||
|
for u in self.sections()
|
||||||
|
if u not in consts.__known_sections__ ]
|
||||||
|
return ul
|
||||||
|
|
||||||
|
def items(self, section):
|
||||||
|
"""
|
||||||
|
Return a dictionary (name, value) for each option in the section.
|
||||||
|
|
||||||
|
NB: This differs from ConfigParser.items() which returns a list of
|
||||||
|
tuples!
|
||||||
|
"""
|
||||||
|
items = {}
|
||||||
|
for key, value in ConfigParser.items(self, section):
|
||||||
|
if len(value) > 1 and value[0] == '"':
|
||||||
|
value = value[1:-1]
|
||||||
|
items[key] = value
|
||||||
|
return items
|
||||||
|
|
||||||
|
def set(self, section, option, value):
|
||||||
|
if isinstance(value, types.StringTypes):
|
||||||
|
if not value or value[0].isspace() or value[-1].isspace():
|
||||||
|
value = '"%s"' % value
|
||||||
|
ConfigParser.set(self, section, option, value)
|
||||||
|
|
||||||
|
|
||||||
|
class JobDescription:
|
||||||
|
def __init__(self, filename=None, defaults=None):
|
||||||
|
self._config = config = CSConfigParser(defaults)
|
||||||
|
config.add_section('GLOBAL')
|
||||||
|
if filename:
|
||||||
|
config.read(filename)
|
||||||
|
|
||||||
|
def add_section(self, section):
|
||||||
|
if 1: # PyChecker should _not_ take this a an abstract method
|
||||||
|
raise NotImplementedError
|
||||||
|
remove_section = add_section
|
||||||
|
|
||||||
|
def options(self): return self._config.options('GLOBAL')
|
||||||
|
def items(self): return self._config.items('GLOBAL')
|
||||||
|
def get(self, option): return self._config.get('GLOBAL', option)
|
||||||
|
def getint(self, option): return self._config.getint('GLOBAL', option)
|
||||||
|
def getfloat(self, option): return self._config.getfloat('GLOBAL', option)
|
||||||
|
def getboolean(self, option): return self._config.getboolean('GLOBAL', option)
|
||||||
|
def has_option(self, option): return self._config.has_option('GLOBAL', option)
|
||||||
|
def set(self, option, value): return self._config.set('GLOBAL', option, value)
|
||||||
|
def remove_option(self, option): return self._config.remove_option('GLOBAL',option)
|
||||||
|
def read(self, filenames): return self._config.read(filenames)
|
||||||
|
def readfp(self, fp, filename=None): return self._config.read(fp, filename)
|
||||||
|
|
||||||
|
def write(self, fp):
|
||||||
|
print >> fp, "# Description file for", self.get('filename')
|
||||||
|
print >> fp, "# This if for internal use of CapiSuite."
|
||||||
|
print >> fp, "# Only change if you know what you do!"
|
||||||
|
self._config.write(fp)
|
||||||
|
|
||||||
|
|
||||||
|
def x__getattr__(self, attr):
|
||||||
|
return getattr(self._config, attr)
|
||||||
|
def x__setattr__(self, attr, value):
|
||||||
|
setattr(self._config, attr, value)
|
||||||
|
|
||||||
|
###--- utility functions ---###
|
||||||
|
|
||||||
|
|
||||||
|
def readGlobalConfig(file=None):
|
||||||
|
"""read configuration file and return a ConfigParser object
|
||||||
|
|
||||||
|
The configfile is read from the path given above and the
|
||||||
|
surrounding quotation marks from the values are removed.
|
||||||
|
|
||||||
|
Returns the constructed CSConfigParser object
|
||||||
|
"""
|
||||||
|
config = CSConfigParser()
|
||||||
|
config.read(file)
|
||||||
|
if not config.has_section('GLOBAL'):
|
||||||
|
raise NoGlobalSectionError()
|
||||||
|
return config
|
||||||
|
|
||||||
|
def readDescription(jobfilename):
|
||||||
|
"""read (job) description file for received fax or voice
|
||||||
|
|
||||||
|
This function reads an INI-style description file which has prior
|
||||||
|
been written by writeDesc() .
|
||||||
|
|
||||||
|
jobfilename the job' filename (with extension .txt)
|
||||||
|
|
||||||
|
Returns the filename the data filename (with extension) and
|
||||||
|
content the description as a dictionary
|
||||||
|
"""
|
||||||
|
control = JobDescription()
|
||||||
|
control.read(jobfilename)
|
||||||
|
filename = control.get('filename')
|
||||||
|
description = control.items()
|
||||||
|
return filename, description
|
||||||
|
|
||||||
|
|
||||||
|
def createDescriptionFor(filename, **description):
|
||||||
|
"""write (job) description file for received fax or voice
|
||||||
|
|
||||||
|
This function writes an INI-style description file for the given
|
||||||
|
data file which can later on be read by the CSConfigParser
|
||||||
|
instance. The data file name is used, the extension stripped and
|
||||||
|
replaced by .txt
|
||||||
|
|
||||||
|
filename the data filename (with extension),
|
||||||
|
content the description as a dictionary
|
||||||
|
"""
|
||||||
|
assert isinstance(description, dict)
|
||||||
|
descrname = os.path.splitext(filename)[0] + '.txt'
|
||||||
|
control = JobDescription()
|
||||||
|
control.set('filename', filename)
|
||||||
|
for key, value in description.items():
|
||||||
|
control.set(key, value)
|
||||||
|
descr = open(descrname, 'w')
|
||||||
|
control.write(descr)
|
||||||
|
descr.close()
|
||||||
|
return descrname
|
|
@ -0,0 +1,38 @@
|
||||||
|
"""capisuite.consts
|
||||||
|
|
||||||
|
Constant defintions for the capisuite Python package.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
||||||
|
__copyright__ = "Copyright (c) 2004 by Hartmut Goebel"
|
||||||
|
__version__ = "$Revision: 0.0 $"
|
||||||
|
__credits__ = "This part of www.capisuite.de; thanks to Gernot Hiller"
|
||||||
|
|
||||||
|
SEND_Q = 'sendq'
|
||||||
|
RECEIVED_Q = 'received'
|
||||||
|
|
||||||
|
__known_sections__ = ('GLOBAL',
|
||||||
|
'Mail Fax Sent',
|
||||||
|
'Mail Fax Failed',
|
||||||
|
'Mail Fax Received',
|
||||||
|
'Mail Voice Received')
|
||||||
|
|
||||||
|
# capi return codes:
|
||||||
|
# 34D8 = Incompatible destination
|
||||||
|
|
||||||
|
# returncodes from call_voice and call_faxG3
|
||||||
|
CONNECTION_ESTABLISHED = 0
|
||||||
|
CONNECTION_TIMEOUT_EXCEEDED = 1
|
||||||
|
CONNECTION_FAILED_UNKNONW_REASON = 2
|
||||||
|
|
||||||
|
"""
|
||||||
|
reject causes:
|
||||||
|
1 = ignore call
|
||||||
|
2 = normal call clearing
|
||||||
|
3 = user busy
|
||||||
|
7 = incompatible destination
|
||||||
|
8 = destination out of order
|
||||||
|
0x34A9 = temporary failure
|
||||||
|
"""
|
||||||
|
|
|
@ -0,0 +1,433 @@
|
||||||
|
"""capisuite.core
|
||||||
|
|
||||||
|
This module exposes the built-in core of capisuite.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
||||||
|
__copyright__ = "Copyright (c) 2004 by Hartmut Goebel"
|
||||||
|
__version__ = "$Revision: 0.0 $"
|
||||||
|
__credits__ = "This part of www.capisuite.de; thanks to Gernot Hiller"
|
||||||
|
|
||||||
|
|
||||||
|
# _capisuite may only be imported when running within capisuite
|
||||||
|
try:
|
||||||
|
# import all capisuite symbols in the namespace "_capisuite.symbol"
|
||||||
|
import _capisuite
|
||||||
|
# now add symbols directly used by the scripts to our namespace
|
||||||
|
from _capisuite import log,error,SERVICE_VOICE,SERVICE_FAXG3,CallGoneError
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
#########
|
||||||
|
###
|
||||||
|
### ATTENTION: This interface is not yet stable. You may expect
|
||||||
|
### changes until capisuite 0.5 is released!
|
||||||
|
###
|
||||||
|
#########
|
||||||
|
|
||||||
|
class Capi:
|
||||||
|
def __init__(self, handle):
|
||||||
|
"""
|
||||||
|
handle: a capi handle as received from _capisuite (given to the idle
|
||||||
|
function as parameter)
|
||||||
|
"""
|
||||||
|
self._handle = handle
|
||||||
|
|
||||||
|
|
||||||
|
def call_voice(self, controller, call_from, call_to,
|
||||||
|
timeout, clir=0):
|
||||||
|
"""
|
||||||
|
Initiate an outgoing call with service voice and wait for
|
||||||
|
successful connection.
|
||||||
|
|
||||||
|
This will initiate an outgoing call and choose voice as
|
||||||
|
service, so you can use the audio commands (like audio_receive()
|
||||||
|
and audio_send()) with this connection. After this command has
|
||||||
|
finished, the call is connected successfully or the given
|
||||||
|
timeout has exceeded. The timeout is measured beginning at the
|
||||||
|
moment when the call is signalled (it's "ringing") to the
|
||||||
|
called party.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
controller: ISDN controller ID to use
|
||||||
|
call_from: own number to use (string)
|
||||||
|
call_to: the number to call (string)
|
||||||
|
timeout: timeout in seconds to wait for connection establishment
|
||||||
|
clir: disable sending of own number (default=0, send number)
|
||||||
|
|
||||||
|
On success returns a call object; on failure returns an
|
||||||
|
error_code.
|
||||||
|
"""
|
||||||
|
call, result = _capisuite.call_voice(self.handle, controller,
|
||||||
|
call_from, call_to,
|
||||||
|
timeout, clir)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
return Call(call, SERVICE_VOICE, call_from, call_to)
|
||||||
|
|
||||||
|
|
||||||
|
def call_faxG3(self, controller, call_from, call_to,
|
||||||
|
timeout, stationID, headline, clir=0):
|
||||||
|
"""
|
||||||
|
Initiate an outgoing call with service faxG3 and wait for
|
||||||
|
successful connection.
|
||||||
|
|
||||||
|
This will initiate an outgoing call and choose fax group 3 as
|
||||||
|
service, so you can use the fax commands (like fax_send() and
|
||||||
|
fax_receive()) with this connection. After this command has
|
||||||
|
finished, the call is connected successfully or the given
|
||||||
|
timeout has exceeded. The timeout is measured beginning at the
|
||||||
|
moment when the call is signalled (it's "ringing") to the
|
||||||
|
called party.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
controller: ISDN controller ID to use
|
||||||
|
call_from: own number to use (string)
|
||||||
|
call_to: the number to call (string)
|
||||||
|
timeout: timeout in seconds to wait for connection establishment
|
||||||
|
faxStationID: fax station ID (string)
|
||||||
|
faxHeadline: fax headline to print on every page (string)
|
||||||
|
clir: disable sending of own number (default=0, send number)
|
||||||
|
|
||||||
|
On success returns a call object; on failure returns an
|
||||||
|
error_code.
|
||||||
|
"""
|
||||||
|
call, result = _capisuite.call_faxG3(self.handle, controller,
|
||||||
|
call_from, call_to,
|
||||||
|
timeout, stationID, headline)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
return Call(call, SERVICE_FAXG3, call_from, call_to)
|
||||||
|
|
||||||
|
|
||||||
|
class Call:
|
||||||
|
def __init__(self, handle, service, call_from, call_to):
|
||||||
|
"""
|
||||||
|
handle: a call handle as received from _capisuite
|
||||||
|
|
||||||
|
NB: A Call instance is never True to ease testing results from
|
||||||
|
Capi.call_...()
|
||||||
|
"""
|
||||||
|
self._handle = handle
|
||||||
|
self.service = service
|
||||||
|
self.from_nr = call_from
|
||||||
|
self.to_nr = call_to
|
||||||
|
|
||||||
|
###--- python stuff --###
|
||||||
|
|
||||||
|
def __nonzero__(self):
|
||||||
|
# 'if Call()' must never be true to allow easier results from
|
||||||
|
# Capi.call_...()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self._handle)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
# todo: add service, call_from, call_to
|
||||||
|
return repr(self._handle)
|
||||||
|
|
||||||
|
|
||||||
|
###--- general --###
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
"""
|
||||||
|
Disconnect connection.
|
||||||
|
|
||||||
|
This will cause an immediate disconnection. It should be
|
||||||
|
always the last command in every flow of a script.
|
||||||
|
|
||||||
|
Returns a tuple of two result values. The first is the
|
||||||
|
disconnect cause of the physical connection, the second the
|
||||||
|
disconnect cause of the logical connection. See CAPI spec for
|
||||||
|
the logical causes and ETS 300 102-01 for the physical causes.
|
||||||
|
"""
|
||||||
|
result = _capisuite.disconnect(self._handle)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def reject(self, rejectCause):
|
||||||
|
"""
|
||||||
|
Reject an incoming call.
|
||||||
|
|
||||||
|
If you don't want to accept an incoming call for any reason
|
||||||
|
(e.g. if it has a service or comes from a number you don't
|
||||||
|
want to accept), use this command. There are several reasons
|
||||||
|
you can give when rejecting a call. Some important ones are:
|
||||||
|
|
||||||
|
rejectCause: cause to signal when rejecting call. This may be one of
|
||||||
|
1 = ignore call
|
||||||
|
2 = normal call clearing
|
||||||
|
3 = user busy
|
||||||
|
7 = incompatible destination
|
||||||
|
8 = destination out of order
|
||||||
|
0x34A9 = temporary failure
|
||||||
|
"""
|
||||||
|
_capisuite.reject(self._handle, rejectCause)
|
||||||
|
|
||||||
|
def log(self, message, level):
|
||||||
|
"""
|
||||||
|
Log a connection dependent message.
|
||||||
|
|
||||||
|
This function writes a message to the CapiSuite log. As all messages
|
||||||
|
written with it are prefixed with the current call reference, you
|
||||||
|
should use it for connection-dependant messages (e.g. information about
|
||||||
|
handling *this* call).
|
||||||
|
|
||||||
|
If you want to log messages of general nature not associated with a
|
||||||
|
certain call (e.g. problem in reading configuration files), please use
|
||||||
|
core.log instead.
|
||||||
|
|
||||||
|
message: the log message to be written
|
||||||
|
level: parameter for CapiSuite log_level used (0=vital .. 3=debug info)
|
||||||
|
"""
|
||||||
|
_capisuite.log(message, level, self._handle)
|
||||||
|
|
||||||
|
###--- DTMF support --###
|
||||||
|
|
||||||
|
def enable_DTMF(self):
|
||||||
|
"""
|
||||||
|
Enable recognition of DTMF tones.
|
||||||
|
"""
|
||||||
|
_capisuite.enable_DTMF(self._handle)
|
||||||
|
|
||||||
|
def disable_DTMF(self):
|
||||||
|
"""
|
||||||
|
Disable recognition of DTMF tones.
|
||||||
|
"""
|
||||||
|
_capisuite.disable_DTMF(self._handle)
|
||||||
|
|
||||||
|
|
||||||
|
def read_DTMF(self, timeout, min_digits=0, max_digits=0):
|
||||||
|
"""
|
||||||
|
Read the received DTMF tones or wait for a certain amount of
|
||||||
|
them.
|
||||||
|
|
||||||
|
This function allows to just read in the DTMF tones which were
|
||||||
|
already received. But it also supports to wait for a certain
|
||||||
|
amount of DTMF tones if you want the user to always input some
|
||||||
|
digits at a certain step in your script.
|
||||||
|
|
||||||
|
You can specify how much DTMF tones you want in several ways -
|
||||||
|
see the parameter description. To just see if something was
|
||||||
|
entered before, use capisuite.read_DTMF(0). If you want to get
|
||||||
|
at least 1 and mostly 4 digits and want to wait 5 seconds for
|
||||||
|
additional digits, you'll use capisuite.read_DTMF(5,1,4).
|
||||||
|
|
||||||
|
Valid DTMF characters are '0'...'9','A'...'D' and two special
|
||||||
|
fax tones: 'X' (CNG), 'Y' (CED)
|
||||||
|
|
||||||
|
timeout: timeout in seconds after which reading is terminated;
|
||||||
|
only applied after min_digits have been read! (-1 =
|
||||||
|
infinite)
|
||||||
|
min_digits: minimum number of digits which must be read in ANY
|
||||||
|
case, i.e. timout doesn't count here (default: 0)
|
||||||
|
max_digits: maximum number of digits to read; aborts
|
||||||
|
immediately enough digits are read) (default:
|
||||||
|
0=infinite, i.e. wait until timeout is reached)
|
||||||
|
|
||||||
|
Returns a string containing the characters read.
|
||||||
|
"""
|
||||||
|
# todo: descibe what A...D means and where '#' and '*' go
|
||||||
|
return _capisuite.read_DTMF(self._handle, timeout,
|
||||||
|
min_digits, max_digits)
|
||||||
|
|
||||||
|
|
||||||
|
###--- voice calls ---###
|
||||||
|
|
||||||
|
def connect_voice (self, delay=0):
|
||||||
|
"""
|
||||||
|
Accept an incoming call and connect with voice service.
|
||||||
|
|
||||||
|
This will accept an incoming call and choose voice as service,
|
||||||
|
so you can use the audio commands (like audio_receive() and
|
||||||
|
audio_send()) with this connection. After this command has
|
||||||
|
finished, the call is connected successfully.
|
||||||
|
|
||||||
|
It's also possible to accept a call with some delay. This is
|
||||||
|
useful for an answering machine if you want to fetch a call
|
||||||
|
with your phone before your computer answers it.
|
||||||
|
|
||||||
|
delay: delay in seconds _before_ connection will be established
|
||||||
|
(default: 0=immediate connect)
|
||||||
|
"""
|
||||||
|
_capisuite.connect_voice(self._handle, delay)
|
||||||
|
|
||||||
|
|
||||||
|
def audio_receive(self, filename, timeout, silence_timeout=0,
|
||||||
|
exit_DTMF=0):
|
||||||
|
"""
|
||||||
|
Receive an audio file in a speech mode connection.
|
||||||
|
|
||||||
|
This functions receives an audio file. It can recognize
|
||||||
|
silence in the signal and timeout after a given period of
|
||||||
|
silence, after a general timeout or after the reception of a
|
||||||
|
DTMF signal.
|
||||||
|
|
||||||
|
If the recording was finished because of silence_timeout, the
|
||||||
|
silence will be truncated away.
|
||||||
|
|
||||||
|
If DTMF abort is enabled, the command will also abort
|
||||||
|
immediately if DTMF was received before it is called. This
|
||||||
|
allows to abort subsequent audio receive and send commands
|
||||||
|
with one DTMF signal w/o the need to check for received DTMF
|
||||||
|
after each command.
|
||||||
|
|
||||||
|
The connction must be in audio mode (by connect_voice()),
|
||||||
|
otherwise an exception will be caused.
|
||||||
|
|
||||||
|
The created file will be saved in bit-reversed A-Law format, 8
|
||||||
|
kHz mono. Use sox to convert it to a normal wav file.
|
||||||
|
|
||||||
|
filename: where to save the received message.
|
||||||
|
timeout: receive length in seconds (-1 = infinite).
|
||||||
|
silence_timeout: abort after x seconds of silence (default: no timeout)
|
||||||
|
exit_DTMF: abort sending when a DTMF signal is received (default: 0)
|
||||||
|
|
||||||
|
Returns duration of receiving in seconds.
|
||||||
|
"""
|
||||||
|
return _capisuite.audio_receive(self._handle, filename, timeout,
|
||||||
|
silence_timeout, exit_DTMF)
|
||||||
|
|
||||||
|
|
||||||
|
def audio_send(self, filename, exit_DTMF=0):
|
||||||
|
"""
|
||||||
|
Send an audio file in a speech mode connection.
|
||||||
|
|
||||||
|
This function sends an audio file, which must be in
|
||||||
|
bit-inversed A-Law format. Thus files can be created with eg.
|
||||||
|
sox using the suffix ".la". It supports abortion if DTMF
|
||||||
|
signal is received.
|
||||||
|
|
||||||
|
If DTMF abort is enabled, the command will also abort
|
||||||
|
immediately if DTMF was received before it is called. That
|
||||||
|
allows you to abort subsequent audio receive and send commands
|
||||||
|
with one DTMF signal w/o the need to check for received DTMF
|
||||||
|
after each command.
|
||||||
|
|
||||||
|
The connction must be in audio mode (use connect_voice()),
|
||||||
|
otherwise an exception will be caused.
|
||||||
|
|
||||||
|
filename: file to send
|
||||||
|
exit_DTMF: abort sending when a DTMF signal is received (default: 0)
|
||||||
|
|
||||||
|
Returns duration of send in seconds.
|
||||||
|
"""
|
||||||
|
return _capisuite.audio_send(self._handle, filename, exit_DTMF)
|
||||||
|
|
||||||
|
|
||||||
|
def switch_to_faxG3(self, faxStationID, faxHeadline):
|
||||||
|
"""
|
||||||
|
Switch a connection from voice mode to fax mode.
|
||||||
|
|
||||||
|
This will switch from voice mode to fax group 3 after you have
|
||||||
|
connected, so you can use the fax commands afterwards.
|
||||||
|
|
||||||
|
Attention: Not all ISDN cards or CAPI driver support this
|
||||||
|
command.
|
||||||
|
|
||||||
|
faxStationID: the station ID to use (string)
|
||||||
|
faxHeadline: the fax headline to use (string)
|
||||||
|
|
||||||
|
Returns a FaxInfo instance.
|
||||||
|
"""
|
||||||
|
faxInfo = _capisuite.switch_to_faxG3(self._handle,
|
||||||
|
faxStationID, faxHeadline)
|
||||||
|
self.service = SERVICE_FAXG3
|
||||||
|
if not faxInfo:
|
||||||
|
return FaxInfo()
|
||||||
|
return FaxInfo(*faxInfo)
|
||||||
|
|
||||||
|
|
||||||
|
###--- fax calls --###
|
||||||
|
|
||||||
|
def connect_faxG3(self, faxStationID, faxHeadline, delay=0):
|
||||||
|
"""
|
||||||
|
Accept an incoming call and connect with fax (analog, group 3) service.
|
||||||
|
|
||||||
|
This will accept an incoming call and choose fax group 3 as
|
||||||
|
service, so you can use the fax commands (like fax_receive())
|
||||||
|
with this connection. After this command has finished, the
|
||||||
|
call is connected successfully.
|
||||||
|
|
||||||
|
It's also possible to accept a call with some delay. This is
|
||||||
|
useful if eg. you want to have to fetch a call with your phone
|
||||||
|
before your computer answers it.
|
||||||
|
|
||||||
|
faxStationID: the station ID to use (string)
|
||||||
|
faxHeadline: the fax headline to use (string)
|
||||||
|
delay: delay in seconds _before_ connection will be established
|
||||||
|
(default: 0=immediate connect)
|
||||||
|
|
||||||
|
Returns a FaxInfo instance.
|
||||||
|
"""
|
||||||
|
faxInfo = _capisuite.connect_faxG3(self._handle, faxStationID,
|
||||||
|
faxHeadline, delay)
|
||||||
|
if not faxInfo:
|
||||||
|
return FaxInfo()
|
||||||
|
return FaxInfo(*faxInfo)
|
||||||
|
|
||||||
|
|
||||||
|
def fax_send(self, faxfilename):
|
||||||
|
"""
|
||||||
|
Send a fax in a fax mode connection.
|
||||||
|
|
||||||
|
This command sends an analog fax (fax group 3). It starts the
|
||||||
|
send and waits for the end of the connection. So it should be
|
||||||
|
the last command before disconnect().
|
||||||
|
|
||||||
|
The connction must be in fax mode (use capi.call_faxG3() or
|
||||||
|
call.switch_to_faxG3()), otherwise an exception will be caused.
|
||||||
|
|
||||||
|
The file to be sent must be in the Structured Fax File (SFF)
|
||||||
|
format.
|
||||||
|
|
||||||
|
faxfilename: file to send
|
||||||
|
"""
|
||||||
|
capisuite.fax_send(self._handle, faxfilename)
|
||||||
|
|
||||||
|
|
||||||
|
def fax_receive(self, filename):
|
||||||
|
"""
|
||||||
|
Receive a fax in a fax mode connection.
|
||||||
|
|
||||||
|
This command receives an analog fax (fax group 3). It starts
|
||||||
|
the reception and waits for the end of the connection. So it
|
||||||
|
should be the last command before disconnect().
|
||||||
|
|
||||||
|
The connction must be in fax mode (use capi.call_faxG3() or
|
||||||
|
call.switch_to_faxG3()), otherwise an exception will be caused.
|
||||||
|
|
||||||
|
The created file will be saved in the Structured Fax File
|
||||||
|
(SFF) format.
|
||||||
|
|
||||||
|
filename: where to save the received fax.
|
||||||
|
"""
|
||||||
|
_capisuite.fax_receive(self._handle, filename)
|
||||||
|
|
||||||
|
|
||||||
|
class FaxInfo:
|
||||||
|
def __init__(self, stationID='', rate=0, hiRes=0, format=0, numPages=0):
|
||||||
|
self.stationID = stationID
|
||||||
|
self.bitRate = rate
|
||||||
|
self.hiRes = hiRes
|
||||||
|
self.resolution = hiRes and "hiRes" or "loRes"
|
||||||
|
# cff: color fax; sff: normal black-and-white fax
|
||||||
|
self.format = format and 'cff' or 'sff'
|
||||||
|
self.color = format and 'color' or 'b&w'
|
||||||
|
self.numPages = numPages
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
d = {}
|
||||||
|
for a in ('stationID', 'bitRate', 'resolution',
|
||||||
|
'hiRes', 'format', 'color', 'numPages'):
|
||||||
|
d[a] = getattr(self, a)
|
||||||
|
return d
|
||||||
|
|
||||||
|
# implemented in _capisuite:
|
||||||
|
#
|
||||||
|
#def error(...):
|
||||||
|
# pass
|
||||||
|
#def log(...):
|
||||||
|
# pass
|
|
@ -0,0 +1,34 @@
|
||||||
|
"""
|
||||||
|
Exceptions hierarchy for capisuite
|
||||||
|
|
||||||
|
Exception
|
||||||
|
+ MissingConfigEntry
|
||||||
|
+ FaxError
|
||||||
|
+ JobError
|
||||||
|
+ InvalidJob
|
||||||
|
+ JobLockedError
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Error(Exception): pass
|
||||||
|
class FaxError(Exception): pass
|
||||||
|
class VoiceError(Exception): pass
|
||||||
|
|
||||||
|
class JobError(Error):
|
||||||
|
# todo: distinguish fax/voice
|
||||||
|
def __init__(self, jobnum, jobfile):
|
||||||
|
Error.__init__(self)
|
||||||
|
self.jobnum = jobnum
|
||||||
|
self.jobfile = jobfile
|
||||||
|
|
||||||
|
class JobLockedError(JobError): pass
|
||||||
|
class InvalidJob(JobError): pass
|
||||||
|
|
||||||
|
from ConfigParser import NoOptionError, NoSectionError, Error
|
||||||
|
|
||||||
|
class NoGlobalSectionError(NoSectionError):
|
||||||
|
"""Raised when the GLOBAL section is missing
|
||||||
|
in a configuration file."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
Error.__init__(self, "Invalid config file: section GLOBAL missing")
|
||||||
|
self.section = 'GLOBAL'
|
|
@ -0,0 +1,252 @@
|
||||||
|
"""capisuite.fax
|
||||||
|
|
||||||
|
Module for fax interfacing of capisuite.
|
||||||
|
|
||||||
|
Most functions deal about creating and manipulationg job control
|
||||||
|
files. To actually send the fax out, call sendfax(). This is normaly
|
||||||
|
done by the idle-script.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
||||||
|
__copyright__ = "Copyright (c) 2004 by Hartmut Goebel"
|
||||||
|
__version__ = "$Revision: 0.0 $"
|
||||||
|
__credits__ = "This part of www.capisuite.de; thanks to Gernot Hiller"
|
||||||
|
|
||||||
|
import os, os.path, time, re, errno
|
||||||
|
from types import ListType, TupleType
|
||||||
|
|
||||||
|
# capisuite stuff
|
||||||
|
import fileutils
|
||||||
|
from capisuite.config import JobDescription, createDescriptionFor
|
||||||
|
from capisuite.exceptions import InvalidJob, JobLockedError
|
||||||
|
from capisuite.consts import *
|
||||||
|
|
||||||
|
_job_pattern = re.compile("fax-([0-9]+)\.txt")
|
||||||
|
|
||||||
|
###---- Utility functions ---###
|
||||||
|
|
||||||
|
def _userQ(config, user, Q):
|
||||||
|
userdir= config.get('GLOBAL', "fax_user_dir")
|
||||||
|
# todo: enable this, iff using config.getUser()
|
||||||
|
#if not userdir:
|
||||||
|
# raise NoOptionError('', 'fax_user_dir')
|
||||||
|
return os.path.abspath(os.path.join(userdir, user, Q))
|
||||||
|
|
||||||
|
|
||||||
|
###---- Job handling ---###
|
||||||
|
|
||||||
|
def _createSendJob(user, filename, **controlinfo):
|
||||||
|
"""
|
||||||
|
Create a control file for a fax to be send. The control file is
|
||||||
|
written to the same directory as the filename.
|
||||||
|
|
||||||
|
NB: This function does not care about the control information to
|
||||||
|
be written to the controlfile. This is to keep the definition of
|
||||||
|
what is required for sending the fax out of here. It's up to the
|
||||||
|
application layer to ensure correct parameters.
|
||||||
|
"""
|
||||||
|
controlfile = createDescriptionFor(filename, **controlinfo)
|
||||||
|
fileutils._setProtection(user, 0600, filename, controlfile)
|
||||||
|
|
||||||
|
|
||||||
|
def createReceivedJob(user, filename, call_from, call_to, causes, **kwargs):
|
||||||
|
"""
|
||||||
|
Create a file description for a received fax. The description file
|
||||||
|
is written to the same directory as the filename.
|
||||||
|
"""
|
||||||
|
controlinfo = {
|
||||||
|
'call_from': call_from,
|
||||||
|
'call_to': call_to,
|
||||||
|
'time': time.ctime(),
|
||||||
|
'cause': "0x%x/0x%x" % causes
|
||||||
|
}
|
||||||
|
controlinfo.update(kwargs)
|
||||||
|
controlfile = createDescriptionFor(filename, **controlinfo)
|
||||||
|
fileutils._setProtection(user, 0600, filename, controlfile)
|
||||||
|
|
||||||
|
|
||||||
|
def enqueueJob(config, user, infiles, converter, **controlinfo):
|
||||||
|
# todo: enable color-suffixes
|
||||||
|
"""
|
||||||
|
Enqueue a file into the fax send queue.
|
||||||
|
|
||||||
|
This sets the spool-filename and calls 'converter(infile,
|
||||||
|
spoolfile)' to convert the infile into a faxfile. The later has to
|
||||||
|
be written tp 'spoolfile'. If the conversion succeeds, the
|
||||||
|
appropriate job controlfile is written .
|
||||||
|
|
||||||
|
NB: This function does not care about the control information to
|
||||||
|
be written to the controlfile. This is to keep the definition of
|
||||||
|
what is required for sending the fax out of here. It's up to the
|
||||||
|
application layer to ensure correct parameters.
|
||||||
|
|
||||||
|
@param user
|
||||||
|
@param infile
|
||||||
|
@param converter a function for converting the infile into a fax file
|
||||||
|
(will be called covnerter(infile, faxfile)
|
||||||
|
@controlinfo the fax job description
|
||||||
|
"""
|
||||||
|
assert isinstance(infiles, (ListType, TupleType))
|
||||||
|
# ensure some required entries (which may have defaults) exist
|
||||||
|
if not controlinfo.has_key('tries'):
|
||||||
|
controlinfo['tries'] = 0
|
||||||
|
if not controlinfo.has_key('starttime'):
|
||||||
|
controlinfo['starttime'] = time.ctime(time.time())
|
||||||
|
|
||||||
|
sendQ = _userQ(config, user, SEND_Q)
|
||||||
|
jobnum, faxname = fileutils.uniqueName(sendQ, "fax", "sff")
|
||||||
|
converter(infiles, faxname)
|
||||||
|
_createSendJob(user, faxname, **controlinfo)
|
||||||
|
return jobnum
|
||||||
|
|
||||||
|
|
||||||
|
def moveJob(controlfile, newdir, user=None):
|
||||||
|
# todo: important: update 'filenmae' in job description!
|
||||||
|
control = JobDescription(controlfile)
|
||||||
|
filename = control.get('filename')
|
||||||
|
cname = os.path.split(controlfile)[1]
|
||||||
|
fname = os.path.split(filename)[1]
|
||||||
|
if not user:
|
||||||
|
cname = os.path.join(newdir, cname)
|
||||||
|
fname = os.path.join(newdir, fname)
|
||||||
|
else:
|
||||||
|
cname = os.path.join(newdir, "%s-%s" % (user, cname))
|
||||||
|
fname = os.path.join(newdir, "%s-%s" % (user, fname))
|
||||||
|
|
||||||
|
# move controlfile to keep owner and protection!
|
||||||
|
os.rename(controlfile, cname)
|
||||||
|
os.rename(filename, fname)
|
||||||
|
# update controlfile
|
||||||
|
control.set('filename', fname)
|
||||||
|
control.write(open(cname, 'w'))
|
||||||
|
|
||||||
|
return control
|
||||||
|
|
||||||
|
|
||||||
|
def abortJob(controlfile):
|
||||||
|
"""
|
||||||
|
Abort a fax job defined by it's controlfile.
|
||||||
|
|
||||||
|
This will remove the job from respective queue and delete both the
|
||||||
|
controlfile and the file defined in the controlfile.
|
||||||
|
"""
|
||||||
|
# todo: security: May this be missused for deleting other users files?
|
||||||
|
# todo: security: should ensure controlfile and filename are in the same
|
||||||
|
# directory
|
||||||
|
lockname = fileutils.lockname(controlfile)
|
||||||
|
if not os.access(controlfile, os.W_OK):
|
||||||
|
raise InvalidJob(None, controlfile)
|
||||||
|
try:
|
||||||
|
lock = fileutils._getLock(lockname, blocking=0)
|
||||||
|
except IOError, err:
|
||||||
|
if err.errno in (errno.EACCES, errno.EAGAIN):
|
||||||
|
raise JobLockedError(None, controlfile)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
control = JobDescription(controlfile)
|
||||||
|
filename = control.get('filename')
|
||||||
|
os.unlink(filename)
|
||||||
|
os.unlink(controlfile)
|
||||||
|
finally:
|
||||||
|
fileutils._releaseLock(lock)
|
||||||
|
|
||||||
|
|
||||||
|
def abortUserJob(config, user, jobnum):
|
||||||
|
"""
|
||||||
|
Abort a fax send job defined by username and job number.
|
||||||
|
|
||||||
|
This will remove the job from respective queue and delete both the
|
||||||
|
controlfile and the file defined in the controlfile.
|
||||||
|
"""
|
||||||
|
sendQ = _userQ(config, user, SEND_Q)
|
||||||
|
controlfile = fileutils.controlname(os.path.join(sendQ,
|
||||||
|
"fax-%03i" % jobnum))
|
||||||
|
abortJob(controlfile)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###---- Queue handling ---###
|
||||||
|
|
||||||
|
def getQueueFiles(config, user):
|
||||||
|
"""
|
||||||
|
Generate a list of all fax jobs in the send queue.
|
||||||
|
|
||||||
|
Result is a list of (job-number, controlfile) tuples, where
|
||||||
|
'controlfile' is an absolut paht.
|
||||||
|
"""
|
||||||
|
sendQ = _userQ(config, user, SEND_Q)
|
||||||
|
for filename in os.listdir(sendQ):
|
||||||
|
m = _job_pattern.match(filename)
|
||||||
|
if m:
|
||||||
|
yield (int(m.group(1)), # job number
|
||||||
|
os.path.join(sendQ, filename))
|
||||||
|
|
||||||
|
def getQueue(config, user):
|
||||||
|
"""
|
||||||
|
Generate a list of all fax entries in the send queue.
|
||||||
|
|
||||||
|
Result is a list of (job-number, description) tuples, where
|
||||||
|
'description' is the content of the job's controlfile as a
|
||||||
|
dictionary.
|
||||||
|
"""
|
||||||
|
for num, controlfile in getQueueFiles(config, user):
|
||||||
|
jobDesc = JobDescription(controlfile).items()
|
||||||
|
yield (num, jobDesc)
|
||||||
|
|
||||||
|
|
||||||
|
def getQueueDetails(config, user):
|
||||||
|
"""
|
||||||
|
Return a list of interesting details about the fax jobs in the
|
||||||
|
send queue.
|
||||||
|
|
||||||
|
Result is a list of tuples of (job-num, addresse/dialstring,
|
||||||
|
tries, starttime, subject), where starttime it the time when the
|
||||||
|
next try for sending is undertaken and addresse/dialstring is the
|
||||||
|
adresses (if not empty) or the dialstring otherwise).
|
||||||
|
"""
|
||||||
|
jobs = []
|
||||||
|
for num, jobDesc in getQueue(config, user):
|
||||||
|
jobs.append( (
|
||||||
|
num,
|
||||||
|
jobDesc['addressee'] or jobDesc['dialstring'],
|
||||||
|
jobDesc['tries'],
|
||||||
|
jobDesc['starttime'],
|
||||||
|
jobDesc['subject'],
|
||||||
|
))
|
||||||
|
return jobs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###--- Send/Receive Fax ---###
|
||||||
|
|
||||||
|
def sendfax(config, user, capi, faxfile,
|
||||||
|
outgoing_num, dialstring, stationID=None, headline=None):
|
||||||
|
"""
|
||||||
|
Send a fax out via the capi.
|
||||||
|
"""
|
||||||
|
import capisuite.core as core
|
||||||
|
|
||||||
|
controller = config.getint('GLOBAL', "send_controller")
|
||||||
|
timeout = int(config.getUser(user, "outgoing_timeout"))
|
||||||
|
|
||||||
|
# get defaults for stationID and headline from config
|
||||||
|
if not stationID:
|
||||||
|
stationID = config.getUser(user, "fax_stationID")
|
||||||
|
if not stationID:
|
||||||
|
core.error("Warning: fax_stationID for user %s not set" %user)
|
||||||
|
if not headline:
|
||||||
|
headline = config.getUser(user, "fax_headline")
|
||||||
|
|
||||||
|
try:
|
||||||
|
call = core.call_faxG3(
|
||||||
|
capi, controller, outgoing_num,
|
||||||
|
dialstring, timeout, stationID, headline)
|
||||||
|
if call:
|
||||||
|
# an errror occured
|
||||||
|
return call
|
||||||
|
call.fax_send(faxfile)
|
||||||
|
return call.disconnect()
|
||||||
|
except core.CallGoneError:
|
||||||
|
return call.disconnect()
|
|
@ -0,0 +1,158 @@
|
||||||
|
"""capisuite.fileutils
|
||||||
|
|
||||||
|
File handling utility function.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
||||||
|
__copyright__ = "Copyright (c) 2004 by Hartmut Goebel"
|
||||||
|
__version__ = "$Revision: 0.0 $"
|
||||||
|
__credits__ = "This part of www.capisuite.de; some ideas taken from Gernot Hiller"
|
||||||
|
|
||||||
|
import fcntl, os, re, errno
|
||||||
|
|
||||||
|
from types import IntType
|
||||||
|
|
||||||
|
class UnknownUserError(KeyError): pass
|
||||||
|
class LockTakenError(Exception): pass
|
||||||
|
|
||||||
|
|
||||||
|
def lockname(path):
|
||||||
|
return "%s.lock" % os.path.splitext(path)[0]
|
||||||
|
def controlname(path):
|
||||||
|
return "%s.txt" % os.path.splitext(path)[0]
|
||||||
|
|
||||||
|
|
||||||
|
def _getLock(lockname_=None, forfile=None, blocking=0):
|
||||||
|
if forfile:
|
||||||
|
lockname_ = lockname(forfile)
|
||||||
|
elif not lockname_:
|
||||||
|
raise ValueError, lockname_
|
||||||
|
lockfile = open(lockname_, "w")
|
||||||
|
try:
|
||||||
|
if blocking:
|
||||||
|
fcntl.lockf(lockfile, fcntl.LOCK_EX)
|
||||||
|
else:
|
||||||
|
fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
|
except IOError, err: # can't get the lock
|
||||||
|
if err.errno in (errno.EACCES, errno.EAGAIN):
|
||||||
|
lockfile.close()
|
||||||
|
raise LockTakenError
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
return (lockname_, lockfile)
|
||||||
|
|
||||||
|
|
||||||
|
def _releaseLock((lockname, lockfile)):
|
||||||
|
fcntl.lockf(lockfile, fcntl.LOCK_UN)
|
||||||
|
lockfile.close()
|
||||||
|
try:
|
||||||
|
os.unlink(lockname)
|
||||||
|
except OSError, err:
|
||||||
|
# as we don't hold the lock any more, the other thread can be quicker
|
||||||
|
# in deleting than we; this doesn't harm, so ignore it
|
||||||
|
if (err.errno!=2):
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def _setProtection(user, mode=0600, *files):
|
||||||
|
import pwd
|
||||||
|
try:
|
||||||
|
userdata = pwd.getpwnam(user)
|
||||||
|
except KeyError:
|
||||||
|
raise UnknownUserError(user)
|
||||||
|
print files
|
||||||
|
if os.getuid() == 0:
|
||||||
|
# running as root, change ownership
|
||||||
|
for f in files:
|
||||||
|
os.chmod(f, mode)
|
||||||
|
os.chown(f, userdata.pw_uid, userdata.pw_gid)
|
||||||
|
else:
|
||||||
|
for f in files:
|
||||||
|
os.chmod(f, mode)
|
||||||
|
os.chown(f, os.getuid(), userdata.pw_gid)
|
||||||
|
|
||||||
|
|
||||||
|
def _mkuserdir(user, parrentdir, *dirs):
|
||||||
|
import pwd
|
||||||
|
try:
|
||||||
|
userdata = pwd.getpwnam(user)
|
||||||
|
except KeyError:
|
||||||
|
raise UnknownUserError(user)
|
||||||
|
path = parrentdir
|
||||||
|
for d in dirs:
|
||||||
|
path = os.path.join(path, d)
|
||||||
|
# todo: use os.path.exists?
|
||||||
|
if not os.access(path, os.F_OK):
|
||||||
|
os.mkdir(path, 0700)
|
||||||
|
os.chown(path, userdata.pw_uid, userdata.pw_gid)
|
||||||
|
return path
|
||||||
|
|
||||||
|
###--- counter files ---###
|
||||||
|
|
||||||
|
def readCounter(default=0, *fileparts):
|
||||||
|
assert isinstance(default, IntType)
|
||||||
|
filename = os.path.join(*fileparts)
|
||||||
|
if os.path.exists(filename):
|
||||||
|
lastfile = open(filename, "r")
|
||||||
|
count = int(lastfile.readline())
|
||||||
|
lastfile.close()
|
||||||
|
return count
|
||||||
|
else:
|
||||||
|
return default
|
||||||
|
|
||||||
|
def writeCounter(count, *fileparts):
|
||||||
|
assert isinstance(count, IntType)
|
||||||
|
filename = os.path.join(*fileparts)
|
||||||
|
lastfile = open(filename, "w")
|
||||||
|
print >> lastfile, count
|
||||||
|
lastfile.close()
|
||||||
|
|
||||||
|
|
||||||
|
###--- ... ---###
|
||||||
|
|
||||||
|
def __makeCountedFilePattern(basename, suffix):
|
||||||
|
# todo: group should be digits only
|
||||||
|
return re.compile("%s-([0-9]+)\.%s" % (re.escape(basename),
|
||||||
|
re.escape(suffix)))
|
||||||
|
|
||||||
|
# @brief thread-safe creation of a unique filename in a directory
|
||||||
|
#
|
||||||
|
# This function reads the nextnumber from then "nextnr"-file in the given
|
||||||
|
# directory and updates it. It holds the next free file number.
|
||||||
|
#
|
||||||
|
# If nextnr doesn't exist, it's created.
|
||||||
|
#
|
||||||
|
# The filenames created will have the format
|
||||||
|
#
|
||||||
|
# basename-number.suffix
|
||||||
|
#
|
||||||
|
# @param directory name of the directory to work in
|
||||||
|
# @param basename the basename of the filename
|
||||||
|
# @param suffix the suffix of the filename (without ".")
|
||||||
|
#
|
||||||
|
# @return job number, new file name
|
||||||
|
def uniqueName(directory, basename, suffix):
|
||||||
|
nextfile = "%s-nextnr" % os.path.join(directory, basename)
|
||||||
|
lock = _getLock(os.path.join(directory,"cs_lock"), blocking=1)
|
||||||
|
try:
|
||||||
|
nextnum = readCounter(-10, nextfile)
|
||||||
|
if nextnum < 0:
|
||||||
|
# search for next free sequence number
|
||||||
|
pattern = __makeCountedFilePattern(basename, suffix)
|
||||||
|
numbers = [0]
|
||||||
|
for f in os.listdir(directory):
|
||||||
|
m = pattern.match(f)
|
||||||
|
if m:
|
||||||
|
numbers.append(int(m.group(1)))
|
||||||
|
# take number of last file and increase it by one
|
||||||
|
nextnum = max(numbers)+1
|
||||||
|
writeCounter(nextnum+1, nextfile)
|
||||||
|
except:
|
||||||
|
_releaseLock(lock)
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
_releaseLock(lock)
|
||||||
|
newname = "%s-%03i.%s" % (os.path.join(directory,basename),
|
||||||
|
nextnum, suffix)
|
||||||
|
return nextnum, newname
|
|
@ -0,0 +1,216 @@
|
||||||
|
# -*- python -*-
|
||||||
|
# .pycheckrc file created by PyChecker v0.8.13 @ Wed Feb 25 14:03:29 2004
|
||||||
|
#
|
||||||
|
# It should be placed in your home directory (value of $HOME).
|
||||||
|
# If $HOME is not set, it will look in the current directory.
|
||||||
|
#
|
||||||
|
|
||||||
|
# unused imports
|
||||||
|
importUsed = 1
|
||||||
|
|
||||||
|
# unused imports from __init__.py
|
||||||
|
packageImportUsed = 1
|
||||||
|
|
||||||
|
# module imports itself
|
||||||
|
reimportSelf = 1
|
||||||
|
|
||||||
|
# reimporting a module
|
||||||
|
moduleImportErrors = 1
|
||||||
|
|
||||||
|
# module does import and from ... import
|
||||||
|
mixImport = 1
|
||||||
|
|
||||||
|
# unused local variables, except tuples
|
||||||
|
localVariablesUsed = 1
|
||||||
|
|
||||||
|
# all unused local variables, including tuples
|
||||||
|
unusedLocalTuple = 0
|
||||||
|
|
||||||
|
# all unused class data members
|
||||||
|
membersUsed = 0
|
||||||
|
|
||||||
|
# all unused module variables
|
||||||
|
allVariablesUsed = 0
|
||||||
|
|
||||||
|
# unused private module variables
|
||||||
|
privateVariableUsed = 1
|
||||||
|
|
||||||
|
# report each occurrence of global warnings
|
||||||
|
reportAllGlobals = 0
|
||||||
|
|
||||||
|
# functions called with named arguments (like keywords)
|
||||||
|
namedArgs = 0
|
||||||
|
|
||||||
|
# Attributes (members) must be defined in __init__()
|
||||||
|
onlyCheckInitForMembers = 0
|
||||||
|
|
||||||
|
# Subclass.__init__() not defined
|
||||||
|
initDefinedInSubclass = 0
|
||||||
|
|
||||||
|
# Baseclass.__init__() not called
|
||||||
|
baseClassInitted = 1
|
||||||
|
|
||||||
|
# Subclass needs to override methods that only throw exceptions
|
||||||
|
abstractClasses = 1
|
||||||
|
|
||||||
|
# Return None from __init__()
|
||||||
|
returnNoneFromInit = 1
|
||||||
|
|
||||||
|
# unreachable code
|
||||||
|
unreachableCode = 0
|
||||||
|
|
||||||
|
# a constant is used in a conditional statement
|
||||||
|
constantConditions = 1
|
||||||
|
|
||||||
|
# 1 is used in a conditional statement (if 1: or while 1:)
|
||||||
|
constant1 = 0
|
||||||
|
|
||||||
|
# check if iterating over a string
|
||||||
|
stringIteration = 1
|
||||||
|
|
||||||
|
# Calling data members as functions
|
||||||
|
callingAttribute = 0
|
||||||
|
|
||||||
|
# class attribute does not exist
|
||||||
|
classAttrExists = 1
|
||||||
|
|
||||||
|
# First argument to methods
|
||||||
|
methodArgName = 'self'
|
||||||
|
|
||||||
|
# First argument to classmethods
|
||||||
|
classmethodArgNames = ['cls', 'klass']
|
||||||
|
|
||||||
|
# unused method/function arguments
|
||||||
|
argumentsUsed = 1
|
||||||
|
|
||||||
|
# unused method/function variable arguments
|
||||||
|
varArgumentsUsed = 1
|
||||||
|
|
||||||
|
# ignore if self is unused in methods
|
||||||
|
ignoreSelfUnused = 0
|
||||||
|
|
||||||
|
# check if overridden methods have the same signature
|
||||||
|
checkOverridenMethods = 1
|
||||||
|
|
||||||
|
# check if __special__ methods exist and have the correct signature
|
||||||
|
checkSpecialMethods = 1
|
||||||
|
|
||||||
|
# check if function/class/method names are reused
|
||||||
|
redefiningFunction = 1
|
||||||
|
|
||||||
|
# check if using unary positive (+) which is usually meaningless
|
||||||
|
unaryPositive = 1
|
||||||
|
|
||||||
|
# check if modify (call method) on a parameter that has a default value
|
||||||
|
modifyDefaultValue = 1
|
||||||
|
|
||||||
|
# check if variables are set to different types
|
||||||
|
inconsistentTypes = 0
|
||||||
|
|
||||||
|
# check if unpacking a non-sequence
|
||||||
|
unpackNonSequence = 1
|
||||||
|
|
||||||
|
# check if unpacking sequence with the wrong length
|
||||||
|
unpackLength = 1
|
||||||
|
|
||||||
|
# check if raising or catching bad exceptions
|
||||||
|
badExceptions = 1
|
||||||
|
|
||||||
|
# check if statement appears to have no effect
|
||||||
|
noEffect = 1
|
||||||
|
|
||||||
|
# check if using (expr % 1), it has no effect on integers and strings
|
||||||
|
modulo1 = 1
|
||||||
|
|
||||||
|
# check if using (expr is const-literal), doesn't always work on integers and strings
|
||||||
|
isLiteral = 1
|
||||||
|
|
||||||
|
# check consistent return values
|
||||||
|
checkReturnValues = 1
|
||||||
|
|
||||||
|
# check if using implict and explicit return values
|
||||||
|
checkImplicitReturns = 1
|
||||||
|
|
||||||
|
# check that attributes of objects exist
|
||||||
|
checkObjectAttrs = 1
|
||||||
|
|
||||||
|
# various warnings about incorrect usage of __slots__
|
||||||
|
slots = 1
|
||||||
|
|
||||||
|
# using properties with classic classes
|
||||||
|
classicProperties = 1
|
||||||
|
|
||||||
|
# check if __slots__ is empty
|
||||||
|
emptySlots = 1
|
||||||
|
|
||||||
|
# check if using integer division
|
||||||
|
intDivide = 1
|
||||||
|
|
||||||
|
# check if local variable shadows a global
|
||||||
|
shadows = 1
|
||||||
|
|
||||||
|
# check if a variable shadows a builtin
|
||||||
|
shadowBuiltins = 1
|
||||||
|
|
||||||
|
# check if input() is used
|
||||||
|
usesInput = 1
|
||||||
|
|
||||||
|
# check if the exec statement is used
|
||||||
|
usesExec = 0
|
||||||
|
|
||||||
|
# ignore warnings from files under standard library
|
||||||
|
ignoreStandardLibrary = 0
|
||||||
|
|
||||||
|
# ignore warnings from the list of modules
|
||||||
|
blacklist = ['Tkinter', 'wxPython', 'gtk', 'GTK', 'GDK']
|
||||||
|
|
||||||
|
# ignore global variables not used if name is one of these values
|
||||||
|
variablesToIgnore = ['__version__', '__warningregistry__', '__all__',
|
||||||
|
'__credits__', '__test__', '__author__',
|
||||||
|
'__email__', '__revision__', '__copyright__']
|
||||||
|
|
||||||
|
# ignore unused locals/arguments if name is one of these values
|
||||||
|
unusedNames = ['_', 'empty', 'unused', 'dummy']
|
||||||
|
|
||||||
|
# ignore use of deprecated modules/functions
|
||||||
|
deprecated = 1
|
||||||
|
|
||||||
|
# maximum lines in a function
|
||||||
|
maxLines = 200
|
||||||
|
|
||||||
|
# maximum branches in a function
|
||||||
|
maxBranches = 50
|
||||||
|
|
||||||
|
# maximum returns in a function
|
||||||
|
maxReturns = 10
|
||||||
|
|
||||||
|
# maximum # of arguments to a function
|
||||||
|
maxArgs = 10
|
||||||
|
|
||||||
|
# maximum # of locals in a function
|
||||||
|
maxLocals = 40
|
||||||
|
|
||||||
|
# maximum # of identifier references (Law of Demeter)
|
||||||
|
maxReferences = 5
|
||||||
|
|
||||||
|
# no module doc strings
|
||||||
|
noDocModule = 0
|
||||||
|
|
||||||
|
# no class doc strings
|
||||||
|
noDocClass = 0
|
||||||
|
|
||||||
|
# no function/method doc strings
|
||||||
|
noDocFunc = 0
|
||||||
|
|
||||||
|
# print internal checker parse structures
|
||||||
|
printParse = 0
|
||||||
|
|
||||||
|
# turn on debugging for checker
|
||||||
|
debug = 0
|
||||||
|
|
||||||
|
# { 'module1': 'no-namedargs maxlines=0',
|
||||||
|
# 'module2.my_func': 'argsused',
|
||||||
|
# 'module3.my_class': 'no-initreturn', }
|
||||||
|
suppressions = {
|
||||||
|
'config.NoGlobalSectionError.__init__': 'no-callinit',
|
||||||
|
}
|
|
@ -0,0 +1,176 @@
|
||||||
|
"""capisuite.voice
|
||||||
|
|
||||||
|
Module for voice interfacing and interactions of capisuite.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
||||||
|
__copyright__ = "Copyright (c) 2004 by Hartmut Goebel"
|
||||||
|
__version__ = "$Revision: 0.0 $"
|
||||||
|
__credits__ = "This part of www.capisuite.de; thanks to Gernot Hiller"
|
||||||
|
|
||||||
|
import os, re, errno
|
||||||
|
|
||||||
|
# capisuite stuff
|
||||||
|
import fileutils
|
||||||
|
from capisuite.config import JobDescription, createDescriptionFor
|
||||||
|
from capisuite.exceptions import InvalidJob, JobLockedError
|
||||||
|
#from capisuite.consts import *
|
||||||
|
|
||||||
|
_job_pattern = re.compile("voice-([0-9]+)\.txt")
|
||||||
|
_la_pattern = re.compile("voice-([0-9]+)\.la")
|
||||||
|
|
||||||
|
|
||||||
|
def _userQ(config, user, Q):
|
||||||
|
userdir= config.get('GLOBAL', "voice_user_dir")
|
||||||
|
# todo: enable this, iff using config.getUser()
|
||||||
|
#if not userdir:
|
||||||
|
# raise NoOptionError('', 'fax_user_dir')
|
||||||
|
return os.path.abspath(os.path.join(userdir, user, Q))
|
||||||
|
|
||||||
|
|
||||||
|
def getAudio(config, user, filename):
|
||||||
|
"""
|
||||||
|
Search for an audio file first in user_dir, than in audio_dir
|
||||||
|
|
||||||
|
'config' is the ConfigParser object containing the configuration,
|
||||||
|
'user' the name of the user, 'filename' the filename of the wave
|
||||||
|
file.
|
||||||
|
|
||||||
|
Returns the found file with full path
|
||||||
|
"""
|
||||||
|
|
||||||
|
userdir = config.get('GLOBAL', "voice_user_dir")
|
||||||
|
userdir = os.path.join(userdir, user)
|
||||||
|
if config.has_option('GLOBAL', "user_audio_files") and \
|
||||||
|
config.getboolean('GLOBAL', "user_audio_files") and \
|
||||||
|
os.access(os.path.join(userdir, filename),os.R_OK):
|
||||||
|
return os.path.join(userdir, filename)
|
||||||
|
else:
|
||||||
|
systemdir = config.get('GLOBAL', "audio_dir")
|
||||||
|
return os.path.join(systemdir, filename)
|
||||||
|
|
||||||
|
|
||||||
|
def getNumberFiles(number, gender="-"):
|
||||||
|
number = str(number)
|
||||||
|
if number == "-" or number == "??":
|
||||||
|
# "??" is needed for backward compatibility to versions <= 0.4.1a
|
||||||
|
yield 'unbekannt'
|
||||||
|
elif gender != "-" and number in ("1", "01"):
|
||||||
|
if gender in ("n", "m"):
|
||||||
|
yield 'ein'
|
||||||
|
else:
|
||||||
|
yield 'eine'
|
||||||
|
elif len(number) == 2 and number[0] != "0":
|
||||||
|
digit10, digit01 = number
|
||||||
|
if digit10 == "1" or digit01 == "0":
|
||||||
|
# for 10, 11...19, 20, 30, ... we have seperate voice files
|
||||||
|
yield number
|
||||||
|
else:
|
||||||
|
if digit01 == "1":
|
||||||
|
yield 'ein'
|
||||||
|
else:
|
||||||
|
yield digit01
|
||||||
|
yield 'und'
|
||||||
|
yield '%s0' % digit10
|
||||||
|
else:
|
||||||
|
for digit in list(number):
|
||||||
|
yield digit
|
||||||
|
|
||||||
|
|
||||||
|
# @brief say a german number
|
||||||
|
#
|
||||||
|
# All numbers from 0 to 99 are said correctly, while all larger ones are
|
||||||
|
# split into numbers and only the numbers are said one after another.
|
||||||
|
# An input of "-" produces the word "unbekannt" (unknown)
|
||||||
|
#
|
||||||
|
# @param call reference to the call
|
||||||
|
# @param number the number to say
|
||||||
|
# @param curr_user the current user named
|
||||||
|
# @param config the ConfigParser instance holding the configuration info
|
||||||
|
# @param gender if the number is used in connection with a singular noun ("f" --> "eine Nachricht")
|
||||||
|
def sayNumber(config, user, call, number, gender="-"):
|
||||||
|
for f in getNumberFiles(number, gender=gender):
|
||||||
|
say(config, user, call, "%s.la" % f)
|
||||||
|
|
||||||
|
def say(config, user, call, *files):
|
||||||
|
for f in files:
|
||||||
|
call.audio_send(getAudio(config, user, f),1)
|
||||||
|
|
||||||
|
|
||||||
|
###---- Queue handling ---###
|
||||||
|
|
||||||
|
def getInquiryCounter(config, user):
|
||||||
|
return fileutils.readCounter(-1,
|
||||||
|
_userQ(config, user, "received"),
|
||||||
|
"last_inquiry")
|
||||||
|
|
||||||
|
def setInquiryCounter(config, user, count):
|
||||||
|
return fileutils.writeCounter(count,
|
||||||
|
_userQ(config, user, "received"),
|
||||||
|
"last_inquiry")
|
||||||
|
|
||||||
|
|
||||||
|
def getQueueFiles(config, user):
|
||||||
|
"""
|
||||||
|
Generated a list of all Queue files, where each entry consists of
|
||||||
|
a tuple (job-number, filename).
|
||||||
|
|
||||||
|
filename is an absolute path
|
||||||
|
|
||||||
|
"""
|
||||||
|
receivedQ = _userQ(config, user, "received")
|
||||||
|
for filename in os.listdir(receivedQ):
|
||||||
|
m = _job_pattern.match(filename)
|
||||||
|
if m:
|
||||||
|
yield (m.group(1), # job number
|
||||||
|
filename)
|
||||||
|
|
||||||
|
|
||||||
|
def abortJob(controlfile):
|
||||||
|
"""
|
||||||
|
Abort a fax job defined by it's controlfile.
|
||||||
|
|
||||||
|
This will remove the job from respective queue and delete both the
|
||||||
|
controlfile and the file defined in the controlfile.
|
||||||
|
"""
|
||||||
|
# todo: security: May this be missused for deleting other users files?
|
||||||
|
# todo: security: should ensure controlfile and filename are in the same
|
||||||
|
# directory
|
||||||
|
lockname = fileutils.lockname(controlfile)
|
||||||
|
if not os.access(controlfile, os.W_OK):
|
||||||
|
raise InvalidJob(None, controlfile)
|
||||||
|
try:
|
||||||
|
lock = fileutils._getLock(lockname, blocking=0)
|
||||||
|
except IOError, err:
|
||||||
|
if err.errno in (errno.EACCES, errno.EAGAIN):
|
||||||
|
raise JobLockedError(None, controlfile)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
control = JobDescription(controlfile)
|
||||||
|
filename = control.get('filename')
|
||||||
|
os.unlink(filename)
|
||||||
|
os.unlink(controlfile)
|
||||||
|
finally:
|
||||||
|
fileutils._releaseLock(lock)
|
||||||
|
|
||||||
|
|
||||||
|
def createReceivedJob(user, filename, call_from, call_to, causes):
|
||||||
|
"""
|
||||||
|
Create a file description for a received fax. The description file
|
||||||
|
is written to the same directory as the filename.
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
control = {
|
||||||
|
'call_from': call_from,
|
||||||
|
'call_to': call_to,
|
||||||
|
'date': time.ctime(),
|
||||||
|
'cause': "0x%x/0x%x" % causes,
|
||||||
|
# we return this dict, thus set the filename here, too
|
||||||
|
'filename': filename,
|
||||||
|
}
|
||||||
|
controlfile = createDescriptionFor(**control)
|
||||||
|
fileutils._setProtection(user, 0600, filename, controlfile)
|
||||||
|
return control
|
|
@ -1,4 +1,4 @@
|
||||||
# Makefile.in generated by automake 1.8.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.1 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
@ -46,9 +46,9 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
CONFIG_HEADER = $(top_builddir)/config.h
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
CONFIG_CLEAN_FILES =
|
CONFIG_CLEAN_FILES =
|
||||||
|
LIBRARIES = $(noinst_LIBRARIES)
|
||||||
AR = ar
|
AR = ar
|
||||||
ARFLAGS = cru
|
ARFLAGS = cru
|
||||||
LIBRARIES = $(noinst_LIBRARIES)
|
|
||||||
libccmodules_a_AR = $(AR) $(ARFLAGS)
|
libccmodules_a_AR = $(AR) $(ARFLAGS)
|
||||||
libccmodules_a_LIBADD =
|
libccmodules_a_LIBADD =
|
||||||
am_libccmodules_a_OBJECTS = audiosend.$(OBJEXT) callmodule.$(OBJEXT) \
|
am_libccmodules_a_OBJECTS = audiosend.$(OBJEXT) callmodule.$(OBJEXT) \
|
||||||
|
@ -60,14 +60,6 @@ libccmodules_a_OBJECTS = $(am_libccmodules_a_OBJECTS)
|
||||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||||
am__depfiles_maybe = depfiles
|
am__depfiles_maybe = depfiles
|
||||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/audioreceive.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/audiosend.Po ./$(DEPDIR)/callmodule.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/calloutgoing.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/connectmodule.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/disconnectmodule.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/faxreceive.Po ./$(DEPDIR)/faxsend.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/readDTMF.Po \
|
|
||||||
@AMDEP_TRUE@ ./$(DEPDIR)/switch2faxG3.Po
|
|
||||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||||
CXXLD = $(CXX)
|
CXXLD = $(CXX)
|
||||||
|
@ -144,6 +136,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
am__leading_dot = @am__leading_dot@
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
bindir = @bindir@
|
bindir = @bindir@
|
||||||
build_alias = @build_alias@
|
build_alias = @build_alias@
|
||||||
datadir = @datadir@
|
datadir = @datadir@
|
||||||
|
@ -247,16 +241,14 @@ distclean-compile:
|
||||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
.cpp.obj:
|
.cpp.obj:
|
||||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
uninstall-info-am:
|
uninstall-info-am:
|
||||||
|
|
||||||
|
@ -280,9 +272,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
done | \
|
done | \
|
||||||
$(AWK) ' { files[$$0] = 1; } \
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
END { for (i in files) print i; }'`; \
|
END { for (i in files) print i; }'`; \
|
||||||
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||||
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
$$tags $$unique
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$tags $$unique; \
|
||||||
|
fi
|
||||||
ctags: CTAGS
|
ctags: CTAGS
|
||||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
|
@ -356,7 +350,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# -*- python -*-
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
libmodules = env.StaticLibrary('ccmodules', source = Split("""
|
||||||
|
audiosend.cpp callmodule.cpp audioreceive.cpp faxreceive.cpp
|
||||||
|
connectmodule.cpp switch2faxG3.cpp readDTMF.cpp calloutgoing.cpp
|
||||||
|
disconnectmodule.cpp faxsend.cpp
|
||||||
|
"""))
|
||||||
|
|
||||||
|
Return('libmodules')
|
Loading…
Reference in New Issue